Radical modularity in Java

| | August 5, 2015

The development team I’m a part of wrote and still maintains a codebase of pure Java spaghetti code. Most of this was implemented before I joined this team.

My background is in Python/Django development and the Django community really emphasizes “pluggability” — a feature of Django “apps” (modules) which implies mostly “one thing and one thing well”, re-useability, loose coupling, and a clean, conscious API. Once the Django team I once worked in started to “get it”, we pretty much had zero problems with messy, tightly-coupled masses of monolithic code.

Our practice involved developing Django apps outside of the Django project in which we intended to use the app (a common practice among Django developers, from what I’ve gathered) Each even lived in a Git repository separate from that of the overall Django project.

Now, we’re presented with an opportunity to refactor much of our spaghetti code, and it seems to me that some of what I learned from the Django community should be applied here. In short, I’d like to see our new codebase developed as a series of “pluggable” modules each written under the assumption that it won’t have access to other modules (except those on which it should rationally depend). I believe this should do a good job of driving home principles of proper software design to the whole team.

So, what I’m advocating for is to have one separate repository per “feature” we want in our new (Spring) project. Each would have its own, independent build process and the result would be a .jar . We’d also have a repository for project-level things (JSP’s, static files, etc) and its build process would produce a .war . The .jars wouldn’t be placed inside the .war, but rather be treated as Gradle dependencies (the same way third-party dependencies would be.)

Now I have to sell it to the boss. He’s asked for some example of precedent for this plan. Obvious places to look would be open-source projects, but if a project is split across multiple repositories, it’s likely to be multiple projects. So, perhaps I’m looking for some sort of suite. Spring itself looks promising as an example, but I haven’t been able to find many others.

My questions are (and sorry for the long back-story):

  • Is there any such precedent?
  • What examples are there?
  • Is there any documentation (even just a blog post would be of help) out there advocating anything like this?
  • Any suggestions for implementing this?
  • Is this even a good idea?

Thanks in advance!

Edit: Whether or not to refactor is not in question. We have already decided to make some drastic changes to most of our code — not primarily for the purpose of “making it cleaner” in fact. My question is about whether our planned project structure is sound and how to justify it to the decision-makers.

5 Responses to “Radical modularity in Java”

  1. Jarrod Roberson on November 30, -0001 @ 12:00 AM

    The following issues are more important that where to put code on the disk or in an artifact:

    If you don’t understand that, you have already failed.

    What you describe is not refactoring, it is rewriting using a more palatable name:

    Unless you have 100% code covered in unit tests already; someone(s) are going to get fired over this when ( not if ) this effort fails spectacularly, probably multiple times!

    Even with awesome unit tests, someone is going to miss something and someone is going to take the fall when it finally gets discovered in production, usually after months of silently corrupting data.

    Semantics are Important:

    Removing Struts and replacing with Spring is not refactoring is rewriting by definition. Refactoring would be moving from Struts 1.1 to 2.0, replacing Struts means replacing all the Struts code with something else, by definition that is rewriting not refactoring.

    Working Software comes in many disguises:

    The business always thinks what they have is working.

    Miss a deadline, introduce a bug no matter how minor, lose a feature no matter how minor, mis-interpret an undocumented process and change something no matter how minor or even for the better. They are just looking for any problems weakness or potential trouble to spread FUD and make sure your effort is a failure, at least most of the time.

    All these things will cost you and your team political capital, someone will take the fall for these things, no matter how innocent or merit-less the perceived failures are!

    Projected outcome:

    Most likely you and/or other “non-Java” developers and not the core Java people that created this working system that you “non-Java” people refactored ( code word for rewrite in this case ) and delivered on time broken and incomplete or didn’t deliver on time or didn’t deliver at all.

  2. I think it’s possible to find examples of good and bad implementation in both Java and Python.

    Spring is indeed a good place to start. It emphasizes good layering, designing to interfaces, etc. I’d recommend it highly.

    Spring’s layering is “horizontal”. If “module” means “business functionality” to you, then multiple modules will be present in a given layer.

    Plugable suggests a more vertical approach.

    Maybe another way to attack it would be to decompose the system into a set of independent REST web services. Decouple the functionality from the interface completely. That way the services can be shared by web, mobile, or any other client that comes along.

    This will require strict isolation of services and ownership of data sources. A single web service will own/manage a swath of data.

    I’d recommend looking at Michael Feathers’ book “Working Effectively With Legacy Code”. It’s ten years old, but still highly regarded on Amazon.

    One thing I like about the REST web services approach is you can isolate features and do them as time and budget permit. Create and test a service, let clients exercise it, move on to the rest. If things aren’t too coupled you can march through the app that way.

  3. Every component is in its own jar, but the jars are not contained in the war ? How should that work ? Even third party libs are included in the war. Except for those that are provided by the container. Regarding the jsp stuff: Can I serve JSPs from inside a JAR in lib, or is there a workaround?

  4. I would recommend watching “Four Strategies for Dealing with Legacy Code” by Eric Evans, the originator of Domain-Driven Design: http://dddcommunity.org/library/evans_2011_2/

    It may not entirely answer your question but it offers arguments and strategies that might help with your endeavour.

  5. Refactoring entire application is not an easy task, specially if the code is hard-wired as you have described. If Pluggablity is an important target, I would recommend Grails/Groovy.

    If you can somehow identify view, controller and business logic, or much better services. You might be able to reuse some existing codes. The good thing about grails/groovy is that you are able to incorporate JSP/JAVA with GSP/GROOVY.

    Again, this is really hard to sell and grails is probably a good framework to ease the refactoring pain.

Leave a Reply