I’ve been on a refactoring mission for what feels like an eternity. The motivation for which is to pay off a significant portion of our technical debt. However, throughout the whole process I keep being reminded of how I believe systems should be written. Namely, simple parts brought together simply.
The problem is that this normally stops at the code level. So while you’re happily abiding by the SOLID principles, your creating a massive code base with little overall cohesion. This makes it difficult to navigate and debug and makes it too easy to create dependencies where they are not required, much less wanted. I would scientifically guesstimate that this increase in complexity follows a power curve against the size of your code base.
A large part of what I have been doing is breaking up the “one assembly to rule the all” into 40, yes 40, assemblies with much better defined responsibilities. These assemblies roughly map to namespaces but there are many places where there’s a dependency loop you would not have chosen to create if creating that dependency was not as simple as importing a namespace. The build now takes longer but as this part of the code base is now under my control and being released as binaries that’s just my problem.
What we have also done that has given us both reduced complexity and increased power is shipping out core functionality to well-defined services. I’ve had little to do with this, but an example of this is that our thumbnail generation has all been moved out to an internal service. This service is written in a combination of Java, C, pixie dust and magic. You’d be surprised by what it can handle and amazed by how fast it works. Yet it’s easy to use as the API is so simple; a combination of XML and HTTP which I wrote a .NET wrapper for which has three public methods. This wrapper was then used by one of our wizards to create a simple set of classes which were easily extensible and solved a lot of the problems with our previous thumbnail service along the way.
This approach has many benefits. It allows you to focus resources where they will be most beneficial and utilise the expertise you have within your company by allowing you to pick the best tools for the job. You prevent the ability to take dependencies you do not want to have whilst maintaining the ability to rewrite a significant part of your system entirely. This makes it easier to write something that’s “good enough” now as you know precisely how it will be depended upon when it needs replacing.
Given the choice, our whole system would be written this way. It scales better as all the significant parts of the system are well disconnected, leaving the strategies of scaling up and out available. Previously we only had one system which only gave us the option of scaling up. It allows you to focus your efforts, in terms of functionality or performance, much more precisely and it leaves your application developers to focus on adding features in a much smaller code base. A code base that’s easier to navigate and change as a result, allowing them to deliver more features in less time.
All in all a system and development department that’s greater than the sum of it’s parts.