This is because one of the projects I am consulting on at the moment is for a company with just such a system, and I am trying to evolve the system from its present state into a high-quality architecture. In doing this, I have found myself on an odyssey of thought. I have had to try to imagine the thoughts of another developer and understand the decisions they have taken, and in doing so I have had to re-examine the way that I approach architecture and design, and look again at what is right.
One of the most difficult aspects of evolving an application rather than starting one from scratch is that of pragmatism. When we start working on a "greenfield" solution we take a set of requirements for a system, apply patterns of what has worked before and quickly arrive at a skeleton architecture. We then look at the detail of the requitements and create data models, look at the main services required and start to create service interfaces and APIs and then usually we will then embark on an iterative development cycle of some sort where we take a slice of functionality, develop the functionality and so prove the design by getting the architecture working end-to end (I'm not going to get into the agile debate just yet, but take it as read the whether we are using an agile methodology or a waterfall we usually will develop in incremental iterations).
However, in a legacy application we do not always have this luxury. The application may already be embedded in a business too deeply, and the cost of a rewrite may be prohibitive. In this case we need to be able to deliver new or amended functionality within an existing application framework. To complicate the matter further, we not only have to deliver functionality on our current project but we hope to continue to work with the same client and deliver future releases as well so we can't just hack away as we will only create more mess for ourselves to clean up later.
Having found ourselves here we have to make decisions about how much of the system we need to reactor, how much we need to replace altogether, and to what extent we need to grit our teeth and live with what is there. In doing this we have are continually doing cost/benefit/risk assessments. In this series of blog posts I will be looking at some of these decisions that I am making, and the thinking that lies behind them.
I'm not going to disclose any private details of my client, but in order to get a feel for the same thing I am going to create a substitute client instead for the purpose of illustration. Imagine a customer that sells cable TV (my real one doesn't, but it's close enough) and they have a system for providing sales quotes to their customers. The key thing here is that they sell services, and the services may have a complex price structure. There are both recurring and non-recurring (installation) costs associated with providing the service and when selling these services on to customers there is a balance to be struck between initial set-up charges and ongoing monthly charges. If the setup cost is too high customers may be ut off, but if the setup costs are discounted then they must be clawed back over the life of the contract.
The Legacy Application
At this stage I will describe the legacy application in more detail. It is an intranet-hosted C# / ASP.Net line of business application, and the latest release was developed in Visual Studio 2005 (although I suspect that the first version was produced in .Net 1.1). The database platform is SQL Server 2005. The data access layer uses NHibernate, although it's quite an old version of NHibernate, and there is an extensive entity model in place already built onto the NHibernate libraries. The UI uses the UI Process application block in order to implement an MVC (model-view-controller) design pattern. There are a few 3rd-party controls used in the UI, which appear to have been harvested off the Internet as freebies.
"That's not too old, what's the problem?" That's the first thing that springs to mind when you read the technical overview of the system. The technologies are not outdated and are all capable of being upgraded easily. The problems lie in the way that they have been used. In fact, this leads me to the first of my observations on this topic, and that is this:
"In solution architecture, technology choice is not usually the primary source of problems. Problems lie in the way that the technologies are applied."
The customer has tried several times to develop their application in the past, but the previous projects had failed. They have needed to be able to support new and different services for their sales department, but have so far been unable to. This is because the original developers of the system did not give enough thought to their design in the first place, and so have found that when trying to develop the system they could not add new products without creating more and more spaghetti code. What I have been doing is trying to sort out this mess.
I'm coming to the end of this blog post now, and I hope that you've found this useful, and over the next few posts in this series I will be going through some of the things that I have been doing to try to get to grips with this application and take it from a support nightmare and into a half-decent system. Hopefully some of the readers of these posts may be experiencing some of the same issues and might find some useful ideas in this series.
Coming next: Taking over a legacy codebase.