Frameworks and Frankenstein

Jul 7, 2014

In the famous novel Dr. Frankenstein built his monster out of many parts from dead people. Initially he wanted to create a beautiful creature but the difficulties of reanimating and combining the parts made him create a hideous monster instead.

When you approach building an application, one of the earliest decisions you usually have to make is in choosing what to write yourself, and what to leverage from frameworks, libraries, toolkits and the like. Pick the right ones and development is accelerated, pick the wrong ones and you wind up with a monster. Often the decision might be initially good but over time becomes a nightmare.

The most important thing to understand in this decision is that whatever you choose, it becomes a part of what you will be delivering, almost as if you wrote it yourself. The customer won't care who wrote what or how well it integrates; they only care about how well the end result is. You can't tell the customer "It's not our fault, the gadget library was full of bugs." From their perspective you screwed it up.

In fact choosing frameworks incorrectly, either because they were poorly written, hard to maintain, not used as designed or even modified without understanding, is most definitely your problem.

Some frameworks of course you have little choice in picking. If you write for iOS, Apple's frameworks are required. Whatever language you choose may come with standard libraries you have to use. Here you don't really have a choice except to not write for an OS or use a language.

Generally you choose from closed or open source libraries and frameworks because what you need to do has already been done, or you don't have the expertise to write it yourself, or maybe the business requires a third party library to function. You have to consider each option or choice as a balance between what it provides for you and what you might risk in using it versus another choice or even doing it yourself.

Sometimes the choices are easy but often they aren't so obvious. Evaluating someone else's code is always hard. What might appear as a no-brainer after a quick evaluation might eventually drag you into a pit of snakes.

The sad thing is often you don't get a choice in the matter. Upper management might tell you what you have to use no matter how horrible it might be. I've seen this way too often for it to be uncommon. Terrible decisions usually lead to terrible software.

I went to work for a financial services company about 10 years ago. Previously they had decided to buy BEA Portal Server to build their customer site. I found they were only using one portlet per page; of course it would have made so much more sense to just write the app as a normal webapp. Adding the complexity of the Portal software running on top of the app server running on top of the web server made development far more complex. Add to that the web server was IIS but the app server was BEA/Java and user accounts stored in Active Directory (yet another bad idea) and a differently configured QA environment and the rollout of the app was a disaster. We weren't allowed to do anything different from what had been chosen before I came. Picking a bad combination of libraries, tools and technologies can make even a good team fail.

A couple of jobs ago I worked for a healthcare company who's flagship batch processing system had been written in Java but using a third party HIPAA validation engine written in C++, along with an orchestration engine to coordinate processing. The validator was fine but had been incorrectly implemented and leaked like a sieve, so that the system had to be restarted every two hours, a real nightmare for the sysops folks who had to do this during the night manually. The orchestration engine made the original architect decide to chop the system into 20 different apps, each one of which dumped intermediate data into an enormous database. It was a terribly wasteful system that frequently got stuck. In this case you had one framework incorrectly implemented, and another incorrectly applied. Both were closed source.

When you make those choices to include someone else's code into yours, it is still your responsibility to treat them as if you had written them yourself. They are part of the product. You have to understand how to use them correctly. You have to integrate them as designed and not try to force a square library into a round framework.

If you use an open source framework you have the source code so it's a little easier to evaluate, but if the library is large it might be prohibitive to really look at all of it. With open source you also have to consider how likely it is to be maintained in the future, how easy it will be to manage updating those future versions into your usage, especially if you make changes. You also have to make sure you use it correctly as designed assuming there is enough information to figure that out.

When I started at my current and soon to be former job (90% of the company was laid off in the past year as we became a marketing only subsidiary) we were handed an unfinished iPad app. It had been created by a recently closed office and was written by a third party that had never developed an ecommerce type app before. They had chosen to use an open source iOS framework called RestKit to handle networking and mapping JSON data from our mobile server API. None of this code using this worked when we got it but we were expected to ship in 10 days anyway. I had never seen it before and it took a lot of effort to understand how it worked, or didn't in this case. There was a race condition buried deep inside which caused double posts that took 2 programmers 2 days out of the ten to solve. It also featured way too much complicated code that make it difficult to fix when we found bugs.

We also found that the version they had chosen was out of date and the current version at the time had changed far too radically to integrate. The app shipped but was never as stable as we wanted it to be though it proved popular and made good money.

Later that year the CEO demanded we write a special purpose app in such a short timeframe that I had to crib part of the iPad app to use; I integrated it inside a shell so that at least I could replace it later. It never got replaced so the decisions that that third party made long before continued to plague us for two more years. That's the hard part of evaluation, thinking of the future. Often you don't get a chance to remake the decisions so it's good to do it right the first time.

The original authors made a decision that seemed to make sense to them since they knew they wouldn't ever have to maintain it. RestKit was fairly popular but it was not all that well written and then being terribly used in the app made me even less enthused by it.

A year later I had the opportunity to consider a replacement app for everything we had and thus had time to evaluate what to use. In the end I decided to write everything myself based only on what iOS provided; I had plenty of time to consider how to do it the right way. The resulting framework became the basis of our new flagship iOS app which was written between the iOS 7 announcement and the iOS 7 ship date (we were on the famous 1 second slide at the keynote) and we shipped it on day 1. Writing it yourself isn't always the best idea but if you look at the choices critically sometimes it does make sense. In this case we had a well tested solid framework that did exactly what we need and nothing we didn't. Building an app on it turned out to be pretty easy.

When you utilize a general purpose open source framework you often wind up with complexity and extra functionality you don't need. Then when updates are made or you make customizations it's hard to integrate them. Sometimes it might be abandoned and now you have to maintain it yourself when OS versions change or other needs appear. Now you have code you don't really understand yet have to make potentially major architecture changes. It's hard to balance the benefits and challenges especially if they might be far in the future.

One thing I like about node.js is that many things in NPM are fairly small and single purpose, making deciding to use them or not reasonable easy to do. Micro-frameworks, a recent concept, although not without their own issues, at least make evaluation a little easier.

In the early days of my career this wasn't a big issue, no open source frameworks, basically not much more than C libraries and Inside Macintosh. Today however it's never easy to decide what to use and what to write and often you don't get a choice and get to make it work somehow. Life is more complicated today for sure.