© 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
Top Related