62
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission. Whoops! Where did my architecture go? Approaches to architecture management for Java and Spring applications Oliver Gierke

Whoops! Where did my architecture go?

Embed Size (px)

DESCRIPTION

Slides of my SpringOne 2011 talk on how to implement and enforce architecture in codebases.

Citation preview

Page 1: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Whoops! Where did my architecture go?Approaches to architecture management for Java and Spring applications

Oliver Gierke

Page 2: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Oliver Gierke

Spring DataCore/JPA/MongoDB

[email protected]

Page 3: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

BackgroundFew years of consulting

Lots of code reviewsEoin Woods‘ talk on InfoQ

Page 4: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

RoadmapArchitecture 101

A Java packages modelHera

Page 5: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Architecture 101

Page 6: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Know your dependencies

Page 7: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

GranularityModulesLayers

Vertical slicesSubsystems

Page 8: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

GranularityJava ARchive

PackageClass

Page 9: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Of layersand slices…

Page 10: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Layer 1

Layer 2

Layer 3

Slice A Slice B Slice C

Page 11: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

LayersWell understood

Known to developersLess important to business

Page 12: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

SlicesHardly understoodNew to developers

Key for business req

Page 13: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Layer 1

Layer 2

Layer 3

Slice A Slice B Slice C

Page 14: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

"How to implement an architectureinside a codebase?

Page 15: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

ArchitectureVS.

Codebase

Page 16: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

"How to implement an architectureinside a codebase?

Page 17: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

"How to enforcean architectureinside a codebase?

Page 18: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Code analysisJDepend

Sonar

Page 19: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Demo

Page 20: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

SonargraphFormerly known as SonarJ

Page 21: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Demo

Page 22: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

A plain Javabased approach

Page 23: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Layer 1

Layer 2

Layer 3

Slice A Slice B Slice C

Page 24: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

….${layer}.${slice}VS.

….${slice}.${layer}

Page 25: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Layers firstLeaks slice internals

Lower layers visible to everyone

Page 26: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

"Start with less packages and the least visibility possible…

Page 27: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Layer 1

Layer 2

Layer 3

Slice A Slice B Slice C

Page 28: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Layer 1

Layer 2

Layer 3

Slice A Slice B Slice C

Page 29: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Slices firstStart with package per slice

Expose interfaces and domain typesKeep implementations private

Page 30: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Slices firstEncapsulates business moduleInternals understood anyway

Page 31: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Subsystems

Page 32: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

BackgroundRisk mgmt. at German public bank

Quite a few other SpringSource clients

Page 33: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

"The smallest plugin systemever!

Page 34: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Host

SPI SPI SPI

Plugin Plugin

Page 35: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

ContextNo OSGi

Spring basedBuild-time composition

Don‘t touch the host system

Page 36: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Host

Plugin Plugin

App

Page 37: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

"How to make the host aware of the plugins?

Page 38: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

"How to dynami-cally collect Spring beans of a given type?

Page 39: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

classpath*:META-INF/spring/plugin-context.xml

Page 40: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

classpath*:META-INF/spring/plugin-context.xml

SPI SPI SPI

META-INF/spring/plugin-context.xml

META-INF/spring/plugin-context.xml

Page 41: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

@Componentpublic class MyComponentImpl implements TransferService {

private List<MyPlugin> plugins;

@Autowired public MyComponentImpl(List<MyPlugin> plugins) { this.plugins = plugins; } …}

public interface MyPlugin {void doSomething();

}

Page 42: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Demo

Page 43: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

XML?Back in the days

Page 44: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

(XML?)Back in the days

Probably not a big deal anymore

Page 45: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Easy access?

Page 46: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

@Componentpublic class MyComponentImpl implements TransferService {

private List<MyPlugin> plugins;

@Autowired public MyComponentImpl(List<MyPlugin> plugins) { this.plugins = plugins; } …}

public interface MyPlugin {void doSomething();

}

Page 47: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

@Componentpublic class MyComponentImpl implements TransferService {

// Constructor omitted

public Result myMethod(SomeParameter parameter) {

// Select the first one to match to invoke?// Select multiple ones to invoke?// Select and fallback to one if none found?// Select and throw an exception if none found?

}}

Page 48: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

PluginsSelection criterionCallback method

Let the implementation decide

Page 49: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

RegistryEquipped with plugins

Common access patterns

Page 50: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

public interface Plugin<T> {

public boolean supports(T delimiter );}

public interface PluginRegistry<S extends Plugin<T>, T> {

T getPluginFor(S delimiter);T getPluginFor(S delimiter, T default);<E extends Exception> T getPluginFor(S del, E exception) throws E;

List<T> getPluginsFor(S delimiter);…

}

Page 51: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

@Componentpublic class MyComponentImpl implements TransferService {

private PluginRegistry<MyPlugin, String> plugins;

@Autowired public MyComponentImpl(PluginRegistry<MyPlugin, String> plugins) { this.plugins = plugins; } …}

public interface MyPlugin extends Plugin<String> {void doSomething();

}

Page 52: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

@Componentpublic class MyComponentImpl implements TransferService {

private final MyPlugin defaultPlugin = new MyDefaultPlugin();

public Result myMethod(String parameter) {// Select the first one to match to invoke?… = plugins.getPluginFor(parameter);// Select multiple ones to invoke?… = plugins.getPluginsFor(parameter);// Select and fallback to one if none found?… = plugins.getPluginFor(parameter, defaultPlugin);// Select and throw an exception if none found?… = plugins.getPluginsFor(parameter, new RuntimeException());

}}

Page 53: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

OrderAwarePluginRegistryRespects @Order/Ordered

OAPR.reverse()

Page 54: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Bells‘n‘whistlesFactoryBean

Spring namespaceLazy-eval

Page 55: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Hera

Page 56: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Herahttp://hera.synyx.org

Apache 2.0Soon to be on GitHub

Page 57: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Spring Integration2

Page 58: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

<bean class="….FirstSamplePlugin" /><bean class="….SecondSamplePlugin" />

<int:channel id="input" /><int:channel id="output" />

<int-hera:dynamic-service-activatorinput-channel="input" outputChannel="output" plugin-type= "….MyPlugin" method= "myBusinessMethod"delimiter="payload" invocation-arguments= "payload" />

Page 59: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Demo

Page 60: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Take-awaysKnow your dependencies

On every granularityStart as strict as possible

Get lenient where necessary

Page 61: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

Thanks & creditsEoin Woods - Talk @ InfoQ

Page 62: Whoops! Where did my architecture go?

© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.

ResourcesSourcecode @ GitHub

Sonargraph