Framework vs Library
By: Muhammad Siraj
Tags: React, Libraries, Web Development, Framework, Programming

When working with developers or creating something without help from anyone else you regularly discover such words as “Framework” and “Library”. Be that as it may, do you understand what they mean and what you should think about them? In this article, I will show you the advantages and disadvantages of every one of those standards and a portray in which cases you ought to pick one over another. I will likewise show you contrasts among them and depict how to utilize them. As an illustration, I will utilize Symfony, which is incompletely a framework and mostly a library.

Library

The library is described as “a collection of implementations of behavior, written in terms of a language, that has a well-defined interface by which the behavior is invoked.”

The principle

What does it mean? To understand libraries we need to go back to the beginnings of libraries. One of the biggest issues back then was how complicated the code was. Since applications had to be written as a whole, when they got bigger and more advanced, the number of bugs drastically increased. In 1959 JOVIAL introduced a way to split an application into smaller parts. The new solution became a basis for what we now know as libraries.

The next big step was the implementation of the so-called “Linux way” or a “KISS Rule” (KISS= Keep It Simple, Stupid). To fulfill the latter any module or library had to do one thing and do it well. Combining this with the “Divide and conquer” principle (in which every difficult problem can be split into multiple smaller problems, which are then independently solved) we get the current library system.

Examples

Let’s say we want to use a database. In PHP it’s quite simple. All we need to do is connect to a database, prepare the question we want to ask, and get the answer.

This example of pseudocode shows how to do it:

$config = ... //load config

$query = ... //some query

$data = ... //data for this query $conn = mysql_connect($config['server'], $config['user'], $config['password']);

if($conn === false)

throw new Exception('cannot connect to database'); $success = mysql_select_db($config['databse']);

if($success === false)

throw new Exception('cannot select database');



$queryString = $query;

foreach($data as $key => $value)

{

$queryString = str_replace(':'.$key, mysql_escape_string($value), $queryString);

} $queryHandle = mysql_query($queryString, $conn);

if($queryHandle === false)

throw new Exception('query failed'); $result = mysql_fetch_assoc($queryHandle);

if($result === false)

throw new Exception('query failed');

Quite a bit of work, isn’t it? And now imagine that you have to do 5 versions of this code for various databases. It can get messy very quickly. And this method is already using a library (yes, mysql_* functions are functions provided by a library called php-mysql)!

Let’s try to use a library called PDO:

$config = ... //load config

$query = ... //some query

$data = ... //data for this query $pdo = new PDO($config['uri'], $config['user'], $config['password']);

$statement = $pdo->prepare($query);

if($statement === false)

throw new Exception('query failed'); if($statement->execute($data) === false)

throw new Exception('query failed');



$result = $statement->fetchAll(PDO::FETCH_ASSOC);

if($result === false)

throw new Exception('query failed');

We not only reduced the code size from 20 lines to only 12 but at the same time allowed other databases to be used. Why is this so powerful? Because PDO library is internally using a different library, which is using another library, which is… This chain means that when you write a blog you don’t need to worry about resolving database address to IP or preventing SQL injection. It’s all done for you by the library, so you can create the blog you are working on — you just “do one thing and do it well”. That is the power of libraries.

Disadvantages

Just like every other solution in the world, libraries also have disadvantages. There are two main issues you can step upon. First is so-called bug propagation, second library limitations.

Bug propagation

Let’s assume we are working on a library that is going to be used to calculate map distances — I will call it B. It’s using a calculation library that allows adding, subtracting, multiplying, and dividing — it’s going to be called A. Someone is also using our library on their website, which is marked as C. In this scenario website, C depends on library B that depends on library A.

Now, what happens if library A has a bug? Let’s assume that adding two numbers always results in a number increased by 1, so 1+3 = 5, 4+4 = 9, etc. It will end with library B also showing wrong distances, while website C will also be incorrect. What is described here is a bug propagation — a bug in dependency will cause a bug independent.

Now let’s assume we fixed that issue by modifying library B to always subtract 1 after the calculation. But after some time a patch for Library A will come out that fixed the problem. Now our library is a source of problems because we are needlessly subtracting 1. This is called derivative bug propagation.

The longer the chain of dependencies, the bigger the issue. Multiple libraries on the path can have workarounds for bugs in their dependencies, which will cause new bugs and propagate them down the line.

Limitations

When using libraries, their internals is often hidden from you. This is done on purpose, so a library is kept in a known state. Because it can do a limited amount of things, it’s easier to debug it by for example covering all possible actions a library can do with unit tests. But at the same time, you might need to do some small tweaks on internals or get some information this library cannot give you. There are three ways of solving this problem:

The first one is to just give up. If you are asking for something a library cannot do, then maybe you should not ask for it, or just use a different library. In most cases, this is the best idea, because other solutions may cause some trouble.

The second solution is “the advanced way”. If a library is of good quality, it often has three modes in which it can work: simple, normal, and advanced. A good example is a music library I used a few years ago. To play a song until the end you had to just call:

player.play("filename.ogg");

In normal mode you were able to add some extra parameters to it, such as this:

music = player.load("filename.ogg");

music.setVolume(0.75);

music.play();

sleep(10); //10 seconds

music.pause();

