Top Banner
ARCHITECTING WELL-STRUCTURED JAVA APPLICATIONS Eduards Sizovs @eduardsi
67

JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

Aug 10, 2015

Download

Technology

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

ARCHITECTING WELL-STRUCTURED JAVAAPPLICATIONS

Eduards Sizovs

@eduardsi

Page 2: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

MOST APPS BEGIN LIFE SMALL AND NEAT.

Page 3: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

TIME GOES BY...

Page 4: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

HELLO. I AM YOUR ROTTING ENTERPRISE APP.

Page 5: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

- RIGIDITY

- FRAGILITY

- IMMOBILITY

- VISCOSITY

- OPACITY

- NEEDLESS COMPLEXITY

- NEEDLESS REPITITION

SMELLING SYMPTOMS ->

Page 6: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

HIBERNATE CORE V4.3.8.FINAL

Page 7: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

JDK V1.7.0_51

Page 8: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

A JDK CODE BASE IS DEEPLY INTERCONNECTED AT BOTH THE API AND THEIMPLEMENTATION LEVELS, HAVING BEEN BUILT OVER MANY YEARS

PRIMARILY IN THE STYLE OF A MONOLITHIC SOFTWARE SYSTEM. WE’VESPENT CONSIDERABLE EFFORT ELIMINATING OR AT LEAST SIMPLIFYING AS

MANY API AND IMPLEMENTATION DEPENDENCES AS POSSIBLE, SO THATBOTH THE PLATFORM AND ITS IMPLEMENTATIONS CAN BE PRESENTED AS A

COHERENT SET OF INTERDEPENDENT MODULES, BUT SOME PARTICULARLYTHORNY CASES REMAIN.

(C) MARK REINHOLDS, CHIEF ARCHITECT OF THE JAVA PLATFORM

Page 9: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

SPRING V4.1.6

Page 10: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

PRINCIPLES.

Page 11: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

PACKAGE IS THE FIRST-CLASS CITIZEN ANDKEY ELEMENT OF LOGICAL DESIGN.

Page 12: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

TREAT PACKAGES AS A HIERARCHY EVEN IFTHEY’RE REPRESENTED FLAT.

Page 13: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.userio.shwitter.user.registrationio.shwitter.user.profileio.shwitter.timeline

 

Page 14: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.user (part of)io.shwitter.user.registrationio.shwitter.user.profileio.shwitter.timeline

 

Page 15: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.userio.shwitter.user.registration (part of)io.shwitter.user.profile io.shwitter.timeline

 

Page 16: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.userio.shwitter.user.registrationio.shwitter.user.profile (part of)io.shwitter.timeline

 

Page 17: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.userio.shwitter.user.registrationio.shwitter.user.profileio.shwitter.timeline (part of)

 

Page 18: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

USE PACKAGES TO GROUP FUNCTIONALLY-RELATED ARTIFACTS. DO NOT GROUPARTIFACTS THAT DO THE SAME THING, BUTARE DIFFERENT BY NATURE.

Page 19: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.controllerio.shwitter.daoio.shwitter.domainio.shwitter.servicesio.shwitter.exceptions

Page 20: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.controllerio.shwitter.daoio.shwitter.domainio.shwitter.servicesio.shwitter.exceptions

UserController, TimelineController...

 

Page 21: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.controllerio.shwitter.daoio.shwitter.domainio.shwitter.servicesio.shwitter.exceptions

UserDAO, TimelineDAO...

 

Page 22: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.controllerio.shwitter.daoio.shwitter.domainio.shwitter.servicesio.shwitter.exceptions

User, Timeline...

 

Page 23: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.controllerio.shwitter.daoio.shwitter.domainio.shwitter.servicesio.shwitter.exceptions

RegistrationService, TimelineService...

 

Page 24: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.controllerio.shwitter.daoio.shwitter.domainio.shwitter.servicesio.shwitter.exceptions

 

Page 25: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.controllerio.shwitter.daoio.shwitter.domainio.shwitter.servicesio.shwitter.exceptions

io.shwitter.userio.shwitter.user.registrationio.shwitter.user.profileio.shwitter.timeline

