Tuesday, May 26, 2009

Software Process and Motivation

There are two main factors (besides the obvious lack of free time) that keep me from posting more frequently to my blogs.  The first is a fear of mistakes.  I fear saying something dumb, whether it is just a simple typo or if it is not thinking through my ideas enough before committing them to the Internet.  The second is that it is all for naught because no one reads what I write anyway.  However, if I want readers I have to post regularly, and if I want to get better at writing, I have to keep doing it.  So, for me, a large part of writing posts is a psychological battle with myself.

When writing software, there are also motivation issues that prevent or slow down development.  I think one of the key reasons Agile has such vocal followers is that it addresses the psychology of programming, keeping developers happy and productive.

Fear of Mistakes

While Agile may not explicitly say "Embrace Your Mistakes", the idea of constantly refactoring along with a large suite of automated tests and continuous integration attempts to address this fear.

Useful Software

The other day I was reading a friend's blog (May Contain Blueberries) and he mentioned that he read and enjoyed my blog.  This gave me a huge emotional boost, which encourages me to keep writing.  Similarly, besides all of the tangible benefits to quality that a release early and release often philosophy that Agile has, there is the huge psychological benefit to the development team having people use their software.  Nobody wants to work on something that never sees the light of day.

Staying Productive

Other ideas that Agile methodologies tend to push are Pair Programming and No Overtime.    The No Overtime philosophy is explicitly about programmer morale and mentality and keeping them sharp.   Pair Programming also has this affect.  When pair programming, you are less likely to be distracted by emails about lolcats.  You also have a compatriot who is in the same boat as you, sharing your miseries and successes.

Developers are People

Basically it comes down to the fact that developers are people.  Keeping us happy and motivated is a key component to continually getting quality software over time.   And, while free snacks are a tangible way of accomplishing this (and let me tell you, the Google snack rooms are pretty awesome), process and business practices are more important over the long haul.


As a postscript - it seems that I must feel strongly about this.  I just noticed that I had already posted on Psychology of Extreme Programming.  Oh well.  If its worth saying once, its worth saying twice.  :)  Hopefully I made enough new points to make it worthwhile.

Saturday, May 16, 2009

Embrace Your Mistakes


All endeavors have their goof ups, and writing software is no exception.  There are two ways of handling with mistakes - try to prevent them, or try to fix them.  "Traditional" software engineering approaches focus on the former while "Agile" approaches focus on the latter.  Formal requirements and big-up-front-design attempt to prevent mistakes from getting into code.  Short iteration cycles with lots of customer interactions attempt to expose mistakes early and often so they can be fixed.

While the benefits of preventing mistakes is obvious, there are many less obvious benefits to embracing the mistakes and fixing them later.

Tangible

When you accept that mistakes are part of the business, you plan for them.  This leads to automated tests (to catch future mistakes), logging and other introspection techniques (like JMX) to catch and diagnose problems in the field, and hot patching or automated upgrades which have become par for the course in modern software - to fix bugs without a whole new release/deploy cycle.

These are obvious advantages and they can be (and are) used no matter what approach you take.  However, there are some psychological advantages to embracing mistakes which can really pay off in terms of getting software out the door and getting it right.

Psychological

Not being afraid of a mistake means you don't get paralyzed and can keep going.  When developing software there are countless decisions that have to be made, from small things like what to name a variable, method, or class to larger things like what data storage mechanisms to use.  With traditional approaches, your analysis step tells you everything you need to know to make the right decision.  However, in practice, often you don't have enough information, or things change.  This leads to extra long analysis and requirement gathering steps and the production of vaporware.

Accepting the idea that "it is ok to make a mistake now, because I can (and will) fix it later" is a huge step.  Once you do that, you can keep from getting bogged down with the unknowable.  Often it is by making a decision and seeing what the resulting software is, that you best understand the right decision.  For me, one of the huge advantages of subversion over CVS is the ability to change file names while keeping revision history.  Knowing that I can change a file name in the future keeps me from blocking while trying to determine exactly how a class will be used/morphed over time so I can give it the perfect name.  Instead I give it the name that makes sense today, and if the class changes over time, the name can be changed to match its new use/behavior.