That library still gives you the ability to access the underlying backend library by doing something like this:

music = player.load("filename.ogg");

handle = music.getHandle();

call_system_function(handle);

Unfortunately, the advanced way is not that common, and many quickly made libraries don’t have more than one mode in which they can work. Therefore if you are choosing which library to use, check whether it has an “advanced mode”. Even if you don’t need it now, you may in the future — it’s always easier to make a change sooner than later.

The last solution, which is both the worst and the most commonly used, is hacking. Many languages have some backdoors you can use to access the library’s internals. And with those, you can do almost anything. Just remember, by using a library in a way that differs from its original purpose you’ll just ask for bugs.

Framework

The framework is described as “an abstraction, in which software providing generic functionality can be selectively changed by additional user-written code, thus providing application-specific software”.

The principle

Let’s analyze what that means. The first thing we should do is think about what “abstraction” means. Well, in programming it describes something that is half-finished when it’s up to an end-user (or end-class) to fill the gaps to complete it. Another thing to note about “abstraction” is that it already contains information about what those gaps are and how they should be filled. Let’s take an iterator as an example. Iterator is an abstraction that must have a way of getting the current object and moving to the next one. Similarly, a framework contains a list of rules that need to be fulfilled to make the finished product.

The second thing we should note about a framework is that it often combines libraries and “packages”. We already know what is a library, what about those “packages”? Each framework has its own name. In Laravel, they are called “packages”, in Symfony “bundles”, in other frameworks they may have different names. The easiest way to understand packages is imagining them as reversed libraries, where API is provided not by the library, but by a framework. This has a few consequences:

every package should instantly work in a specific framework,

package made for one framework cannot be used in other frameworks,

packages are often bound to specific versions of the framework since package API must exactly match framework API

If you look at this list, you may think that libraries are far superior to packages. Because of that, it’s a common practice to create packages as proxies to libraries and keep the functional code in the library itself. This way you will have advantages of both worlds.

Advantages

One of the biggest benefits of frameworks is the easiness of creating code. Let’s use the previous example of the database to check out Laravel:

$users = DB::table('users')->whereName('Hubert')->get();

Yes, we just changed all these lines of code (and the query itself) to a single line, making it incredibly simple to use databases. Everything related to handling errors and loading Eloquent (the library used to manage the database) is done for you by the framework.

Another advantage of using frameworks is their great support for the MVC pattern. The fact whether MVC is better or worse than Decorator (used by libraries), is a topic for a completely different article.

Disadvantages

Like everything, frameworks also have disadvantages. The biggest one is, in fact, the principle itself. Since the framework is an “abstraction”, it has a relatively limited amount of features you can make in “the correct way”. But it doesn’t mean it cannot be done in a “hacky way”.

For example, it’s common in object-oriented programming to give objects a toString function that will provide its human-readable text representation. If your program supports multiple languages, you will need access to a translator. Problem is, you don’t have access to the translator (or any other service) in Entities in Symfony.

Framework vs Library

Now that we know what frameworks and libraries are, let’s compare them, and find out where and when they can be used.

Master-Slave

The first and most important difference between framework and library is the master-slave model.

When using libraries you are the master. That means you are using the library and have control over its usage. You can create an object and destroy it, as well as manipulate it (based on libraries’ API).

On the other hand, the framework is using your code, so it works as the master. That means you don’t have control over what will happen and when which is the responsibility of the framework. The advantage is that you have fewer things to worry about, but you also have less control over what can be done. As I already mentioned, frameworks often tie your hands and prevent you from doing both stupid and useful things.

Flow of commands

In libraries, your code is calling a function and gets a response in return. On the other hand, the framework is calling your functions and you are returning responses. This has a tremendous impact on debugging. Since application flow is independent of programmers, it’s impossible to make breakpoint-based debugging, nor follow the flow of data to find issue. The only solution is to use stack traces and tools provided to you by the framework itself, while in libraries you can just look at data that goes in and comes out of functions to find the source of problems.

The core of an application

One of the biggest decisions you have to make is which core for your application you want to pick. You can either pick one of the existing frameworks or do it from the scratch. Depending on how complicated your project is, I would suggest getting the more fluent solution the more complex it gets. Therefore for a simple project, you should pick a framework that fits your problem best, such as Symfony (because it has a lot of premade components). For more complicated ones, on the other hand, I would suggest going with more configurable frameworks (eg. Laravel) or even making code by hand, just to keep good control of the project.

Divide and rule

As I mentioned before, libraries are based on the “divide and rule” principle, but packages used in frameworks can also base on it. Dividing big projects into smaller parts will make it much easier to control while it grows. That’s something you should consider when choosing a framework. When it (or its packages) has limited reusability (like eg. in TextPattern) it’s best to avoid using it for bigger projects.

Final verdict

If you want me to choose between framework and library, you will be disappointed. Each solution has its pros and cons. But for achieving the best results you should combine those two solutions. Use and write libraries for each small thing your project does, such as ‘shop’, ‘search engine’ or ‘file management’, create proxy packages for them, and use those packages in your favorite framework.

This way you will get good code quality, speed, reusability, and control (advantages of libraries), as well as faster programming, and support from the community (advantages of frameworks).