Architecting well-structured Java applications

Post on 06-Aug-2015

2.725 views 18 download

Transcript of Architecting well-structured Java applications

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 1/68

ARCHITECTING WELL-STRUCTURED JAVAAPPLICATIONS

Eduards Sizovs

@eduardsi

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 2/68

MOST APPS BEGIN LIFE SMALL AND NEAT.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 3/68

TIME GOES BY...

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 4/68

HELLO. I AM YOUR ROTTING ENTERPRISE APP.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 5/68

- RIGIDITY

- FRAGILITY

- IMMOBILITY

- VISCOSITY

- OPACITY

- NEEDLESS COMPLEXITY

- NEEDLESS REPITITION

SMELLING SYMPTOMS ->

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 6/68

HIBERNATE CORE V4.3.8.FINAL

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 7/68

JDK V1.7.0_51

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 8/68

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 9/68

SPRING V4.1.6

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 10/68

PRINCIPLES.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 11/68

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 12/68

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 13/68

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

 

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 14/68

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

 

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 15/68

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

 

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 16/68

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

 

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 17/68

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

 

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 18/68

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 19/68

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 20/68

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

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

 

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 21/68

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 22/68

- ABILITY TO DISTRIBUTE YOUR LAYERS OVER MULTIPLE PHYSICAL TIERS (HA-HA)

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 23/68

- ABILITY TO DISTRIBUTE YOUR LAYERS OVER MULTIPLE PHYSICAL TIERS (HA-HA)

- DECOUPLING / ABSTRACTING FOR EXHANGEABILITY (HA-HA)

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 24/68

- ABILITY TO DISTRIBUTE YOUR LAYERS OVER MULTIPLE PHYSICAL TIERS (HA-HA)

- DECOUPLING / ABSTRACTING FOR EXHANGEABILITY (HA-HA)

- DECOUPLING / ABSTRACTING FOR INDEPENDENT EVOLUTION (HA-HA)

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 25/68

- ABILITY TO DISTRIBUTE YOUR LAYERS OVER MULTIPLE PHYSICAL TIERS (HA-HA)

- DECOUPLING / ABSTRACTING FOR EXHANGEABILITY (HA-HA)

- DECOUPLING / ABSTRACTING FOR INDEPENDENT EVOLUTION (HA-HA)

- DECOUPLING FOR REUSE (HA-HA)

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 26/68

- ABILITY TO DISTRIBUTE YOUR LAYERS OVER MULTIPLE PHYSICAL TIERS (HA-HA)

- DECOUPLING / ABSTRACTING FOR EXHANGEABILITY (HA-HA)

- DECOUPLING / ABSTRACTING FOR INDEPENDENT EVOLUTION (HA-HA)

- DECOUPLING FOR REUSE (HA-HA)

- SEPARATION OF CONCERNS (IS PARTICULAR LAYER OUR CONCERN?)

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 27/68

- ABILITY TO DISTRIBUTE YOUR LAYERS OVER MULTIPLE PHYSICAL TIERS (HA-HA)

- DECOUPLING / ABSTRACTING FOR EXHANGEABILITY (HA-HA)

- DECOUPLING / ABSTRACTING FOR INDEPENDENT EVOLUTION (HA-HA)

- DECOUPLING FOR REUSE (HA-HA)

- SEPARATION OF CONCERNS (IS PARTICULAR LAYER OUR CONCERN?)

- RELATED STUFF CO-LOCATION (ARE DAOS REALLY RELATED?)

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 28/68

- ABILITY TO DISTRIBUTE YOUR LAYERS OVER MULTIPLE PHYSICAL TIERS (HA-HA)

- DECOUPLING / ABSTRACTING FOR EXHANGEABILITY (HA-HA)

- DECOUPLING / ABSTRACTING FOR INDEPENDENT EVOLUTION (HA-HA)

- DECOUPLING FOR REUSE (HA-HA)

- SEPARATION OF CONCERNS (IS PARTICULAR LAYER OUR CONCERN?)

- RELATED STUFF CO-LOCATION (ARE DAOS REALLY RELATED?)

- CONSTRAINT ENFORCEMENT (IS THERE A BETTER WAY?)

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 29/68

APPLY SERVICE-ORIENTED MINDSET TOSOFTWARE STRUCTURE.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 30/68

LAYERING IS YOUR SERVICE'S DETAIL AND ISINTERNAL TO THE SERVICE.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 31/68

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

- THE COMMON CLOSURE PRINCIPLE

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 32/68

MAKE PACKAGES HIGHLY COHESIVE BYFOLLOWING SINGLE RESPONSIBILITYPRINCIPLE.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 33/68

io.shwitter.user.registrationio.shwitter.user.notificationsio.shwitter.user.profileio.shwitter.user.profile.blocking

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 34/68

io.shwitter.user.registrationio.shwitter.user.notificationsio.shwitter.user.profileio.shwitter.user.profile.blocking

io.shwitter.user :(

 

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 35/68

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 36/68

package io.shwitter.user

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

package io.shwitter.timeline

@Entity class Timeline { @OneToOne User user; }

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 37/68

package io.shwitter.user

@Embeddable class UserId { Long value; }

package io.shwitter.timeline

@Entity class Timeline { @Embedded UserId userId; }

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 38/68

PROVIDE SLIM PACKAGE INTERFACE AND HIDEIMPLEMENTATION DETAILS.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 39/68

AVOID DEPENDENCY MAGNETS. SOMETIMESDUPLICATION IS NOT THAT EVIL.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 40/68

MANAGE RELATIONSHIPS. EVERYDEPENDENCY ARROW HAS A REASON.

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 41/68

FINDBUGS V1.0 - A GREAT START

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 42/68

FINDBUGS V1.1 – IMPERFECTION CREEPS IN

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 43/68

FINDBUGS V1.2 – IMPERFECTION TAKES HOLD

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 44/68

FINDBUGS V1.3 – CHAOS BEGINS

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 45/68

FINDBUGS V1.4 – EXPLOSION

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 46/68

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 47/68

HOW?

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 48/68

MERGING

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

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 49/68

MERGING - REPACKAGING

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

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 50/68

DEPENDENCY INVERSION

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

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 51/68

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) {} }

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 52/68

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) {} }

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 53/68

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) {}}

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 54/68

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()); }}

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 55/68

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.registration

class Registrator { void register(User user, Notifier n) {}}

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 56/68

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.registration

class Registrator { void register(User user, Notifier n) { n.notify(user); }}

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 57/68

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.registration

class Registrator { void register(User user, Notifier n) { n.notify(user.email()); }}

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 58/68

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()); }}

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 59/68

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.emailer

interface EmailHolder { String email();}

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 60/68

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.emailer

interface EmailHolder { String email();}

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 61/68

TOOLS

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 62/68

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 63/68

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 64/68

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 65/68

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

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 66/68

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

@EDUARDSI

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 67/68

THANK YOU

5/11/2015 Title

file:///Users/EDUARDSI/Desktop/well-structured-java-architectures/index.html#1 68/68