XNSIO
  About   Slides   Home  

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

Outside In or Inside Out?

Thursday, April 1st, 2010

Based on an open space discussion at GOOSgaggleRachel Davies wrote this interest post on Is Working Outside-In Always Better? (in the context of TDD)

This is one of my favorite topic. So I’ll freely express my thoughts here:

When I was doing my little “Avatars of TDD” experiment, I found TDD practitioners could take the same problem and approach it using either the Outside-In or the Inside-Out approach quite nicely. Obviously each person had their preferences. Also the tool used, the choice of programming language and paradigm influenced their technique quite a bit. I could see trade-offs in both scenarios. So I don’t believe in ONE best way.

Personally I don’t choose just one style. Depending on various criteria (listed below) I choose which approach I’m going to start with. I & most programmers I know go back and forth between Outside-In and Inside-out.

I tend to make the decision based on the following criteria (just a list of things that comes to my mind right now, I’m sure there are many more criteria):

  • Familiarity with the problem – How clear the problem & its solution is.
  • Stage of the feature/Project
  • Prior Knowledge/Experience with the technology stack and implementation details
    • If its completely unknown, one might spike it out or build a throw-away prototype. Having the prototype in front of you, can influence which way you start.
  • Whether your goal is to go breath first or depth first.
  • Whether your goal is to get low hanging fruits first (easy first) or core first (highest risky items first)
  • Whether you are driving the design or validating the design (test driven or test first).

Inside-Out and Outside-In also applies at a product level. Which massively influences our development style. For Ex: if the original idea about a feature/product is about a core feature that needs to be built. We could start building just the core idea, getting feedback and then slowly flush out the rest of the system as we build inside out.

It appears to me that, this topics needs a lot of context. Any discussion outside that context might dumb down the importance of this topic.

Goodbye Simplicity; I’m Object Obsessed

Monday, October 26th, 2009

In retrospect, I think Object Orientation has tremendously helped me become a better programmer. But at the same time, its also made me vulnerable to including extra complexity (or at least thinking in terms of more complex solutions) in my code.

One of the important lessons I learned a few years ago was, not to try and model my software on real world (my perception of reality). This leads to my software solution ending up as complex and easy to misunderstood as the real world. Soon I started embracing “There is no Spoon” philosophy and really focusing on abstractions.

Last year, I was again caught red handed, trying to sneak in too many objects (and hence complexity) into my code. This time I was pairing with another developer new to TDD and we were building a Snakes and Ladders game using TDD. The focus was really demonstrate TDD in a very different context.

(I’m sure everyone is aware of the Snakes and Ladders board game).

Snakes And Ladders

30 mins into the pairing, we had the following classes with wonderful tests for almost each class:

  • Game
  • Board
  • Player
  • Dice
  • Snake
  • Ladder

Just then Sandeep Shetty was passing by and he looked at the beautiful piece of mess we had created. He was surprised how royally we were wasting our time. The following 15 min discussion helped all of us realize how we were so caught up in TDD and coming up with all those (useless) abstractions when simply we could just have

  • one class called Game (place holder, the class is not really required) with
  • one method called move(int number_on_the_dice)
  • a list to hold the current position of each player on the board (there can be more than 2 players)
  • a hashmap with starting and ending points on the board (represents both the snakes and ladders, how does it matter whether its a snake or a ladder, they are just starting and ending points on the board)
  • a counter to calculate player’s turn
  • and … and what? …that’s it

Can you beat the simplicity of these 15 odd lines of code? Its not really about the number of lines of code, its about the conciseness and simplicity of it.

Refactoring Teaser IV is another great example of “Death by Objects” pattern. Solution Summary highlights the real difference.

I would also suggest reading Embrace Simple Design, an analogy and a recent example of Object Obsession.

TDD Overview Slides from Houston APLN Meeting

Tuesday, October 6th, 2009

Embracing Context Objects with Fluent Interfaces for my Tests

Thursday, September 24th, 2009

