Everything I know about software in spaghetti bolognese: managing complexity


Published on

None of of us enjoy spaghetti code, much less spaghetti builds, spaghetti tests, or spaghetti classpaths. Some days software engineering seems like the struggle against spaghetti - modern projects often become a large and complex tangle of source code and resources, and the runtime interactions are even worse! This means many projects are hard to navigate, difficult to extend and problematic to deploy/run. You only have to look at the OpenJDK itself to see the problems it faces in trying to have a smaller deployment and runtime footprint! Jigsaw was to be the inbuilt solution for the OpenJDK, extending beyond the JVM itself to help applications with their modularisation story (i.e. Jigsaw or OSGi). Sadly, Jigsaw is not going to make it for Java 8, so developers are left with only a few tooling choices in order to help them. However, tooling is only part of the answer in managing the complexity. What really matters in avoiding a noodly mess is the layout of your source code and resources, clear contracts, and how you think about the dependencies your code has at runtime. Dr Holly Cummins and Martijn Verburg will take you through some of the practical design decisions you can take to help modularise your application properly, independent of tooling. Time permitting they'll then showcase some of tooling support that OSGi can bring to the table as the premier modularity system for Java today.

Published in: Technology

Everything I know about software in spaghetti bolognese: managing complexity

  1. 1. Everything I know about software I learned from spaghetti bolognese Managing complexity Holly Cummins, IBM @holly_cummins Martijn Verburg, jClarity @karianna
  2. 2. What do we know about software?Holly Martijn11 years with IBM CTO - jClarityWebSphere Diabolical DeveloperJVM performance Community Cat Herder
  3. 3. What do we know about spaghetti?
  4. 4. Common understanding No more noodling with code.
  5. 5. Understanding interfacesMy users dont need to know about all my methods●Id like to swap this implementation for that● implementation
  6. 6. Understanding reuse“Could I re-use some your code in my project, please?”● Inheritance vs Composition ● Inheritance ~= Liskov Substitution Principle ● Composition ~= Does Type B only want only some/part of the behavior exposed by Type A?
  7. 7. Services Normal spaghetti bolognese Vegetarian spaghetti bolognese
  8. 8. Getting hold of implementationsPerpetual problem●Factories● ● Factory factories ● Factory factory factories ● Factory factory factory factoriesHome-rolled frameworks●META-INF/Services●OSGI services●
  9. 9. Dependency injectionExternalised Factory Problem●Enable implementations to be switched in and out●● Avoids hard-couplings in runtime● Enables effective testing and test-driven-development ● Implementations can be stubbed or mocked out● Really helps modularity● Guice, Picocontainer are light-weight starting points
  10. 10. What can I do?● Be strict about dependency management● Understand external and internal interfaces ● What do you want to be able to swap?● Think about what type of re-use youre going for● Draw out dependencies ● Tooling can help
  11. 11. JAR Hell
  12. 12. Problems with JARs● JARs are transparentMarch12, 2010 QCon London 2010 Ian Robinson 12
  13. 13. Problems with JARs● Java Platform Modularity Classes encapsulate data Jar ● ● Packages contain classes Package ● Jars contain packages Class● Class visibility: Package ● private Class Class ● package private Package ● protected Class ● public Class● No “jar scoped” access modifiers.March12, 2010 QCon London 2010 Ian Robinson 13
  14. 14. Problems with JARs● No means for a jar to declare its dependencies. Jar Package● No versioning. Class Package Jars have no modularization Class● Class characteristics Package Class Class● At runtime there is just a collection of classes on a global classpathMarch12, 2010 QCon London 2010 Ian Robinson 14
  15. 15. More problems with jars● In a normal jar, an implementation is just as easy to use as the interface. ● In a normal jar, an implementation easier to use than the interface ● No worries about factory patterns ● Encourages consumers to bust encapsulation wide openMarch12, 2010 QCon London 2010 Ian Robinson 15
  16. 16. Why classloading is brokenMarch12, 2010 QCon London 2010 Ian Robinson 16
  17. 17. What can I do?Dont think JARs, think modules
  18. 18. Modularity PrinciplesThis section is a tooling-free zone. Mostly.
  19. 19. Understanding dependenciesWhat other code does my code touch?●What happens if I change my code?●
  20. 20. Understanding dependencies● What other code does my code touch?● When does it connect? ● Compile time? ● Runtime? ● Transitively? ● Only at test?
  21. 21. Modularity
  22. 22. Bad Modularity● Dividing up the code != good modularity● Retrofitting modularity is hard● See Michael Feathers “Dealing with Legacy Code”
  23. 23. Think about modularity from the start
  24. 24. Enforcing modularity with classloaders
  25. 25. Sharing between modules OSGi OSGiOSGi OSGi OSGi
  26. 26. Sharing between modules
  27. 27. A question of scale● Need for modularity grows with size of project
  28. 28. Choose the right granularity
  29. 29. Choose the right granularity
  30. 30. Choose the right granularity
  31. 31. Choose the right granularity● A common approach ● foo-api ● foo-core ● foo-ui● Outsiders only rely on foo-api (interfaces!)● It boils down to your domain modeling. ● Naming is everything
  32. 32. Modularity isnt free
  33. 33. What can I do?● There is a bunch of tooling to help ● Maven, Ant/Ivy ● OSGi, Jboss Modules● Nothing beats a whiteboard or a drawing pad ● TDD should be Test Driven Design ● Pair Programming? Think Pair Designing instead
  34. 34. Versioning Now that you have modules, how do you manage the relationship between them?March12, 2010 QCon London 2010 Ian Robinson 34
  35. 35. VersioningMarch12, 2010 QCon London 2010 Ian Robinson 35
  36. 36. Versioning● Major increment: I break consumers ● Removal of existing methods or interfaces● Minor increment: I break implementers ● Addition of methods to interfaces● Micro increment: I promise I dont break anything ● “Clear” defect fixes ●March12, 2010 Internal improvements QCon London 2010 Ian Robinson 36
  37. 37. Versioning● But … causes developer depression ● Compatibility != amount of work ● Tempting to use marketing versions rather than semantic versions● A good example here is Java itself!March12, 2010 QCon London 2010 Ian Robinson 37
  38. 38. What can I do?● major.minor.trivial ● SNAPSHOT is acceptable internally● If you have customers/clients ● You need to think about backwards compatibility ● Plugin systems are useful here ● Once more think dependency injectionMarch12, 2010 QCon London 2010 Ian Robinson 38
  39. 39. Testing
  40. 40. TastingWhat does our pasta taste like?Testing simple things is easy●Testing complex things is hard●● Make your things simple
  41. 41. Unit testing
  42. 42. Integration testing
  43. 43. What can I do?● Test early, Test often● Test at lots of granularities ● Unit ● Integration ● System● Let machines do your testing for you!
  44. 44. Tools, Tips and Techniques
  45. 45. CI
  46. 46. OSGi● Explicit dependency management ● Classloading● Explicit version management● Services ● No more hacky factories
  47. 47. OSGi● Enables ● Reliability ● No more ClassDefNotFoundException ● Small footprint ● Dynamism● Easy to get started with – its just simple manifests ● Its compatible too!
  48. 48. OSGi Manifests Manifest is a bit like a recipeManifest-Version: 1.0Bundle-ManifestVersion: 2Bundle-Name: MyService bundleBundle-SymbolicName: com.sample.myserviceBundle-Version: 1.0.0Bundle-Activator: com.sample.myservice.ActivatorImport-Package: org.apache.commons.logging;version="1.0.4"Export-Package: com.sample.myservice.api;version="1.0.0"
  49. 49. All done!
  50. 50. Thank you.... and now its time for lunch. .... which may be pasta.