YAGNI - Ya Ain’t Gonna Need It
What is a Framework?
Why Do We Build Frameworks?
Are In-house Frameworks Worthwhile?
- Complexity before split: N2
- Complexity after split: 0.6 * N2
- App: (1.1 * N/2)2
- Framework: (1.1 * N/2)2
- Total: 2 * (1.1 / 2)2 * N2
When to use 3rd Party Frameworks
- Does it do what you need it to do?
- Does it meet your performance goals?
- Is the source open?
- Can you look at the source code? No matter how good the documentation is, there are always questions it doesn’t answer. If the source is open, you can get definitive answers. If not, you will be flying blind.
- Is it OpenSource?
- Can you contribute improvements back to the project?
- How clear are the maintainers about what sort of contributions are acceptable?
- Can you fork the project? This is only a last resort, but it is nice to have as an option. If you expect to fork early, you will be mostly maintaining your own, in-house framework. The problem with this is it is a codebase no-one in your organization knows well. Seriously consider writing your own in-house framework from the start.
- How difficult will it be to switch frameworks later?
- How much of your code will directly interact with the framework?
- If you are picking a UI framework, most of your code will be tied to that framework. Changing frameworks later probably means rewriting the app from scratch.
- If you are using an encryption framework, like, say, md5, only a line or two of your app will use it. Changing that framework later is usually trivial.
- Momentum. Usually there are multiple options for the same type of framework. Eventually, some die out and some thrive. It’s a good idea to use a tool like Google-Trends to determine which projects are thriving and which are dieing. If a framework dies, you may need to fork it to maintain it, and then you are back to maintaining an in-house framework.
- Direction. 3rd party frameworks evolve outside your control. It is important to not only assess the current technical merits of the framework, but also, where is the framework going? What values and goals does the controlling team have? What values and goals does their organization/funding have? If your use-case is not squarely in their target use-cases, seriously consider looking elsewhere.
When to Write an In-House Framework
- Is it the best of modules?
- Is the interface simple?
- Will the implementation be well isolated and minimally leaky?
- Is there a reasonable chance you’ll reuse the framework on other projects? YAGNI argues you should be cautions making assumptions here, but if you think there is a > 90% chance you’ll reuse it even once, this can be a big factor.
Frameworks Clarify ThinkingFrameworks have another benefit beyond reducing complexity. Once you have isolated part of your code in a framework it takes on a life of its own. It has purpose beyond just serving the current app (though it should still be driven by that app's requirements ala YAGNI). A framework begs for clarity in its purpose. By drawing a line between your app and your framework you have to start thinking clearly about what belongs where.
Don't expect to nail the framework's "purpose" in the first pass. Your framework will evolve as YAGNI drives it. Over time, though, clarity will emerge and you will have a new, powerful tool, codified in your framework, but also in your mental toolbox for solving and thinking about programming problems.
Writing Frameworks is Hard - and WorthwhileI don't want to make this seem easy. Writing the best of all possible modules is hard! However, it is a learnable skill. You are only going to learn a skill be practicing it - a lot.
And what about YAGNI? Writing frameworks and YAGNI are not in conflict. You can write frameworks while observing YAGNI. After all, DHH, one of the strongest proponents of YAGNI, wrote Ruby on Rails.
- I measure codebase size in parse tokens rather than lines of code. Though still only an approximate measure, they are much better than LOC. They are the smallest meaningful unit in code. LOC measures several aspects of code which are ignored by the compiler including comments and whitespace.
- Codebase complexity can be understood in terms of graph-theory. Complexity comes from the number of possible interactions within the code. In the worst case, if you have N bits of code (tokens), you can have as many as N * (N - 1) or roughly N2 possible interactions. In practice the relationship between code-size and code-complexity is somewhere between O(Nk>1) < CodeComplexity(N) < O(N2).
Modular design is all about reducing the number of interactions a chunk of code has with the rest of the code-base. This is how modules help reduce complexity.