Of late I’ve been toying around with a new way of using Fluent Interfaces with a Context Object for my Tests. Esp. when I’m using Mockito.

In this post (Fluent Interfaces improve readability of my Tests), I’ve taken an example and demonstrated how I’ve evolved my tests to be more expressive. In my quest for getting my tests to communicate precisely to-the-point by hiding everything else which is noise, I’ve stared exploring another way of using Fluent Interfaces.

Following is an example:

1
2
3
4
5
6
7
8
9
@Test
public void redirectSubDomainsPermanently() {
    lets.assume("google.com").getsRedirectedTo("google.in").withSubDomain();
    response = domainForwardingServer.process(requestFor("blog.google.com"));
    lets.assertThat(response).contains(StatusCode.PermanentRedirect)
                             .location("google.in/blog").protocol("HTTP/1.1")
                             .connectionStatus("close").contentType("text/html")
                             .serverName("Directi Server 2.0");
}

lets and on are both Context objects which provide fluent, domain specific api to make the test very easy to read (communicative and expressive). It also helps me hide all my mocking/stubbing related code.

If you compare this with the original code, you can get a sense of what I’m talking about:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void redirectSubDomainsPermanently()  {
    when(request.hostName()).thenReturn("blog.google.com");
    when(request.protocol()).thenReturn("HTTP/1.1");
    when(request.path()).thenReturn("/");
    domain.setDomain("blog.google.com");
    domain.subDomainForwarding(true);
    domain.setForward("google.in");
    response = domainForwardingServer.processMessage(request);
    assertStatus(StatusCode.PermanentRedirect);
    assertLocation("google.in/blog");
    assertProtocol("HTTP/1.1");
    assertConnectionStatusIs("close");
    assertContentType("text/html");
    assertServerName("Directi Server 2.0");
}

Another example showing the Context object and Fluent Interface style is

1
2
3
4
5
6
@Test
public void avoidRestrictedWordsInIds() {
    lets.assume("naresh").isARestrictedUserName();
    List<String> suggestions = suggester.optionsFor(naresh_from_mumbai);
    lets.assertThat(suggestions).are("[email protected]", "[email protected]", "[email protected]", "[email protected]");
}

As I said, I’m still toying around with this idea. If this works well, may be it will be part of some mocking framework soon.

There is No Spoon (Objects)

Monday, June 15th, 2009

In OO, frequently, we get caught up in modeling our objects based on our perspective of the real world. Since everyone’s perspective is different we end up with a lot of thrashing and confusion. We end up arguing about these models in the air, baselessly. For example in a Veterinarian Information System (system responsible for billing and patient history), we end up arguing whether the Patient class should have a getShot(Vaccination) or should the Doctor class have a giveShot(Vaccination) method. In the end (when we finally start implementing the system) we realize that it really does not matter who gives the shot or takes the shot. What really matters is that we have recorded what shot was given to which patient. So we end up creating a Visit class with a method called add(Procedure).

Long story short, there are no real-world objects, its all how we perceive things. If we try to model our software based on our understanding of the real world, the software would also be as complex as our understanding of the real world. Since in software we are dealing with creating abstractions, we really want to focus on behavior rather than Objects. TDD is a great way to do this.

We start off with a test which expects that our system will exhibit some Behavior. At this point, we don’t know or care about which Object/s will provide this behavior. To make the tests work, we start creating methods that we need from our objects on the test for the time being. Once we have our test working, then we ask yourself, where does this behavior really belong? Sometimes real world objects pop-up. Sometimes we create Objects that don’t exist in real world. This is important because it helps us make our design simpler and more expressive. Slowly we expect more behavior from our system (by writing new tests) which starts flushing out our objects.

The I Naming Convention

Saturday, June 13th, 2009

I don’t like the I<something> naming convention for interfaces for various reasons.

