At every point in my career in software there has been a current trend in architecture. The trend has usually changed every couple of years, far faster than there have been significant changes in the underlying languages. This has often struck me as significant, as (ignoring the growing areas of machine learning and AI) the basic problems we’re trying to solve have not changed hugely over the years. So why was it ok in the 1990’s to build a monolith? Why is it no longer a good idea to install an Enterprise Service Bus? What changed?
I’ve often heard people talk about past patterns with phrases like “back when we thought this was a good idea”, but I’m hesitant to believe that so many people could have been wrong about the same thing at the same time. I think there must be more to it than that.
There are always benefits
When I think about all the monoliths I’ve worked on, I can’t say that the experience has always been terrible. There are obvious benefits to a monolithic approach, such as being able to easily share code without the need for package management. They can be a lot easier to test as there are no application boundaries, just about every test you can think of could be implemented as a unit test, although the units may get rather large. Because everything is in one solution we don’t get as many network calls, so we aren’t exposed to network outages or versioning issues during releases.
What about SOA? That was huge at one point. Services focused on business processes which can be called by various applications which need that functionality, it doesn’t sound unreasonable. In fact it sounds a lot like microservices. I have worked on dozens of service oriented architectures over the last decade, none of which would have been described by their builders as SOA.
Enterprise Service Bus – almost no-one likes these any more. Yet the idea of having an integration platform which allows each application to carry on it’s day to day processes without ever having to be aware of any other application which might need to know about its data or processes is not a silly one.
How about: the Service Locator Pattern, Stored Procedures, utility classes, remote procedure calls? I’m sure if you think long enough, there will always be some other ‘good idea at the time’ that is now generally frowned upon.
But what about: microservices, serverless, cloud computing, native apps, no sql databases? Surely these things are destined to be around forever..? We got it right these times. Right?
You still have to design stuff
“How do you build a microservice?”
Is this a good question? If you can answer this question, does that mean you can implement a micro-architecture successfully?
If you know how to deploy, manage, and push code to an enterprise service bus, does that mean you can successfully implement one?
Let me ask these questions in another way:
Which business problem is solved by either micro-architecture or ESB? Because if you aren’t solving a business problem, then you aren’t successfully implementing anything.
It seems to me that an awful lot of technologists follow trends like each one is their next true religion, without ever seeing the actual truths behind them. I know for absolute certainty that every single ‘bad idea’ that has at one time been ‘the latest trend’ will fix a specific problem pretty well. It may lead to other problems if not managed correctly, but that isn’t the point – if you choose an approach, you must choose an approach which is going to work for you and continue to work.
These are some of the characteristics of microservices:
- They are individually deployable.
- They are individually testable.
- They are individually versionable.
- They represent a business process.
- They own their own database and data.
- When changing one service, it’s important to know what other services consume it and test them alongside the change.
- The number of microservices in an enterprise can grow pretty quickly, managing them requires a high degree of automation.
These are some of the characteristics of monoliths:
- All code is in a single solution.
- Boundaries are defined by namespaces.
- The entire application is redeployed each time.
- User interfaces are built into the same application as business logic.
- They often write to databases which are used by other applications.
- If they become too big, the code becomes gridlocked and difficult to change.
These are some of the characteristics of enterprise service busses:
- They can be highly available.
- They allow for moving data in a resilient fashion.
- Changes can be deployed without interfering with other applications.
- They can integrate applications across LAN boundaries in a resilient fashion.
- They can abstract away the implementation of business concerns behind facades.
- They can quickly become an expensive dependency which can be updated only by a specific few people who understand the technology.
These are some of the characteristics of the service locator pattern:
- It allows access to an IOC kernel from objects which haven’t necessarily been instantiated by that kernel.
- It allows access to different implementations based on the requirements of the consuming class.
- It isn’t immediately obvious that the pattern is in use, which can lead to confusion when working on an unfamiliar codebase.
These are some of the characteristics of a serverless approach:
- Developers can think more about the code they’re writing and less about the platform.
- The container running the code is generally the same in dev as test and production.
- Some serverless implementations are reduced to the function level and are very small.
- When they become very small, services can become harder to group and manage.
- Building serverless can sometimes require extra technical knowledge of the specific flavour of serverless in use.
Each of these patterns, approaches, or technologies, all have benefits and down sides. There is a time and a place for each. More importantly, there are more scenarios where each of these patterns would be a mistake than where they would work well. Even where one of these could be a good idea, there’s still plenty of scope to implement it poorly.
I think this is what happens. I think technologists at work get pressured into delivering quickly, or have people telling them they have to work with specific technologies, or their piers laugh when they build something uncool. I think as technologists there are too many of us out there who don’t put enough consideration into whether they are solving the business problem, or whether they are just regurgitating the same stuff that was built previously because ‘that pattern worked ok for them’. I think too may people only see the label, when they should be looking at what’s behind the label.
Piling code on top of code in a situation which isn’t being watched because “it’s worked perfectly fine so far” is what leads to problems. Whether you’re building a single application, pushing into a service fabric, or programming an ESB – if you take your eye off the ball, your pattern itself will rot.
Take SOA for example, how many huge, complicated, poorly documented, misunderstood API’s are deployed which back onto a dozen databases and a range of other services? API’s getting called by all sorts of applications deployed to all sorts of locations, with calls proxied through multiple layers to find their way to this one point of functionality. At some point those API’s were small enough to be a good idea. They were consumed by a few applications deployed somewhere not too distant, and didn’t need much documentation because their functionality was well scoped. Then someone took their eye off the ball and logic which should have been implemented in new services was thrown into the existing one because ‘deploying something else would be tricky’.
This is where patterns get thrown out, as if it was inevitable that the pattern would lead to something unmanageable. Well I have news for you: the pattern doesn’t make decisions, you do.
If you solve a problem by building a service which represents a business process, doesn’t need to call other services, but has been stuck on top of a well used legacy monolithic database, then well done! Who cares that it isn’t quite a microservice? As long as you have understood the downsides to the choices you have made, and know how they are managed or mitigated in your specific circumstances, then that’s just fine. You don’t have to build from the text book every time.
By solving problems rather than implementing cool patterns, we move the focus onto what is actually important. Support the business first.