At the beginning of your programming carrier, the fact, you can do technically anything in many ways, may cause you to feel overwhelmed. It’s like trying to decide what to eat in the restaurant serving a thousand dishes. Before you will quickly go through the menu, it turns out it’s late, and you are asked to leave. Hungry. The same problem shows up when you are asked to write your first professional program. There are so many questions in your head, so many doubts on how to make it properly. You are a rookie, so you wrap up your sleeves and start coding everything from scratch. Sure, it takes you some time, but hey, thanks to this you have everything under control, you don’t have to learn some other people’s stoopid and over-engineered approaches. You can do this better, don’t you?
The truth is, you actually can’t. The vast majority of problems you will need to solve as a programmer, have already been solved. There are thousands of battle-tested and proven pieces of code used in every programming project out there. Wasting time for something already done, will get you a nice torture chamber after you go to hell for doing such things :)
Libraries
One of the concepts, that makes our industry so cool, the almighty library. Only god knows how much do we owe them, how much work, tears and frustration they saved us. And what is even cooler, in most cases they are totally free. Not just free like the free lunch, but they also give you freedom of reuse and reshaping it to your needs. You can even ask an author for some help, the chances are he or she will help you. This is basically an idea behind Free Software and Open Source.
Back to the topic, libraries are your friends, because they provide you some functions, routines or classes, to help you deal with most common problems, the date for that matter. All you have to do, is to instantiate a Date class, and there you go, you can do anything like adding or removing time intervals, getting day of the week or just nicely formatting human-readable form of a given point of time. Now imagine how much work it would be to write this kind of Date handling library by your own. Think of all the bugs you would introduce to your project, making it unstable and unpredictable. Thanks to the library concept, you can just import it (probably from the standard library of your programming language), and use this deeply tested and widely used piece of code without any issues.
Frameworks
Since libraries are specialized in solving particular problems, they don’t put any constraints on your code architecture. They are imported anywhere in your code and just used, giving some results like new Date or array of numbers. They don’t care about architecture of your code, because this is not their responsibility. They just do one thing, and they do this as well as they can. The idea behind Framework is different.
According to Wikipedia, Framework is a structure, which supports other things built on top of it. The word structure suggests something more complicated than just do small, but perfect, and this is a thing here. Let the typical Web Framework like Django or Symfony be our example.
Typically, a Framework can be characterized as having two traits:
- it uses a lot of libraries
- comes with constraints on directories, files, classes and functions naming and/or placing
It goes without saying, that having a hand-picked, widely used set of libraries puts you in a comfortable position of quick development and deployment of your project. There a fine and convenient wrappers on anything you can imagine, from HTTP or CLI input and output handling, through database abstractions like ORM, to standardized logging and configuring of your application. In many cases, you have everything configured on a sane level, so you don’t have to worry about anything, but to develop features that drive the business, especially in MVP phase.
At first glance, the idea of all the naming conventions in a given Framework seems to be useful. Especially, when you are a junior developer, who has been introduced to some Framework lately. Wow, everything seems to be so easy from now on. All you have to do, is to put your files in some special directories like:
- controllers (or actions)
- entities (or models)
- events
- services
- etc.
Then you have to add a special suffix or prefix to the classes, or use some annotations to decorate your code with abilities like handling HTTP params or mapping objects directly to your database tables. You are a big fan of Frameworks now, you still wonder where have they been through all this time. It saved your six many times, especially when requirements were changing fast from one iteration to another. Some other people were hired to the project, because they knew the Framework, so they could start bringing value to the project from day one. They could, right? Well, the first two yes, but six months and fifty models later, the picture was not so perfect as in the beginning. What went wrong?
Directories and Files Structure
It all came up after the new programmer have joined the project. On his first day he had cloned the repository and after opening it in his IDE, he saw a set of Framework-constrained directories. They are named generically after the type of component they hold, like controllers or entities. It means, that if you want to trace the streamlining of creating a new order, you have to navigate through all the directories in search of order model’s involvement. Isn’t it frustrating?
Lack of Architecture
What is even worse, the Framework works only on a project root level, so it doesn’t force you to use any specific architecture in your contexts. It is up to the team to decide, what architecture (if any) will be used on the module level. If they don’t agree on some kind of boilerplate, if the code grows in many different ways, it will quickly become a big ball of mud, which is a classic term for the disaster.
Data Hardwired To The Business Logic
Another feature, which is a two-edged sword. On one hand, it provides you with a super-fast development environment, all the forms, views, fetching and saving, is done with single lines of code. The setup usually involves providing a dsn string to your database and voila, you may provide a CRUD operations in the blink of an eye. But there are some downsides as well. The more code and functionalities you create, the tighter coupling becomes between the data and its source. Also, since the data models with their respective providers lays in different directories, they also become lowly cohesive. What a paradox.
Too Much Dependency On Libraries
The last thing, which can actually bury the project quicker than you think. You may be surprised, especially because it was said at the beginning, to use libraries as much as possible. And this is valid, until you use them wisely and in proper places. It usually doesn’t hurt to use some nicely abstracted APIs on generic level like views or database handlers. Using external dependencies in the domain layer also seems to be a good idea, once again it makes your life easier and your work quicker. All is nice and fun until the disaster comes. Imagine you have used three external packages on your business logic level. Hundreds of calls are spread across the project, many bigger and smaller components are build on top of these three libraries, being there from the beginning. What are the threads?
The first library was abandoned by the author, right after some critical bugs were found by the community. Now your application is vulnerable, because library allows the attacker to browse and print your source code files just by sending prepared request to the web server. Because half of the logic is based on this library, you cannot simply removed it and become safe. In such a situation, you have basically two options. You can fix the library yourself, what comes with learning and fixing process, which may be time-consuming. The other option is to rewrite your business logic, so you are not dependent on external resources, but try to explain it to the stakeholders.
The second library quickly become a bad choice, because it provides only a fraction of functionality you need right now. The best solution here, is to start developing a missing features in-house, but it also doesn’t come for free. There is a learning curve, and you also need to host the package in some way. Not difficult, but requires some time and resources to handle properly.
The last case was the least dramatic of them all. The man behind the library decided to make it payable, if you wanted to receive actualizations and security patches. He dedicated himself to support his work on full-time, but he also needed some money for the living. It makes some additional costs from your side, but what you get is a piece of a well written and reliable software. Another problem is out of your hair.
Should I Use Frameworks?
This article is not against the idea of the framework. This is a great tool that takes some repeatable, generic tasks out of your shoulders, automates development and deployment, lets you create prototypes quickly. It is great when it comes to manage requests and responses, conduct simple CRUD operations or quickly validate new concepts. Frameworks come with great documentation, clean and modular code and with huge communities built around them, so you can get a hand almost instantly. Using a Framework doesn’t exclude using a proper software architecture, these two things are complementary. The most important, is to separate your business logic from the Framework layout and external libraries. Your code should be compatible between frameworks, not because you will change them (what is also possible, framework support can be dropped), but to be independent of environment it runs. Basically, this is one of the characteristics of good software design.