Let me explain with an example. Lets say we have IAccount interface. Why is this bad?

  • All I care is, I’m talking to an Account, it really does not matter whether its an interface, abstract class or a concrete class. So the I in the name is noise for me.
  • It might turn out that, I might only ever have one type of Account. Why do I need to create an interface then? Its the speculative generality code smell and violating the YAGNI principle. If someday I’ll need multiple types of Accounts, I’ll create it then. Its probably going to be as much effort to create it then v/s doing it now. Minus all the maintenance overhead.
  • Let’s say we’ve multiple types of Accounts. Instead of calling it IAccount and the child classes as AccountImpl1 or SavingAccountImpl, I would rather refer to it as Account and the different types of account as SavingAccount or CreditAccount. It might also turn out that, there is common behavior between the two types of Account. At that point instead of having IAccount and creating another Abstract class called AbstractAccount I would just change the Account interface to be an abstract class. I don’t want to lock myself into an Interface.

Personally I think the whole I<something> is a hang-over from C++ and its precursors.

Some people also argue that using the I<something> convention is easy for them to know whether its an interface or not (esp. coz they don’t want to spend time typing new Account() and then realizing that its an interface).

The way I look at it is good IDEs will show the appropriate icon and that can help you avoid this issue to some extent. But even if it did not, to me its not a big deal. The number of times the code is read is far more than its written. Maintaining one extra poorly named Interface is far more expensive than the minuscule time saved in typing.

P.S: I’m certainly not discouraging people from creating interfaces. What I don’t like is having only one class inheriting from an interface. May be if you are exposing an API, you might still be able to convenience me. But in most cases people use this convention through out their code base and not just at the boundaries of their system.

In lot of cases I find myself starting off with an Interface, because when I’m developing some class, I don’t want to start building its collaborator. But then when I start TDDing that class, I’ll change the interface to a concrete class. Later my tests might drive different types of subclass and I might introduce an Interface or an Abstract class as suitable. And may be sometime in the future I might break the hierarchy and use composition instead. Guess what, we are dealing with evolutionary design.

Naming Style of my Test Methods is changing…

Sunday, May 24th, 2009

Long back, I’ve moved away from naming my test methods as test<something> to should<do_something>. 

1
2
3
4
    @Test
    public void shouldIgnoreDuplicateDocuments() {
        ...
    }

For the last year or so, I’ve moved away from the “should” naming conversion as well. These days my tests look like:

1
2
3
4
    @Test
    public void ignoreDuplicateDocuments() {
        ...
    }

More examples:

1
2
3
4
    @Test
    public void removeDocumentsBasedOnName() {
        ...
    }

From a Domain Forwarding server code:

1
2
3
4
    @Test
    public void redirectDomainsWithSubDomainsAndPathPermanently() {
        ...
    }

To think about it the “should” just seems redundant and lots of times gets in the way of freely expressing what behavior you are trying to drive.

Won’t TDD kill my Productivity?

Thursday, May 21st, 2009

Let me ask you, what do you mean by productivity?

Number of Lines of Code (LoC) committed per unit time….ahhh….I know measuring LoC is a professional malpractice.

May be, number of features committed per unit time….ahhh….ok…it does not end when I commit the code, it also has to be approved by the QA. So lets say number of features approved by the QA per unit time.

Well all my features are not of same size and they don’t add same value. So really measuring number of features does not give a true picture of productivity. Also just because the QA approved the feature, it does not mean anything. There could be bugs or change requests coming from production.

How about using function points or story points or something like that?

Really? You are not kidding right?

Let me ask you something, what is the goal of software development?

Building software is not an end in itself. Its a means to:

  • Enabling your users to be more productive. Making their life easier.
  • Helping them to solve real business problems, faster and better
  • Providing them a competitive edge
  • Providing new services that could not be possible before
  • Enabling users to share and find information more rapidly, conveniently
  • Automating and simplifying their existing (business) process/workflow
  • Innovating and creating kewl stuff to play with
  • And of course making money in the process
  • And so on…

Keeping this in mind, its lame to measure or think about productivity as amount of software created. I’ve never meet an user who wants more software. What users want is, to solve their problems or to enable them with the least amount of software. (no software is even better).

