Monthly Archives: September 2016

Live demo thoughts

Published / by Steve

Before attempting to do a live demo of how to use Git via ssh, make sure that you can ssh to the server, through any tunnels which may be needed, making any VPN connections needed, while using the conference room WiFi or wired connection. Not the WiFi at your desk, and certainly not the wired connection at your desk, but in the conference room.

I’m just saying.

When your Java method is clearly too damn big

Published / by Steve

Personally I strongly prefer small methods. Reasonable people can disagree about when a method is too big, but when you get an error message like this, your method is too damn big.

java.lang.ClassFormatError: Invalid Method Code length <123456> in com/example/MyClass

That’s the JVM telling you that the method is larger than it can cope with it. 123456 is the size of the method bytecode in bytes.

Now I have not actually seen a method so long that the code alone triggered this error – it happened when we used PowerMock to mock a large class with large methods, then tried to use Cobertura to measure our test coverage.

The fix: breaking up the large methods. When you see this error, it’s time.

 

Steps towards breaking up a monolith

Published / by Steve

Okay, so you’ve got a large monolithic web application. It’s big enough to be hard to maintain, enhance, and scale. But from a business perspective it’s successful enough that you can’t afford to just close it down and walk away. A microservice/SOA approach looks like the way to go, but how to get from here to there?

One approach to consider: begin by refactoring the code for clarity. This is useful when defining a good set of services is hard, such as when the application implements complex business logic, there isn’t a good set of specifications for what the business logic should be, and there’s nobody left around who could know. Or when where to draw the lines that will create a clean set of bounded contexts is less than clear, or the clear boundary results in a service so big it feels like it’s half the size of the monolith. It’s much faster to refactor within a single codebase than to rearrange services after they’ve been split out, and it will improve your ability to maintain the codebase as soon as it’s done.

Note: this discussion assumes that the monolith is using a relational database. Use of NoSQL or some other storage model doesn’t actually change much, it’s just that trying to cover multiple possibilities made this post verbose and cluttered.

Review what you have

Start by reviewing the existing codebase. Somewhere in it there must be classes which are model objects/DTOs, and objects which are accessing the data store (DAOs). There must be controllers which accept HTTP requests and produce HTTP responses. With any luck there are some “service” classes which orchestrate calls to the DAOs to implement business logic on behalf of the controllers.

(If there are objects which fit into more than one category, that will get cleared up as we go.)

Hopefully each set of classes will have its own package. If not, start by moving them into separate packages. Don’t worry if they don’t fit neatly at this early stage; additional clarity will emerge as more refactoring is completed.

Model Objects

Now go through the model objects/DTOs. These are candidates for service request and response bodies. There should be little to no business logic in these classes. Any database queries should be moved to the service classes.

DAOs

Next are the DAOs. All database calls go in the DAOs. If there are still any that aren’t inside a DAO, move them into one. Check the service classes, as database calls like to hide there. Create new DAOs as needed.

Note that as a general rule, DAOs should not begin or commit database transactions. Service classes do that so they can orchestrate multiple DAOs calls into a single transaction. However it’s not necessary to fix them all at this point – that can be done after the service classes have been refactored.

Controllers

Next up are the controllers. Refactor the controllers to only talk to services, not DAOs. This may result in service methods which are simply pass-throughs to DAOs or that do little more than begin and end transactions. That’s okay, we’re laying the ground work for separate services. When that happens the controller will need a web service client with provisions for error handling, and that will rate a separate method in a class outside the controller.

Service Classes

Finally we come to the service classes. At this point each service class is a candidate to become a separate web service. This is the most difficult part of the process. Take a step back and review each service class – is it implementing a bounded context? Does it minimize coupling and maximize cohesion? Is the size reasonable? Smaller is better. A good goal is less than 10 public methods exposed to controllers. If there are more than 25 public methods exposed to controllers, definitely look for ways to split up the class.

If the service classes aren’t meeting these criteria, split them up and rearrange methods so that they do. This step will require multiple iterations, possibly many. If it seems overwhelming or you don’t know where to start, try just moving one or two of the most obvious methods. If a class is very large you may need to arbitrarily split it in half, so that ServiceClass becomes ServiceClass1 and ServiceClass2. This will at least result in more manageable pieces. (And it makes the code smell of an overly-large class more obvious, which is actually a good thing.)

Once you move a few of the obvious methods out of the way, the remaining structure will become clearer with less to obscure it. Then you can move a few more methods, and begin to create and split up classes. Don’t be surprised if one day you move a method into class A and two days later find that it should be in class B. In fact, expect it. This is why we’ve waited to create services: you can iterate much faster when moving a method from one class to another in the same project than when moving a method from one service to another.

Web Services

Eventually you’ll reach a point where the code begins to look reasonably well structured, and at least some parts of it are firm and have been that way for a few weeks of development. This is where you can begin to split up the monolith, creating new web services from these more stable areas. If you carve off enough web services, the remaining service classes in the monolith will be small enough to each be a separate web service, even if it’s one that nobody wants to look inside.

Web Application

The original monolith will actually live on as a web application which contains the controllers and makes calls to the web services. Nothing wrong with that. Do your best to make it stateless, or limit the scope of the client state stored in the web application, so that it’s straightforward to cluster and scale horizontally. Then celebrate, it’s not a quick journey.