Whoops! Where Did My Architecture Go?

Whoops! Where Did My Architecture Go?

Slides of my talk at 33degree conference, Warszaw in March 2013

977c74bb044a9d4fa90b305824eda390?s=128

Oliver Drotbohm

March 15, 2013
Tweet

Transcript

  1. Whoops! Where did my architecture go? Approaches to architecture management

    for Java and Spring applications Oliver Gierke
  2. Oliver Gierke SpringSource Engineer Spring Data ogierke@vmware.com olivergierke www.olivergierke.de

  3. Background 5 years of consulting Lots of code reviews Eoin

    Woods‘ talk on InfoQ
  4. Macro VS. Micro Architecture

  5. Macro VS. Micro Architecture

  6. Sample Code http://github.com/olivergierke/ whoops-architecture

  7. Roadmap Architecture 101 A plain Java based approach Spring Plugin

  8. Architecture 101

  9. Know your dependencies

  10. Granularity Modules Layers Vertical slices Subsystems

  11. Granularity Java ARchive Package Class

  12. Of layers and slices…

  13. None
  14. None
  15. Presentation Service Data Access

  16. Presentation Service Data Access

  17. Presentation Service Data Access

  18. Presentation Service Data Access Account Customer Core

  19. Presentation Service Data Access Account Customer Core

  20. Presentation Service Data Access Account Customer Core

  21. Layers Well understood Known to developers Less important to business

  22. Slices Hardly understood New to developers Key for business req

  23. Presentation Service Data Access Account Customer Core

  24. "How to implement an architecture inside a codebase?

  25. Architecture VS. Codebase

  26. "How to implement an architecture inside a codebase?

  27. "How to implement an architecture inside a codebase?

  28. "How to maintain an architecture inside a codebase?

  29. Code analysis JDepend Sonar

  30. Demo

  31. Sonargraph Formerly known as SonarJ

  32. Demo

  33. A plain Java based approach

  34. "How far can we get with plain Java means only?

  35. Presentation Service Data Access Account Customer Core

  36. Packages

  37. …. layer.slice ? …. slice.layer ? … slice ?

  38. …web.core …service.core …repository.core

  39. …core.web …core.service …core.repository

  40. … core … customer … account

  41. Layers first Leaks slice internals Lower layers visible to everyone

  42. Slices first/only Start with package per slice Expose interfaces and

    domain types Keep implementations private
  43. Slices first/only Encapsulates business module Internals understood anyway

  44. "Start with less packages and the least visibility possible…

  45. Presentation Service Data Access Account Customer Core

  46. Presentation Service Data Access Account Customer Core

  47. Subsystems

  48. Background Risk management at German public bank Quite a few

    other SpringSource clients
  49. Systems grow big!

  50. Complexity & Change

  51. "How to localize change?

  52. "Separate frequent from infrequent change!

  53. Granularity Class Package Java ARchive

  54. Host

  55. Host SPI SPI SPI

  56. Host SPI SPI SPI Plugin Plugin

  57. Host SPI SPI SPI Plugin Plugin

  58. Host SPI SPI SPI Plugin Plugin

  59. Context No OSGi Spring based Build-time composition Don‘t touch the

    host system
  60. Host

  61. Host Plugin Plugin

  62. Host Plugin Plugin App

  63. "How to make the host aware of the plugins?

  64. "How to dynamically collect Spring beans of a given type?

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

  66. Host

  67. Host SPI SPI SPI

  68. Host SPI SPI SPI Plugin Plugin

  69. Host SPI SPI SPI Plugin Plugin

  70. Host SPI SPI SPI Plugin Plugin

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

    context.xml
  72. @Component public class MyComponentImpl implements TransferService { private List<MyPlugin> plugins;

    @Autowired public MyComponentImpl(List<MyPlugin> plugins) { this.plugins = plugins; } … } public interface MyPlugin { void doSomething(); }
  73. Demo

  74. XML? Back in the days

  75. (XML?) Back in the days Probably not a big deal

    anymore
  76. Easy access?

  77. @Component public class MyComponentImpl implements TransferService { private List<MyPlugin> plugins;

    @Autowired public MyComponentImpl(List<MyPlugin> plugins) { this.plugins = plugins; } … } public interface MyPlugin { void doSomething(); }
  78. @Component public 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? } }
  79. Spring Plugin

  80. "The smallest plugin system ever!

  81. Plugins Selection criterion Callback method Let the implementation decide

  82. Registry Equipped with plugins Common access patterns

  83. 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 e) throws E; List<T> getPluginsFor(S delimiter); … }
  84. @Component public 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(); }
  85. @Component public 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()); } }
  86. OrderAware PluginRegistry Respects @Order/Ordered OAPR.reverse()

  87. Bells‘n‘whistles FactoryBean Spring namespace Lazy-eval

  88. Spring Plugin github.com/SpringSource/spring-plugin Apache 2.0

  89. Spring Integration2

  90. <bean class="….FirstSamplePlugin" /> <bean class="….SecondSamplePlugin" /> <int:channel id="input" /> <int:channel

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

  92. Take-aways Know your dependencies On every granularity Start as strict

    as possible Get lenient where necessary
  93. Thanks & credits Eoin Woods - Talk @ InfoQ Uwe

    Friedrichsen - Slides @ Slideshare
  94. Resources Spring Data JPA @ GitHub Sonargraph Spring Plugin