To be able to really help your users, you need to build the least amount of software that will not only solve the problem but will also delight them. Get them addicted to your software. IMHO, that’s the real goal of software development. One needs to use this goal to measure productivity (or anything useful for that matter).

So

  • Checking-in code
  • Having the QA approve it
  • Having it deployed in production

None of these is worth measuring. For a minute, get out of your tunnel visioned coding world and think about the bigger context in which you operate. Life is much bigger. Local optimization does not really help.

I recommend you read my post about: Why should I bother to learn and practice TDD?

Why should I bother to learn and practice TDD?

Thursday, May 21st, 2009

My 2 cents, based on personal experience:

  • With TDD, I’m a lot more confident about my solutions. If I spot a design improvement, I can quickly jump in and fix it with confidence. When given feedback, I’m able to respond to it quickly. I feel I’m in control.
  • It really helps me keep my design and code minimalistic and clean. No bells and whistles. No buy one get one free combo offers. <Perfection in design is achieved not when there is nothing more to add, but rather when there is nothing more to take away>
  • Turns out that my code is lot more easier to test. Because its designed to be testable. Lots of people argue that they will write tests after writing the code and it would be more efficient. The biggest problem I find with this approach is that the code ends up being something not readily testable. Then either I’ve to spend time making it testable or I skip testing saying its not possible or not required.
  • It helps me build a safety net of executable, living, up-to-date specification for my classes and features. Its a great starting point for new team members to understand my software. Tests are a great reference point for someone who wants to use my code.
  • TDD is a great teacher. It helps me listen to my code and learn from it. It forces me to pay close attention to what is happening. Its easy to spot bad things faster. Its all about feedback and visibility.
  • TDD forces me to slow down and think. It encourages me to take baby-steps. Sometimes I find people are in such a hurry that they spill mess all over the place. It takes soo much more time and effort to clean up the mess they leave behind.
  • My tests tend to communicate my design choices much longer after I’m gone.
  • I massively reduce the amount of time I spend in the debugger or trying to manually test (monkey test) from the UI. When something breaks, I no longer need to crawl through the logs to figure out where things are going wrong. I get pin-pointed feedback.
  • TDD helps me maintain focus on measurable outcome (producing software that accomplishes a concrete objective). I’m not longer drifting down ratholes.
  • TDD also helps me reduce the hand-overs between developers and tests and hence the wastage introduced because of all that overhead and context switching.
  • And so on…

Having said that, TDD alone is not sufficient to achieve the above. At times you need to spike/prototype things. One needs to have (or at least start focusing on building) a good knowledge of Design Principles and Patterns. Its easy to get lost, having a pair can really help.

Again I don’t want to sound dogmatic. I don’t think TDD is the only way to build great software. There are lots of great developers out there, building amazing software without TDD. However I think TDD is a much easier approach to achieve the same.

MbUnit to NUnit and back

Wednesday, March 18th, 2009

Recently I was helping a team @ Directi working on a .NET project. They were using MbUnit for unit testing and acceptance testing. The team was using VS 2008 as their IDE. (Seriously its a joke to call VS as an IDE).

As I was pairing with one of the developers, I was watching him make code changes, hit F6 to build the project and then switch to MbUnit UI to run the tests. What a freaking waste of time! Ideally I would make a code change and hit a keyboard shortcut to execute the tests.

So I suggested that we use ReSharper plugin or at least use Test Driven .Net . But the big problem was that ReSharper does not support MbUnit, it only support NUnit. So we looked at what was different in MbUnit that was not in NUnit. The main thing that stood out was RowTest feature. But then we soon found NUnit extension for RowTest. Great!

So we went ahead and changed all our MbUnit tests to use NUnit. (It was a breeze). But then, when we tried to run the tests inside VS using resharper, it was detecting all our test fixtures but did not detect any tests in them. Only later, we realized that ReShaper does not support RowTest extension.

So we simply reverted to MbUnit and installed the MbUnit Resharper Plugin to run MbUnit tests from ReSharper.

    Licensed under
Creative Commons License