Tuesday, November 22, 2011

You Ain't Gonna Need It!

"Always implement things when you actually need them, never when you just foresee that you need them.", Ron Jeffries

One of the rules of extreme programming is “Never AddFunctionality Early”.  This concept is also often referred to as “You Aren’t Gonna Need It” or YAGNI.  The basic idea is to only add features when you need them, even if you are absolutely sure you will need it later on.  Yes you may very likely need the feature one day, but you never know what the future holds.  Building something you don’t need is obviously a waste of time and even when you do need it, by the time you get there it’s often different in some way than what you previously envisioned.  Following this principle keeps your system uncluttered, simple and meeting the requirements without extra work.  

Time and time again in software engineering the product owners and engineers suggest adding some “small” piece of functionality into the current release that is planned for a future release, or not planned at all.  It’s easy to be tempted to add something because it seems easy or seems like a good improvement to the product but this is almost always a bad idea.  To understand this I want to walk you through an example:

In our case we have already done some designs for future releases of the product and for this example we’ll keep it simple by referring to two releases: V1 and V2.  We have a field on the UI which is dependent on several attributes.  Some of these attributes are to be populated in V1 and others added in V2.  When it came time to build this UI field, the product owners made the suggestion that we add the attributes for V2 to the data model even though they will just be empty for V1.  Seems easy enough right?  Just add some fields to the data model that are always NULL and have the UI rules already in place.  According to the product owners this was even better in some respects because we’d have all the attributes defined that we’re going to need already and when we write this UI algorithm we only need to do it once and won’t have to change it in V2.  Let’s look at the many reasons this is wrong:

Time spent (however seemingly small) adding any unnecessary (at least for now) functionality is time taken away from adding necessary functionality

Generally speaking time spent moving toward a solution is more important than time put towards a fully complete solution.  At some point things need to be done, where “done” does not necessarily mean total completeness.   Don’t lose sight of the need for progress and shorter term milestones. This should be applied not only to the overall release, but also to iterations during the release.  For example if something is needed for the release, but not for the current sprint than you should not detract resources from achieving the current sprints goals.

Another important consideration here is that things aren’t always as simple as they appear.  Even adding some simple DB columns has impact on data access layer (entity objects, etc), data import tools, SQL queries, database performance, etc.  We’ve all had experiences where a “simple” feature turned into Pandora’s Box.

Time changes all

If you can predict the future you should probably be in a different job.  Until a feature is actually needed and committed to it is difficult to fully define what it should do.
Imagine V2 is scheduled for two years after V1.  Can you really be sure this design is sufficient for that time?  Are you sure of your customers and their needs in the future?  Even some database fields that seem so basic and immutable can easily change their meaning over time. The logical data model is always a moving target and it would be naive to think it won’t change again. 

Half supported functionality has no benefit to the customer

Putting in some work to get a head start on the next release is not for the customers gain.  It will only end up causing problems when they try to use this functionality or it gets in the way of something else.  

Code bloat

As unnecessary changes are added, the code base becomes larger and more complicated which is against our principle of simple design.  Keeping your code ready for unexpected changes is not about adding extra functionality or flexibility; it’s about a simple design.

Documentation

Even unused or partial features may require documentation.  In our example every field in the data model must be documented and that takes effort.  Also I don’t want to be the one explaining why a column might exist that is not really used.

Snowball effect

Adding one piece of functionality opens up the door to adding other pieces.  This results in the dreaded “feature creep”.  In my little example if I cave on adding these V2 attributes, it becomes hard to draw the line on including all V2 attributes into V1.

Extensibility

Now-a-days applications are being built to be very extensible by the customers.  If you’re adding something to be used by a very small (if at all) percentage of your customers, then perhaps its better accomplished as a custom extension by that customer in the first place rather than complicating your horizontal offering for everybody.  If you’re only partially meeting the requirements, then the customer is going to have to do work anyway to enable this functionality.  In that case the head start you gave your customer is probably not worth the time it took you to add it.

Refactoring

Would refactoring eliminate this functionality?  You should already be constantly refactoring your application to make it simpler and/or faster.  If you add something that would be flagged for removal according to your refactoring principles, then why add it all?  In this example some database columns that are never actually populated would certainly be flagged in one of my reviews.


To summarize, adding functionality you don’t really need is usually a bad idea.  Adding partial functionality is almost always a bad idea. As a development manager you need to focus on the current needs and constantly remind yourself what those needs really are.  Use common sense and be open to adding features that make sense and will be used immediately but remember that most of the time that new piece of functionality is not easy, is not better and is not faster to add now than later!

No comments:

Post a Comment