Page 26: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

io.shwitter.controllerio.shwitter.daoio.shwitter.domainio.shwitter.servicesio.shwitter.exceptions

io.shwitter.userio.shwitter.user.registrationio.shwitter.user.profileio.shwitter.timeline

User, UserDAO, UserController...

 

Page 27: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

GROUP TIGHTLY COUPLED CLASSESTOGETHER. IF CLASSES THAT CHANGETOGETHER ARE IN THE SAME PACKAGE, THENTHE IMPACT OF CHANGE IS LOCALIZED.

- THE COMMON CLOSURE PRINCIPLE

Page 28: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

MAKE SURE ARTIFACTS DO NOT ESCAPE.

Page 29: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

MAKE PACKAGES HIGHLY COHESIVE BYFOLLOWING SINGLE RESPONSIBILITYPRINCIPLE.

Page 30: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

KEEP PACKAGES LOOSELY COUPLED, IDEALLY– COMPLETELY INDEPENDENT. REFLECTIONDOESN’T COUNT.

Page 31: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

package io.shwitter.user

@Entity class User { // name, password etc. }

package io.shwitter.timeline

@Entity class Timeline { @OneToOne User user; }

Page 32: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

package io.shwitter.user

@Embeddable class UserId { Long value; }

package io.shwitter.timeline

@Entity class Timeline { @Embedded UserId userId; }

Page 33: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

PROVIDE SLIM PACKAGE INTERFACE AND HIDEIMPLEMENTATION DETAILS.

Page 34: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

AVOID DEPENDENCY MAGNETS. SOMETIMESDUPLICATION IS NOT THAT EVIL.

Page 35: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

MANAGE RELATIONSHIPS. EVERYDEPENDENCY ARROW HAS A REASON.

Page 36: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

FINDBUGS V1.0 - A GREAT START

Page 37: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

FINDBUGS V1.1 – IMPERFECTION CREEPS IN

Page 38: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

FINDBUGS V1.2 – IMPERFECTION TAKES HOLD

Page 39: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

FINDBUGS V1.3 – CHAOS BEGINS

Page 40: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

FINDBUGS V1.4 – EXPLOSION

Page 41: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

THE DEPENDENCIES BETWEEN PACKAGESMUST NOT FORM CYCLES. BURN BI-DIRECTIONAL DEPENDENCES IN FIRE.

Page 42: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

HOW?

Page 43: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

MERGING

package io.shwitter.userclass User { void register(RegistrationNotifier notifier) {}}

package io.shwitter.user.notifyclass RegistrationNotifier { void notify(User user) {}}

Page 44: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

MERGING - REPACKAGING

package io.shwitter.userclass User { void register(RegistrationNotifier notifier) {}}

class RegistrationNotifier { void notify(User user) {}}

Page 45: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

DEPENDENCY INVERSION

package io.shwitter.userclass User { void register(RegistrationNotifier notifier) {}}

package io.shwitter.user.notifyclass RegistrationNotifier { void notify(User user) {}}

Page 46: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

DEPENDENCY INVERSION - REFACTORING STEP 1

package io.shwitter.userclass User { void register(RegistrationNotifier notifier) {}}

package io.shwitter.user.notifyclass RegistrationNotifier implements UserNotifier { void notify(User user) {}}interface UserNotifier { void notify(User user) {} }

Page 47: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

DEPENDENCY INVERSION - REFACTORING STEP 2

package io.shwitter.userclass User { void register(UserNotifier notifier) {}}

package io.shwitter.user.notifyclass RegistrationNotifier implements UserNotifier { void notify(User user) {}}interface UserNotifier { void notify(User user) {} }

Page 48: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

DEPENDENCY INVERSION - REFACTORING STEP 3

package io.shwitter.userclass User { void register(UserNotifier notifier) {}}interface UserNotifier { void notify(User user) {} }

package io.shwitter.user.notifyclass RegistrationNotifier implements UserNotifier { void notify(User user) {}}

Page 49: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

ESCALATION

package io.shwitter.userclass User { void register(Notifier n) { n.notify(this); }}

package io.shwitter.user.notifyclass Notifier { void notify(User user) { sendEmailTo(user.email()); }}

Page 50: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

ESCALATION - REFACTORING STEP 1

package io.shwitter.userclass User { void register(Notifier n) { n.notify(this); }}

package io.shwitter.user.notifyclass Notifier { void notify(User user) { sendEmailTo(user.email()); }}

package io.shwitter.user.registrationclass Registrator { void register(User user, Notifier n) {}}

Page 51: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

ESCALATION - REFACTORING STEP 2

package io.shwitter.userclass User { void register() { }}

package io.shwitter.user.notifyclass Notifier { void notify(User user) { sendEmailTo(user.email()); }}

package io.shwitter.user.registrationclass Registrator { void register(User user, Notifier n) { n.notify(user); }}

Page 52: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

ESCALATION - REFACTORING STEP 3

package io.shwitter.userclass User { void register() { }}

package io.shwitter.user.notifyclass Notifier { void notify(String emailAddress) { sendEmailTo(emailAddress); }}

package io.shwitter.user.registrationclass Registrator { void register(User user, Notifier n) { n.notify(user.email()); }}

Page 53: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

DEMOTION

package io.shwitter.userclass User { void register(Notifier n) { n.notify(this); }}

package io.shwitter.user.notifyclass Notifier { void notify(User user) { sendEmailTo(user.email()); }}

Page 54: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

DEMOTION - REFACTORING STEP 1

package io.shwitter.userclass User implements EmailHolder { void register(Notifier n) { n.notify(this); }}

package io.shwitter.user.notifyclass Notifier { void notify(User user) { sendEmailTo(user.email()); }}

package io.shwitter.emailerinterface EmailHolder { String email();}

Page 55: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

DEMOTION - REFACTORING STEP 2

package io.shwitter.userclass User implements EmailHolder { void register(Notifier n) { n.notify(this); }}

package io.shwitter.user.notifyclass Notifier { void notify(EmailHolder emailHolder) { sendEmailTo(emailHolder.email()); }}

package io.shwitter.emailerinterface EmailHolder { String email();}

Page 56: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

TOOLS

Page 57: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs
Page 58: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

MACKER EXAMPLE

<?xml version="1.0"?><macker> <ruleset name="Simple example"> <access-rule> <deny> <from class="**Print*" /> <to class="java.**" /> </deny> </access-rule> </ruleset></macker>

Page 59: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs
Page 60: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

CLASSYCLE EXAMPLE

## This is an example of a dependency definition file#show allResults

{package} = classycle

[util] = ${package}.util.*[non-util] = ${package}.* excluding [util][class-file] = ${package}.classfile.*

check sets [util] [non-util] [class-file]

check [util] independentOf [non-util]check [class-file] independentOf [util]

Page 61: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs
Page 62: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs
Page 63: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs
Page 64: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

OO Design Principles & Metrics, Jason Gorman http://goo.gl/RTW9GTThe Economics of Software Design, J.B. Rainsberger http://goo.gl/ra7Q8QSOLID Principles, Eduards Sizovs http://goo.gl/RpxavdDesigning Object-Oriented Software, Jouni Smed http://goo.gl/iyE1R2Grand Unified Theory Of Software Design, Jim Weirich http://goo.gl/ASqyAsFun With Modules, Kirk Knoernschild http://goo.gl/i8jx8YPatterns of Modular Architecture http://goo.gl/yFqmZOLet’s turn packages into a module system! http://goo.gl/Mzco8F

MORE

Page 65: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

EITHER YOU WORK TO CREATE ACOMPANY CULTURE OR YOU DON'T.EITHER WAY A CULTURE WILL EMERGE.

(C) MARTIN LINKHORST

Page 66: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

EITHER YOU WORK TO CREATE ASOFTWARE STRUCTURE OR YOU DON'T.EITHER WAY A STRUCTURE WILL EMERGE.

(C) EDUARDS SIZOVS

Page 67: JavaCro'15 - Architecting well-structured Java applications - Eduards Sizovs

THANK YOU