This is the sixth and last instalment in a series of articles about six core principles that my team, a software development team, and I compiled in order to develop a framework for decision making. The reason for building the framework was to build a common understanding of how we want to work. Writing it down allowed us to easily transfer that knowledge to new colleagues and to spread the word.
All to often products get cluttered with features that someone believes might be useful, without the actual need for them being verified. Feature creep makes a product more expensive, not only in regards to development cost, but more importantly also in regards to maintenance. One should avoid developing a feature, if you ain’t gonna need it.
A system can be said to be overengineered if it is more complex than necessary. Experience shows that implementation of unnecessary features are often based on assumptions that don’t prove true. Premature optimisation, and performance optimisation in particular, lead to design decisions that turn out to be wrong and cause unnecessary costs.
Premature optimization is the root of all evil.
– Donald Knuth
Code bloat denotes code that is unnecessary complicated, e.g. over-abstraction, redundancy or wrong use of design patterns. The code base becomes difficult to understand, unclear and difficult to maintain.
Feature creep is a term to describe the ongoing addition of new features in a product to go beyond its core functionality. They cause unnecessary complexity.
Long Development Cycles
Implementing unnecessary features goes at the expense of the core functionality and may delay the launch of a product.
KISS – Keep it simple, stupid
Simplicity should be a key goal in designing systems and unnecessary complexity should always be avoided. The KISS principle states that most systems work best if they are kept as simple as possible.
Make things as simple as possible, but not simpler.
– Albert Einstein
YAGNI – You Ain’t Gonna Need it
Less is more: for every feature one should ask whether it is really needed. If it is suspected that the phrase “you ain’t gonna need it” applies to a given feature, then you should not implement it. It is better to implement a feature when it’s really required than beforehand and based on wrong assumptions.
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
– Antoine de Saint-Exupéry
A system or product should be continually improved, thus ensuring that it matches best practices and remains readable, clear, extensible and testable. When a product ist bo extended with a new feature, it’s important to ensure through refactoring that it remains consistent as a whole and doesn’t deteriorate to a patchwork.
TDD and Continual Automated Testing
Apply test driven development (TDD) and automate tests at all levels to avoid regressions. Recurrence of errors that have occurred in the past can be avoided.
Continuous Delivery and Deployment
Short release cycles and continuous deployment of new features enables short feedback cycles. Thus, products are promptly tested in production like environments and can be validated.
Smaller and More Manageable Code Base
Omitting unnecessary features a product becomes simpler and clearer. This also reduces the training period for new engineers and users.
Unnecessary features don’t require maintenance, thus leaving more time for further development.
Shorter Development Cycles
Focussing work on implementation of required features reduces development time. You only implement what is actually needed.
Tested and Proven
Because there are no unnecessary and thus unused feature, overall the application is better tested.
If one considers the total cost of ownership of a feature, the cost of maintaining it may significantly exceed the cost of implementation. By exclusively focusing development to features that are actually needed leaving out everything “you ain’t gonna need” the product will be ready faster, implementation will cost less and the it will be easier to maintain.
From Dev-Team with ❤