However, allowing yourself to make mistakes is only useful if you also a willing to admit mistakes.  Admitting that a decision made in the past turned out to not be best is the only way that you can improve your software.  It can be hard to admit mistakes, which is why I titled this post the way I did.  If you embrace your mistakes, that means you are constantly willing to learn and improve, resulting in much higher quality software over time.


Saturday, May 2, 2009

Decouple Ideas, Not Code

Here's a situation that I have witnessed (ok, been involved in) multiple times in my career. You are writing software and you make an effort to "future proof it" so that it will be easy to modify when new requirements come. However, the future comes and it is still a big effort to change. This phenomena has led to the YAGNI philosophy and to my post about not writing reusable software.

All is not lost, though.  There are still things you can do to future proof your software, and decoupling components may be one of the most powerful.  But decoupling code is often not enough, you need to decouple ideas.

Example



Imagine you are developing a .NET website in C# with dynamic data coming from multiple different sources.  One of your sources is a Content Management System (CMS) where authors and editors can update some of the web pages in production without any developer interaction.  The CMS system works by providing the authors an editors with an interface friendly to them.  It stores their work in database tables, which  your .NET application can access.

In this particular application the CMS system has two types of pages "Generic Pages" and "Articles".  The Articles database table has columns like Content and Title which contain HTML data and NumberOfWords which is an integer.  The GenericPages database table has columns:  Body, DisplayTitle, and SidebarContent, which also contain HTML data.

An obvious approach to solving this problem is to create classes GenericPage and Article which know how to read from the database and have accessors for the various fields.  You probably also want a CMSHandler class which has methods for taking a unique identifier (e.g. relative path) and returning the appropriate GenericPage or Article.  Your website code access these GenericPages and Articles via the CMSHandler.

Decoupling



These CMS classes that you wrote seem like they should be decoupled from the rest of the application.  It doesn't seem farfetched that the CMS system will change.  Maybe the company providing it will be bought by Microsoft.  Maybe you'll decide to write an in-house system.  Who knows?

So with this thought in mind you create interfaces IGenericPage, IArticle, and ICMSHandler.  Now the rest of your code base is coupled to the interface, rather than the implementation.  i.e. your website code access an IGenericPage or an IArticle via an ICMSHandler.

Success! ... Right? ... Maybe not.

Future

Fast forward two years.  Your CMS provider is bought by Microsoft, and you decide to go with a cheaper competitor.  However, the new system is a little bit different.  Besides GenericPages and Articles, it also has FAQPages.  And the Articles table in the database doesn't have a NumberOfWord columns.

While you did decouple your code base from the CMS classes, you didn't actually decouple your code from the CMS system and all its assumptions.  Now that you have a new system, you realize it doesn't work the same way as the old system.  Your code base has to change anyway to handle the new system.

Decouple the Idea



So what's the solution?  Decouple your code from the assumption in the system you are using, not just the classes.  Do you really need to handle GenericPages and Articles differently?  Or are you just going to show the pages the same, but not show sidebars for the Articles?  Do you really need a word count?  Rather than looking at the features that are provided, consider the features you really need.  Write your interface classes to provide those features.   This may mean the interface hides some of the functionality that could be provided by the underlying mechanism.  It also means that you may have to add some functionality that wasn't there.  (for example, you decide you really do need a word count, even if it isn't provided by the CMS system).

In this example it means that your website accesses an ICMSPage via an ICMSHandler.  The fact that there are different types of pages like GenericPages or Articles is hidden from your website, since the website doesn't need to know this.

If you have successfully decoupled the assumptions of your code base from the assumptions of the CMS system, then you shouldn't have trouble replacing the CMS system.  Your interface should represent the minimal set of assumptions that your application makes.  Any CMS system that satisfies these assumptions should be easy to drop in.  Or at least much easier than if your decoupling mechanism still allowed all the assumptions of the CMS system to leak through to the website itself.