The Frameworks vs Libraries debate is evergreen. Just to make things clear, my mental model here is:
- Framework: Someone else's code is in the drivers seat. Your code gets invoked by someone else's code.
- Library: You are in the drivers seat. Your code calls external code.
There was a recent post about this I really liked: "Write Libraries, Not Frameworks". The HN discussion is also on-point.
I mostly agree with that post. As a user, I prefer external dependencies that are libraries not frameworks. But there are definitely places where I would like to use a framework — for example, I don't usually want to cobble together every part of a modern web framework from smaller libraries.
If you are using a framework, please follow this rule of thumb though: You can use multiple libraries in a single project, but you're only allowed to have one framework.
Here's why:
-
Frameworks are monolithic and opinionated pieces of code. You have to write your code in a way that works with the framework.
-
Having two (or more!) frameworks in the same application means trouble.
-
The frameworks won't be designed to work well together.
-
Your code will need to be twisted to meet the needs of each framework. Your code will need to serve as a glue layer, just to overcome the impedance mismatch between these frameworks.
-
The end result will be something brittle and harder to maintain.
Let's take a concrete example:
-
Dropwizard is a Java framework that's more minimalistic compared to most JVM frameworks.
-
Out of the box, Dropwizard does not support Dependency Injection12.
-
You might be tempted to put in a dependency injection framework like Guice.
-
By experience, I can say that this is a mistake. You will lose sight of how Dropwizard is meant to work3, and you will have to debug issues caused by integration between Dropwizard & Guice.
-
I've personally wasted time debugging such issues.
- Examples: Why isn't this resource wired properly? How does scoping of injected objects work? Why does application startup take a long time? How do I hide a route from the application when I'm not ready to launch it?
-
With benefit of hindsight, I would either:
- Not use dependency injection when using Dropwizard.
- Or, use a framework like Spring Boot which has built-in support.
This is a simple rule of thumb that I try to follow for all my applications: two frameworks + single codebase = bad idea.
- Technically, it uses HK2 internally. But this is not really exposed, and the Dropwizard docs don't mention HK2 at all.↩
- I should really get down to writing my thoughts about dependency injection one day!↩
- The feeling I get whenever I use Dropwizard is that of a simple, minimalistic framework. Something like Flask with Python. Doing magic seems counter to the goals of using a lightweight framework. Dependency injection is magic. If you want more features, why not pick a framework like Spring Boot instead?↩