© 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
Nov 18, 2014
© 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
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Oliver Gierke
Spring DataCore/JPA/MongoDB
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
BackgroundFew years of consulting
Lots of code reviewsEoin Woods‘ talk on InfoQ
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
RoadmapArchitecture 101
A Java packages modelHera
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Architecture 101
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Know your dependencies
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
GranularityModulesLayers
Vertical slicesSubsystems
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
GranularityJava ARchive
PackageClass
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Of layersand slices…
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Layer 1
Layer 2
Layer 3
Slice A Slice B Slice C
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
LayersWell understood
Known to developersLess important to business
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
SlicesHardly understoodNew to developers
Key for business req
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Layer 1
Layer 2
Layer 3
Slice A Slice B Slice C
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
"How to implement an architectureinside a codebase?
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
ArchitectureVS.
Codebase
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
"How to implement an architectureinside a codebase?
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
"How to enforcean architectureinside a codebase?
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Code analysisJDepend
Sonar
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Demo
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
SonargraphFormerly known as SonarJ
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Demo
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
A plain Javabased approach
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Layer 1
Layer 2
Layer 3
Slice A Slice B Slice C
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
….${layer}.${slice}VS.
….${slice}.${layer}
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Layers firstLeaks slice internals
Lower layers visible to everyone
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
"Start with less packages and the least visibility possible…
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Layer 1
Layer 2
Layer 3
Slice A Slice B Slice C
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Layer 1
Layer 2
Layer 3
Slice A Slice B Slice C
© 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
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Slices firstEncapsulates business moduleInternals understood anyway
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Subsystems
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
BackgroundRisk mgmt. at German public bank
Quite a few other SpringSource clients
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
"The smallest plugin systemever!
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Host
SPI SPI SPI
Plugin Plugin
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
ContextNo OSGi
Spring basedBuild-time composition
Don‘t touch the host system
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Host
Plugin Plugin
App
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
"How to make the host aware of the plugins?
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
"How to dynami-cally collect Spring beans of a given type?
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
classpath*:META-INF/spring/plugin-context.xml
© 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
© 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();
}
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Demo
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
XML?Back in the days
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
(XML?)Back in the days
Probably not a big deal anymore
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Easy access?
© 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();
}
© 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?
}}
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
PluginsSelection criterionCallback method
Let the implementation decide
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
RegistryEquipped with plugins
Common access patterns
© 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);…
}
© 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();
}
© 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());
}}
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
OrderAwarePluginRegistryRespects @Order/Ordered
OAPR.reverse()
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Bells‘n‘whistlesFactoryBean
Spring namespaceLazy-eval
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Hera
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Herahttp://hera.synyx.org
Apache 2.0Soon to be on GitHub
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Spring Integration2
© 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" />
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Demo
© 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
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
Thanks & creditsEoin Woods - Talk @ InfoQ
© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
ResourcesSourcecode @ GitHub
Sonargraph