Building the “Good Enough” Framework
Posted by Keith Elder | Posted in .Net, Programming | Posted on 09-09-2008
At DevLink a few weeks we held open spaces on the theme of “good enough”. I started a topic on building internal application frameworks and re-usable code bases, thus the title. This was an interesting topic to me because my role at work the last several months has been to create this very thing. It is an interesting hat to wear because instead of a team’s clients being entrenched in the business, the clients are fellow developers. The question is how do you go about building this type of framework and what are the things you should watch out for as you go down this path. Below are notes taken from this open space session along with other guidance. Please feel free to continue this conversation here and within your own blogs.
Know What You Are Building
It became obviously very quickly during our open space that developers were scared of the term “framework” as we discussed the topic. As several stated, they’ve been forced to use various libraries and frameworks at previous employers and they’ve found them to get more in the way than to help. If you are tasked with building an internal framework like this it is important there are clear goals in mind. Maybe you don’t need a framework, maybe all you need are reusable services or libraries of utilities.
The main goal of whatever you call these libraries should be about keeping things DRY (don’t repeat yourself). If developers are having to repeat themselves then work with them to keep things DRY so other developers can stay DRY.
To save the confusion I’ll refer to the framework / reusable code as “the libraries” from now on.
Know What Not To Do
It is great to know what to do but knowing what not to do is just as important. These gems of knowledge come from those that have gone before you or those that have tried to use what others have created. Seek those people out and pick their brains to learn what not to do. I’ll touch on some of these as we progress further.
Don’t Put Items in One DLL
Speaking of knowing what not to do, one of the first items the group brought up was to make sure not to put everything in one DLL. This gem of knowledge boils down to separation of concerns. Imagine if the .Net framework was one large DLL. Yeah, not good. The same principle applies here as well.
Make it Discoverable and KIS (keep it simple)
The term discoverable in this context means will developers be able to use your libraries using intuition and Intellisense within the IDE. For example, let’s say you have a method in one of your libraries that validates a phone number. Developers should be able to find that method without much effort and thought and without even knowing if it exists or not. They should be able to just discover that it is there.
Of course if things are kept simple this helps with discovery. These two go hand in hand.
Get Architects Involved
If you are tasked with building a type of system like this it is important to get your architects involved early and continuously. Architects should be driving features into these libraries. Architects should know problems developers face and identify those situations where developers are repeating themselves. Once identified they should be communicated to those managing these libraries and or even contributed by them.
Use Architects as your eyes and ears.
Treat it as a Third Party Vendor
One very important mind set everyone (the team writing the code and those using it) must have about these libraries is they should be treated as any third party vendor. This means a couple of things. One it means these should be updated, deployed and managed as any third party vendor. Developers shouldn’t be able to just grab a DLL and throw it into project they are working on. Not being able to manage the versions applications are using can result in a nightmarish situation. Secondly, it means the developers using these libraries cannot haphazardly contribute to the source just as they cannot contribute to a vendor’s code base. That isn’t to say they can’t contribute, as a matter of fact they should be the driving force behind new features. Most all vendors that build tools for developers will tell you they get their features from their customers.
The third thing this forces everyone think about is breaking APIs. Imagine for a second that vendors changed their APIs on a whim and with each release. Can you imagine how much of an impact that would that have on your organization? The answer is A LOT. The same thing applies for these libraries. Once they are out there and used, changing an API has drastic consequences and can be costly for organizations to redeploy and fix applications. As one of the attendees that works for a company that produces tools for developers said, “Changing an API should require executive decision.”. It is ultimately an executive decision to change APIs because of the time and cost involved. This also segues nicely into the next topic.
Do it Right the First Time
Tying into never breaking the APIs, this is important enough to get it’s own heading. When building reusable libraries it is extremely important things are done right the first time. If this means spending an extra day to research a new pattern do it. If it means writing 10 additional unit tests do it. If it means building sample applications do it. If it means holding up a release to make sure other developers are comfortable with it do it.
The strict nature of these libraries must be adhered to because of the impact of changes. It doesn’t mean there won’t be bugs. There will be bugs but your deployment scenario should handle that gracefully. The .Net framework already allows for this, just be sure you take advantage of it.
Use Senior Engineers, They Are the Gate Keepers
Let’s see, don’t break the API and do it right the first time. Hmm, that sounds like a job for a Jr. Level engineer no? This should go without saying but in order to achieve these goals, the easiest way to do it is to use senior level engineers. Thus, if you were thinking of using Interns to write these libraries, think again.
These senior engineers also should serve as the gate keepers for things that get into the framework.
The Libraries Should Evolve
If you are starting out to build a framework, more than likely it will fail and not meet the needs of your developers. Libraries should evolve over time. Going back to the third party vendor rules, vendors typically don’t add things into their tools unless asked. These libraries should be the same way. In other words, don’t add something just because it is cool. If someone didn’t ask for it, don’t add it (YAGNI – you ain’t gonna need it). Let the libraries evolve over time and you’ll have a better product in the end.
Use Baked Code
If you are a gate keeper of these libraries don’t take just any contribution someone sends your way. There will be obvious cases where this doesn’t apply, but it is safe to say that code needs to bake before being considered. The term baked refers to code being used in production or maybe in several projects. Using baked code helps to make sure the code is needed and wasn’t a one off scenario. It also helps to make sure the code works in broader scenarios rather than just where it was originally written.
Adamantly Adopt Best Development Practices
When building application frameworks and libraries like this it is extremely important best development practices are followed. These practices help to mitigate risk, bugs, defects, and focus on providing the quickest value. If you are using Senior Engineers, more than likely these practices will already be followed and adhered to. Here are some base guidelines in no particular order. I won’t go into detail on each one as I think they have been covered in other conversations better.
- Test Driven Development
- Build To Interfaces
- Continuous Integration – One thing to note is not only do CI for your builds, but also try to get other projects to do CI with your libraries
- Automate Deployment
- Strongly consider using Agile methodologies
These are well known and established best practices but I want to harp on the words “adamantly adopt”. Using one out of this short list of practices is not enough. They should ALL be adopted.
Continuing The Conversation
This was a great open space and it brought to light a lot of things that need to be considered when developing these types of libraries. I welcome anyone to contribute tips and continue this conversation.
@Joel,
Just be careful with wrapping other libraries.
In a conversation it is always good to be concise and therefore avoid providing TMI (too much information) as not all of it is relevant.
When interacting with third-party libraries you need to prevent yourself from falling into the trap of TMA (too much abstraction).
In my experience wrapping a library with a library has little value. However, wrapping multiple libraries to provide a useful abstraction through a composition like pattern is very useful.
Either way, engineering judgment needs to be applied liberally.
Keith,
Great post. It would have been great to be a part of that conversation. Glad you’re continuing it online now that the event is over.
One of the things that struck me in this is stating that you should treat your framework as a third party library. This not only has implications for how you develop the framework, but also how you use it.
If I’m implementing a third party library into my system, I like to build a facade in front of it – to protect myself from changes either from version to version of the library, or in case I have a need to swap out the library. It’s interesting to view an internal library from that perspective, although it does make sense.
@Bob
Understand the exercise of the open space was about building things that were “good enough”. It isn’t the end of the world, just looking at it from a different perspective. Hope that makes sense.
It all makes perfect sense. It just seems sad that we are turning our profession into something where we do “just enough”, rather than making things the best they can be.
You forgot one best practice… Use Drag and Drop and RAD features wherever possible 😉