XNSIO
  About   Slides   Home  

 
Managed Chaos
Naresh Jain's Random Thoughts on Software Development and Adventure Sports
     
`
 
RSS Feed
Recent Thoughts
Tags
Recent Comments

Benefits of Behavior Driven Development (BDD)

Sunday, November 11th, 2012

Should you consider BDD for your team? I just wanted to share my experience with BDD, which you could consider as food for thoughts:

  • Why? – How often does your development team ask the business team why certain feature is important? More importantly, why now and how much of it is enough? In my experience with BDD, the approach naturally lends the teams to have a constructive discussion about this. I’ve seen this leading to a genuine collaboration between business and development. In short, BDD helps getting the right people to discuss the right amount (depth) of things at the right time.
  • Better commitment and buy-in: BDD lays very heavy emphasis on Business value. It forces the Business to justify the priority by showing concrete value. Also it helps the development teams to embrace the prioritizes set by Business, because they understand the thinking process much better. Interestingly, I’ve noticed that teams that practice BDD, I rarely see either sides throwing their weight around to push their pet features through. Also due to the focus on value, rarely I find teams building useless feature for the sake of proving productivity.
  • Ubiquitous domain language: By working together, the business team & the development team build a shared understanding by using tools/techniques like product discovery, story maps, user stories, acceptance criteria and scenarios to create an ubiquitous domain language. The ubiquitous language is usable/understandable not only by domain experts, but also by every member of the team. This goes a long way in reducing the complexity in the domain and making the barrier-to-entry much lower for new members.
  • Right focus: BDD can help you focus on the user’s needs and the expected behavior instead of jumping ahead and getting caught up in implementation details upfront. Also I’ve seen teams which are new to Test Driven Development (TDD), seem to focus too much on “testing” missing the point. BDD helps the teams focus on system’s behavioral aspects rather than focusing on testing your implementation. Over the years, we’ve learned that up-front analysis, design, planning and test planning, all have a diminishing return. In my experience BDD helps strike the balance.
  • Evolutionary Design: Agile (eXtreme Programming in particular) has killed the notion of “fully-specified, completely-detailed-out requirements upfront.” It is a well accepted fact that we won’t be able to figure out all the requirements when we are starting off with a project. BDD, at its very crux, embraces the fact of evolving product understanding and hence helps your system’s design evolve to keep pace with the changing needs.
  • Breaking the knowledge silos in distributed team: Having worked with distributed teams for over a decade, due to the distributed nature, one common problem I see is domain knowledge gap between the team members. Esp. teams which are away from the real business, have a hard time understanding and questioning the business requirements. Usually there are gaps or misunderstanding, leading to rework and frustration. Even if your team is not distributed, you might be familiar with the problems of knowledge silos. I don’t think BDD alone solves this problem, but at least it encourage teams to work more closely and reduces the gap. It also encourages a generalizing specialist attitude in team members, helping with other eXtreme programing practices like pairing, collective ownership, etc.
  • Greater ROI: Behavior has a much longer shelf life than your implementation and implementation related documentation. Also as the business rules change, BDD captures it better than it being lost in documents and code.
  • Predictability & Confidence: Also in my experience working with teams using BDD, I see that they have much better (or at least feel they have better) predictability and confidence in their work.

What’s your experience?

Also to clarify, what I mean by Business team and Development team, my definitions below:

Business Team: Folks who focus on “Are we building the right product.” This usually includes the following roles: Product Owner/Manager, Stakeholders, Product Designer (User Experience), Subject Matter Expert, Business Analysts, and so on.

Development Team: Folks who focus on “Are we building the product right.” This usually includes the following roles: Architects, Tech Leads, Developers, Testers, Graphics designers, Database administrators and so on.

Unit Testing Dilemma: Should I Invest or Not?

Tuesday, November 1st, 2011

Every single line of code must be unit tested!

This sound advice rather seems quite extreme to me. IMHO a skilled programmer pragmatically decides when to invest in unit testing.

After practicing (automated) unit testing for over a decade, I’m a strong believer and proponent of automated unit testing. My take on why developers should care about Unit Testing and TDD.

However over the years I’ve realized that automated unit tests do have four, very important, costs associated with them:

  • Cost of writing the unit tests in the first place
  • Cost of running the unit tests regularly to get feedback
  • Cost of maintaining and updating the unit tests as and when required
  • Cost of understanding other’s unit tests
One also starts to recognize some other subtle costs associated with unit testing:
  • Illusion of safety: While unit tests gives you a great safety net, at times, it can also create an illusion of safety leading to developers too heavily relying on just unit tests (possibly doing more harm than good.)
  • Opportunity cost: If I did not invest in this test, what else could I have done in that time? Flip side of this argument is the opportunity cost of repetitive manually testing or even worse not testing at all.
  • Getting in the way: While unit tests help you drive your design, at times, they do get in the way of refactoring. Many times, I’ve refrained from refactoring the code because I get intimidated by the sheer effort of refactor/rewrite a large number of my tests as well. (I’ve learned many patterns to reduce this pain over the years, but the pain still exists.)
  • Obscures a simpler design: Many times, I find myself so engrossed in my tests and the design it leads to, that I become ignorant to a better, more simpler design. Also sometimes half-way through, even if I realize that there might be an alternative design, because I’ve already invested in a solution (plus all its tests), its harder to throw away the code. In retrospect this always seems like a bad choice.
If we consider all these factors, would you agree with me that:
Automated unit testing is extremely important, but each developer has to make a conscious, pragmatic decision when to invest in unit testing.
Its easy to say always write unit tests, but it takes years of first-hand experience to judge where to draw the line.

Importance of Unit Testing and Test Driven Development (TDD)

Tuesday, November 1st, 2011

Why should developers care of automated unit tests?

  • Keeps you out of the (time hungry) debugger!
  • Reduces bugs in new features and in existing features
  • Reduces the cost of change
  • Improves design
  • Encourages refactoring
  • Builds a safety net to defend against other programmers
  • Is fun
  • Forces you to slow down and think
  • Speeds up development by eliminating waste
  • Reduces fear

And how TDD takes it to the next level?

  • Improves productivity by
    • minimizing time spent debugging
    • reduces the need for manual (monkey) checking by developers and tester
    • helping developers to maintain focus
    • reduce wastage: hand overs
  • Improves communication
  • Creating living, up-to-date specification
  • Communicate design decisions
  • Learning: listen to your code
  • Baby steps: slow down and think
  • Improves confidence
  • Testable code by design + safety net
  • Loosely-coupled design
  • Refactoring

Example of Test Driving Code with Events

Wednesday, July 6th, 2011

Following is a stripped down version of the actual code.

Start with a simple Test:

private static void ContinueMethod(object sender, EventArgs arg)
{
    ((Eventful)sender).ContinueExecutionFor("ContinueMethod");
}
 
[Test]
public void EventHandlerCanRequestFurtherCodeExecution()
{
    var eventful = new Eventful();
    eventful.ContinuationHandler += ContinueMethod;
    eventful.Execute();
    Assert.AreEqual("ContinueMethod wants to execute more logic", eventful.State);
}

and then wrote the production code:

public class Eventful
{
    public string State;
    public event EventHandler<EventArgs> ContinuationHandler;
 
    public void Execute()
    {
        // logic to get ready
 
        var args = new EventArgs();
        //stuff args with some data
        ContinuationHandler(this, args); 
    }
 
    public void ContinueExecutionFor(string delegateName)
    {
        State = delegateName + " wants to execute more logic";
        // some logic
    }
}

The wrote the next Test:

private static void StopMethod(object sender, EventArgs arg)
{
    // no call back
}
 
[Test]
public void EventHandlerCanStopFurtherCodeExecution()
{
    eventful.ContinuationHandler += StopMethod;
    eventful.Execute();
    Assert.IsNull(eventful.State);
}

and this went Green.

Then I wondered what happened if there were no registered event handlers. So I wrote this test.

[Test]
public void NoOneIsInterestedInThisEvent()
{
    eventful.Execute();
    Assert.IsNull(eventful.State);
}

This resulted in:

System.NullReferenceException : Object reference not set to an instance of an object.
at Eventful.Execute() in Eventful.cs: line 17
at EventTest.NoOneIsInterestedInThisEvent() in EventTest.cs: line 46

Then I updated the Execute() method in Eventful class:

public void Execute()
{
    // logic to get ready
 
    if (ContinuationHandler != null)
    {
        var args = new EventArgs();
        //stuff args with some data
        ContinuationHandler(this, args);
    }
}

This made all the 3 tests go Green!

When Should We Encourage Developers to Write Comments?

Sunday, May 15th, 2011

Many people will argue that there is more badly written code than good code. And its important to write comments to avoid these situations. Therefore we should encourage (force) people to write comments.

IMHO they are absolutely right that today many project suffer from poorly written code without any (good) comments. However every team I know, that suffers from this problem, has always been told (forced) to write comments. In spite of the emphasis on writing comments it has not really helped them.

I usually ask:

By asking developers to write comments are we really addressing the root of the problem?

.i.e. developers don’t invest quality time to write self-documenting code; code that clearly communicates its intent and does not require the deodorant of comments.

May be its time to try something different?

I have seen this myself many times, when we emphasize & educate the team on how to write clean code and ask them to stop wasting time writing comments, the code starts to communicate lot better. Its lot more maintainable. Also we have found that writing automated tests is a great way to document your intent as well.

This is how I would explain the concept Comments Smell to a team:

Writing comments that explain “how” or “what” the code does, what it does, is evil IMHO. Comments (esp. about what and how) is a clear failure to express the intent in code. Comment is a deodorant to hide that failure (smell).

  • If developers don’t invest time to write clear code, what is the guarantee that they will write clear comments?
  • Is doing a mediocre job at both (comments and code) better than doing a great job at just Code?
  • Will it actually be more productive to do both or just one?

Remember the biggest problem with comments it that they fall out-of-sync with code very soon. So its not just about the extra investment to write good comments, but also the investment to maintain them.

One has to think hard to write code that expresses intent rather than write some sloppy code with poor abstractions and get away (washing their hands off) by writing comments. Developers have to take responsibility for writing code that others can easily understand.

Having said that, there are times when “the why” (why we are doing something in the code, a particular way) is not apparent by just looking at the code. So if we don’t find a suitable way to communicate “the why” through code, comment is the fall back option.

Note that comments are a fall back option in “the why” case rather than a default option.

Agile is Counter Intuitive

Friday, November 26th, 2010

I hear many people claim Agile is just common sense. When I hear that, I feel, these guys are way smarter than me or they don’t really understand Agile or they are plain lying.

When I first read about test-first programming, I fell off the chair laughing, I thought it was some kind of a joke. “How the heck can I write automated tests, even without knowing what my code would look like”. You think TDD is common sense?

From traditional methods, when I first moved to monthly iterations/sprints, we were struggling to finish what we signed up for in a month. Its but natural to consider extending the time. Also you realize half day of planning is not sufficient, there are lot of changes that come mid-sprint. The logical way to address this problem is to extend the iteration/sprint duration, add more people and to spend more time planning to make sure you’ve considered all scenarios. But to nobody’s surprise but your’s spending more time does not help (in fact makes things worse). In the moments of desperation, you propose to reduce the sprint duration to half, may be even 1/4. Surprisingly this works way better. Logical right?

And what did you think of Pair Programming? Its obvious right, that 2 developers working together on the same machine will produce better quality software faster?

What about continuous integration? Integrating once a week/month is such a nightmare, that you want us to go through that many times a day? But of course its common sense that it would be better.

How about showing working software demos weekly/monthly somehow magically improving collaboration and trust. Intuitive? And also shipping small increments of software frequently to avoid rework and get fast feedback?

One after another we can list each practice (esp.the most powerful ones) and you’ll see why Agile is counter-intuitive (at least to me in early 2000 when I stumbled upon it).

Test Automation Dilemma

Thursday, June 24th, 2010

I regularly practice Test Driven Development. I truly believe in its benefits and also have been able to influence a huge number of develops to practice it.

However, there are situations in which I ask myself questions like:

  • Is it important to automate this particular check (test) ?
  • Will it be worth the effort/investment or is it YAGNI?
  • What is the possibility of this particular scenario breaking (risk)?
  • And so on…

Yesterday I was faced with a similar situation where I decided to skip the automated test.

Context: I was working on a website where users can use their credit card while shopping online. Basically the website had a simple text input box to accept the credit card number. It turns out that most browsers (except Safari) caches the input data and stores it in plain text somewhere on the computer.

So we wanted to turn off the auto-complete and caching feature on this specific input field. There is a very easy way to do this. Just need to set autocomplete=”off” in the input tag. For example:

<input type=”TEXT” name=”creditcard” autocomplete=”off” />

Its an easy fix and quite widely used. So that’s great. But how do I write an automated test for this?

If we think a little hard, there are ways to write automated test. But then you ask yourself is it worth it?

This site had lived without this feature for so long, so I did not think it was that crucial to its users. Even if this feature stops works, it won’t bring the site down. (They certainly had a good battery of automated tests which tests the core functionality if the product.) So I choose to skip the automated test. I manually tested it with different browsers made sure it was working as expected.

If this comes back and bites me, I’ll certainly invest in some form of safety net, but for now, time to hack some more code.

What would you choose to do?

Visualizing your Programming Sessions: New Product From Industrial Logic

Thursday, June 17th, 2010

This post is moved to Industrial Logic’s Blogic.

Mastering TDD with Deliberate Practice

Friday, June 11th, 2010

When I start and finish my 3 Day TDD Workshop, I make it clear to the participants that they will have to deliberately practice, on small pet projects or toy code, in a safe-environment ( in-the-nets, if you will), every single day, for a few months (if not years), to get really good at TDD. Deliberately practice on their design, testing, breaking-user-needs-down, pairing, and many other skills using TDD before they can use TDD for prime time.

However, post the workshop, the participants are very excited and they ignore my humble advice. Next day they go back to work and start applying TDD on their production code. While this might look like a good thing (also making managers super happy too.) Over the years, I’ve realized that this pattern is actually destructive. Without the required amount of practice, the excitement soon dies out. And developers start falling back to old habits. Many times leaving a total mess behind.

I was surprised to see very few companies or teams continue and build on these practices, while 80% of them would only use parts of it and fall back. Every time I went back to a company and saw this, I would be very depressed. So I studied what the 20% did, which the 80% did not.

  • Were the 20% way smatter or talented than the 80%?
  • Did the 20% have better management support, less delivery pressure compared to the 80%?
  • Or the 20% worked on simpler projects with no legacy code and so on?

What I found was the 20% quickly realized that they did not have enough skill to apply TDD on their projects. So they:

1. Watched Screen-casts: Watched experts do TDD on real projects. Good starting point: Let’s play TDD by James Shores or this stackoverflow answers

2. Open Source Projects: Studied and gradually started contributing small patches to open source projects, which used TDD. JUnitCucumberJBehaveFitFitNesse, etc. are all great examples.

3. Small Pet Projects: Started TDDing small pet projects. Gradually practiced in a safer environment and once they acquired enough skill and confidence, then they start applying TDD on their production projects.

In addition to practicing on their pet projects, on their own, they also took 2 hrs every week (on a fixed day of the week), as a whole team, to practice Test-Driving (TDDing) the same problem. During these social-learning sessions, they practiced Pair programming too.

Logistics: Before the meeting, one of the team member sent out the problem to everyone. On practice day, the whole team gathered in a conference room/team area, picked their pairs, set aside 90 mins to TDD the problem. After 90 mins, few pairs did a quick code walk-thru and explain their solution with important decisions they made during the session. Followed by an open discussion. [I also recommend everyone checks-in their code in some common repository, so it can be used for reference by others.]

Sample Problems: Next big question is, what problems do we use for Test Driving?

Usually I recommend starting with simple programs like:

  • Games – Tic-Tac-Toe, Snakes and Ladders, or any other board game.
  • Utility Programs – Convert Roman Numerals to Decimals, Diff 2 files, IP to Country Mapping, etc

Once they practiced enough with simple programs, then they would take some large design problems from DesignFest and try to TDD them. The beauty of these problems is, they are quite big, can take up-to a week to finish it completely. Now we are talking something semi-real world, where

  • We have limited time to solve/program a complex problem, which needs to be simplified.
  • Try to find a relevant System Metaphor that can help you visualize the design
  • Do a quick and dirty, low-fi Interaction Design to understand how the user will use this
  • Identify and prioritize the crux/essence of the problem, figure out what is the most important, what will give us fastest feedback
  • Further thin-slice the identified piece of functionality and
  • Then try TDDing it.

This truly helped them get better at:

4. Code Smells Poster: Created a big poster with all the code smells listed on it. Paste the poster in their team area. Every time anyone from the team found a code smell in their project, that person gets up and adds a dot next to the code smell. This makes everyone more sensitive to these smells and increases awareness by making things visible. (Simple game mechanics.)

5. Refactoring Fest: Picked one of the pungent code smell from their code, and organized a RefactoringFest. Meet as a group (once a month.) Developers pair with each other and everyone tries to refactor the same code on their project to eliminate the specific code smell. [Make it clear that the code will not be checked-in after refactoring. Its a learning exercise and we need a safe environment where people don’t fear touching code. Also if you need some real world code snippets to try refactoring, check out my refactoring teasers.]

6. Blog/Diary: Started writing a blog/diary to capture their learnings and list of issue that got in their way of applying TDD on their project. Writing things down really helped them internalize their learning. [Many times when I’m stuck with a problem, I start writing things down, and the answer becomes obvious to me.]

7. Form a Book Club: As a group, they picked any TDD related book of their choice. Then they decided on a chapter and met over lunch once every week. Everyone came to the meeting after having read that chapter. They used the meeting time to highlight the key-takeaways, debate on the subject and if possible demonstrate it via code.

8. Hands-on Geek-Conference: They participated in a geek conference like Code Retreat, CITCon or Simple Design and Test Conference where they got to meet other practitioners and experts. Got an opportunity to pair with them and learn from their experience plus share your own experience. [Stop wasting your time on stupid marketing conferences.]

9. Teach: They taught a course on Unit Testing or Design Principles at an induction program for new employees or at a local user group. [Teaching is the best way of learning.]

Deliberately practicing this way for a few years to really appreciate the depth and benefit of TDD.

I know TDD coz…

Friday, May 14th, 2010

Just because you know the syntax of a programming language, does not mean you know programming

Just because a toddler can make some sounds, does not mean she can speak

Similarly, just because you write tests before you write code, does not mean you know TDD.

TDD is a lot more than test-first. IMHO, following concepts let’s you truly experience TDD:

  • Evolutionary Design,
  • Acceptance Criteria,
  • Simple Design,
  • System Metaphor,
  • Thin Slicing,
  • Walking Skeleton/Tracer Bullet and
  • Interaction Design

How long does it take a dev to be well-versed with TDD?

Depends on the dev, but atleast a couple of years of deliberate practice on projects

What can we do to become TDD Practitioners?

Start with deliberate practice in safe env. Then gradually start on your project.

    Licensed under
Creative Commons License