As programmers we constantly use frameworks and libraries while developing new applications. Most of you will probably never deal with frameworks or library design nevertheless a certain amount of knowledge of the topic is useful even working on standalone applications.
The following article is an introduction to the differences between these entities and how they interact to produce a consistent and maintainable product.
We will look at their different roles and scopes, when we need one or the other and the best practices for our development cycle.
The last part contains several tips to write a good library I’ve collected in these past years.
The right tools
There are fundamental differences between the roles of application code and framework/library modules within a project.
Framework/libraries provide reusable services that encapsulate lower-level functionalities by providing an higher abstraction to the inner complexities of certain features.
Typically libraries stay static within the development of an application, at least besides occasional upgrades: application code utilises the functionality provided by the modules to create a specific behaviour for the logical interaction between users and a domain of data in a generally tighter-defined environment.
So, while the application code is constantly changing as the application evolves and develops, framework and libraries provides fundamental building blocks behind the structure of the product.
Stable framework/libraries are one of the key principles behind a successful application; picking the right tools heavily influences the result and future evolution (in terms of expandability and complexity) of the project, so we need to take care in their choice.
There a good quote to illustrate today’s life of every developer:
”In programming, it always comes down to one thing: choosing the right tool for the job. Programmers are faced with many tools. Too many. Have you heard the expression “paradox of choice”? That sums up the IT world. The “shall we build our application with a library or a framework?” is just one of many decisions facing us, but it can be an important one. A team with many junior developers may be better off with a framework, enforcing structure and standards, telling them how to build the app; an application that’s not run-of-the-mill and has niche functionality might work better if a library is used, to allow greater flexibility and control.” — Dave Clayton
The application level is where abstract functionality land to a concrete realisation: is where we focus more on interacting with our data model and define the structure of our information and how our actions affects that data. As programmer this is the place where most of us spent a work day.
Typically application’s level must contain only the code which is strictly relevant the application domain.
If when moving from app to app you still use or — worse yet — write the same boilerplate code, probably its time to think about an abstraction.
Duplicate code means duplicate means more chances of errors and more effort and reworks to fix and maintain the same stuff.
When working at application level our first choice is to pick the right paradigm of development; a common paradigm to use to describe applications is the model-view-controller pattern (MVC). There are lots of different paradigms we can use, with pro an cons; within the last few years we have seen Viper, MVC, MMVM, Redux just to quote few of these.
BTW, thank God, the goal of this article is not to talk about that :]
Library & Frameworks: its a matter of control
The key difference between a library and a framework can be summarised in a word: IoC — Inversion Of Control.
- When you use a feature from a library you are in control.
- With a framework the control is inverted; the framework use you: it’s just like The Hollywood Principle: “Don’t call Us, We’ll call You”.
What’s a Library
A library is essentially a set of functions that you can call, these days usually organised into classes.
The scope behind is to produce reusable code for a domain specific area; libraries simplify specific tasks by providing a set of generic functionalities ready to be used in a control flow.
Use of appropriate libraries can reduce the amount of code the need to be written. It will tend to reduce line of code counts for an application will increasing the rate at which functionality is delivered.
In most cases, it is better to use a library routine than to write your own code.
What’s a Framework
Software framework can be defined as an architecture which facilitates implementation of software in a well organised manner.
A framework embodies some abstract design, with more behaviour built in.
In framework, all the control flow is already on-place and there are a bunch of predefined hooks where you can place your code.
In fact a *framework defines a skeleton where the application defines its own features to fill out the skeleton.*
You can think to a framework as collection of patterns and libraries to help building an application.
As we said above the framework dictates the architecture of your application: it will define the overall structure, its partitioning into classes, the key responsibilities thereof and how the objects collaborate.
A framework predefines these design parameters so that you, the application designer/implementer, can concentrate on the specifics of your application. The framework captures the design decisions that are common to its application domain.
Framework or Libraries?
Frameworks thus emphasise design reuse over code reuse.
The main advantage of a framework over a library is clear: it is a matter of superficiality.
When you have a library you need to understand the functionality of each method and it’s relatively hard to create complex interactions as you to invoke several methods to get the result.
Frameworks, on the other hand, contain the basic flow and since you only need to plug in your behaviour its easier to do the right thing. With less efforts to put in it seems framework appears to be the best choice we can do when creating a new product.
There are however several key downsides:
- Framework is like a marriage: it’s good until is not good anymore. Writing a product above a framework invariably distorts the architecture of the product: your entire app and all features are dependant of the possibilities offered by that tool. A free jail exit is not permitted unless you want to rewrite everything; features are permitted inside the bounds of the framework and you are invariably tie to who supports the framework itself. If you plan to make a long-time product you should think carefully about your choices.
- Framework cultivate ignorance: Programming becomes a victim of marketing: they promise us a magic button that will solve all of our problems.
While frameworks have certain advantages, they cultivate ignorance: programmers does not know much about the underlying architecture, they just learn a short-life technology which tends to become obsolete in 1–2 year; moreover they are very limited expanding their products at the price of using just a small portion of the entire framework.
There is a good provocative post about this topic you should really read: “Do Not Learn Frameworks. Learn the Architecture”.
Studying frameworks, you have to relearn, moving to new solutions that appear all the time, and a part of your experience will be erased.
But when you learn principles — they stay.
How to write a good library
During the past years I’m involved writing lots of libraries and tools: some of these are published on Github, some others are internal assets of the companies where I’ve worked.
During this time I learned several tips you can follow if you want to write a library:
- Think from the user’s perspective: when making a library its easy to be focused on the implementation and forget the user; its important to think about what the user/programmer want to achieve, not how we want he use it. A good book on topic is “Domain-Driven Design: Tackling Complexity in the Heart of Software” by Eric Evans.
- Focus on the use-cases: Use-Case defines how the user will user your tools to achieve a specific actions. It’s important to make a list of the use cases ordered by importance/frequency. With this list you can prioritise what the library should expose and the better way to handle it. You can’t hide or simplify all the complexities but you can provide a solution which is the best 9 times out of 10.
Your API must be: obvious, consistent and in tune with the scope of the library.
- Keep in mind: Abstraction fails. If you want to solve a complex problem then you have to be really careful when writing the library; a good knowledge of the problem help you to make a good abstraction and it’s the base of every good library.
This reminds me a Joel post called “The Law of Leaky Abstractions”: ”Abstractions fail. Sometimes a little, sometimes a lot. There’s leakage. Things go wrong. It happens all over the place when you have abstractions.”.
- Don’t forget pro users: while the main goal of a library is to hide the complexity of the underlying layer sometimes is good to leave the door open and allow your pro users to define, redefine and use low level parts of your library.
- Total control is a mirage: some problems are too complex and can be broken down in sub-problems: this mean smaller and more-focused libraries instead of a single fat one.
- Sometimes abstraction is not the answer: abstraction can became a double cutter; you may found which leaving the problem open and complexity visible maybe the best compromise.
Writing a Framework
If applications are hard to design, and libraries are harder, then frameworks are hardest of all.
The main scope of designing a framework is to gambles that one architecture will work for all applications in the domain.
Any substantive change to the framework’s inner design would reduce its benefits considerably, since the framework’s main contribution to an application is the architecture it defines.
Therefore it’s imperative to design the framework to be as flexible and extensible as possible.
During the last years frameworks are becoming common and important because it reduces the complexity of building bigger tools and allows even small companies to join bigger challenges.
Larger object-oriented applications will end up consisting of layers of frameworks that cooperate with each other. Most of the design and code in the application will come from or be influenced by the frameworks it uses.
During this short travel you have seen the importance of the tool you use in your everyday life as programmer, the difference between them and several suggestions to move your level one step forward thought the abstraction:
Ability of abstraction is key requirement for every senior developer and the best way to produce long lived product you are able to expand and evolve.
Even if only a small part of you will have the opportunity to work on design and the creation of bookcases, the knowledge of the subject is important even in the conscious choice of the tools to be used.
Choosing to use one tool rather than another is a decision that belongs to the whole work team and is strictly related to the type of product or project that you intend to develop: it will be the times, the degree of flexibility and the needs of the product itself that will guide this choice which entails, as we have seen, advantages and disadvantages in both cases.
In software design, the best choice will be the one that will best manage to enhance the entire project by adapting to its constraints and needs to achieve the goals.