20/06/2012

TDD in practice: Where does it fit in?

Lately I've been delving deeper into Domain Driven Design and Test Driven Development.

If you asked me two months ago; do you know and/or use test driven development? I'd say - yes, but I only write tests for algorithms or methods with expected results or behavior.

Since then, my view has changed.

The question I was asking was not how to do test driven development, but rather when?

Let's take a look at the well known rules for TDD set out by uncle Bob:
  1. You are not allowed to write any production code unless it is to make a failing unit test pass.
  2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
These are great rules. Too bad most developers don't know how to implement them.

It becomes pretty clear why, when we examine what I was implying two months ago.

We can only test against known results and behaviors.

We struggle to incorporate TDD into our coding practices because we are focused on code, instead of context.

Domain driven design gives a neat explanation of a domain; Whenever a context is implied, a boundary is formed.

Ubiquitous language implies that by classification, an appropriate name can be given for a domain entity that describes its context and purpose.


As an example, I'll describe an User within different contexts of healthcare.

A person that uses a system, is called a user.
A person that needs to be billed, is treated as an account. (Accounting)
A person who has clinical data, is considered a patient. (Clinical)
A user, may be a patient.
A user, may be a doctor.

Let's classify the above into User Roles (roles a user may fulfil) and Domain Entities
User Roles: patient, doctor
Domain entities: account, patient

The reason why we struggle to test domain entities is because we never define them.

Let's take a look at the average programmers model abstraction evolution:

In the beginning
UI -> Database

After we've learnt about presentation patterns
UI -> View Model/Presenter -> Database

After we've learnt about ORMs
UI-> View Model/Presenter -> Data Model -> Database

At this stage, another level of abstraction comes along if you're doing SOA
UI -> View Model/Presenter -> Data Transfer Object -> Data Model -> Database

Let's look at the last example in terms of context:

  • The UI defines the data of the View Model (or rather, the View Model contains the data for UI).
  • The DTO contains the data required by the View Model (the View Model also has UI specific properties like state unlike the DTO).
  • The Data Model represents the structure of how the object is stored in the database.
  • In a simple case, the DTO is effectively a partial 'view' of the Data Model.
The reason why we are struggling to practice TDD is because nowhere in this chain is anything represented in the domain (meaning we don't know where to apply the boundaries/rules).

We are effectively just mapping the one object to the other along the chain.

Let's add in the Domain Entity.
UI -> View Model/Presenter -> Data Transfer Object -> Domain Entity -> Data Model -> Database

What's interesting here is the fact that by simply adding the domain entity, we have given context to the entire chain. For example, the View Model/Presenter UI validation should mirror/conform to that of the Domain Entity.

The role TDD plays in DDD is that of verifying that the domain boundaries (or rules) are in place.

By defining boundaries, you create context. Context, in turn allows you to define behaviour which creates structure. Structure leads to reuse and better code.

Disclaimer: TDD in itself has many benefits and other use cases outside DDD.

In my opinion, the main reason why you should adopt TDD is because it takes the fear out of modifying and extending an existing system, because you can verify that everything works as it should.

We have learnt that just because a system builds successfully, doesn't mean it works the way it should.


17/04/2012

We build boxes

Today I will take a more philosophical approach to software development.

We as developers are faint to admit that our golden goose is building boxes.

Consider for a moment how many authentication and user management systems you have implemented.

Every one of them are similar in many ways - but never entirely reuseable.

Our golden goose is building boxes.

We take ideas and build a box for it.

Often clients will request something that the system wasn't design to do - because the new idea doesn't fit into the old box.

I guess what I'm trying to say here is that (designing the box) constraints are important.

In a sense we are always trying to build boxes for ideas. One for every part of the system that will be neatly stacked into the big box that is the final product.

Modular programming is rarely applied to general scenarios. The responsibility of a box (module) should be defined (even if barely) to keep in mind how it will fit into the big box.

There is no excuse not to plan your boxes and how they will to form your final product.

I think building boxes is a natural reaction to software change requests.

Despite the almost negative character I have portrayed regarding building boxes, they are definitely important.

I have seen (and experienced) many times that businesses suffer because of a lack of constraints in quoting projects for clients.

To define your box and sticking to it requires commitment - in business this is essential to guard against the never-ending stream of new ideas.

Don't be ashamed, embrace building boxes and you will get better at it.


22/12/2011

How the Internet fried your brain

No army can withstand the strength of an idea whose time has come.
Victor Hugo
Ever imagined a world where original ideas were the norm?

That wasn't too long ago...

Before the Internet

Lets consider a century prior to ours, when everthing was local - stores, services, social interaction and worries.

Back then, all you had to do was make it work where you live. Which is still the case today.

To make ideas work; you need persistence, patience and perseverance to bring that idea to realisation.

L&P - Laziness and Procrastination
Everyone wants more time because they waste it away browsing or socializing away on the internet for hours, reading up on all the latest news and gossip and sitting hours on end infront of a screen.

The easiest product/service to sell nowadays are ones that enable laziness and procrastination. We have proactively dubbed this - consumerism.
 
Take care not to believe by being lazy and procrastinating yourself - you will bring your big idea into the world!

Unique ideas 
To bring your unique idea into fruitition, this is what you'll need to know:
To succeed in life, you need two things: ignorance and confidence.
Mark Twain
So here are a couple of rules:
  • Be ignorant but not stupid
  • Have confidence but not headstrong
  • Be humble but not a pushover
  • Have faith and do not doubt
Don't go looking for problems to solve - and definitely don't ask people for ideas. I reckon the only good time to ask people for business/idea advice/feedback is when they are potential or existing customers.

The Big Question
Why do a lot of people fail doing business?

Simply because they aren't working on their idea. Pun implied.

11/12/2011

The Challenger: Larger Size Matters

Our biggest challenger, is not ourselves - but our perspectives.
Image from ideachampions.com


Think small

We believe worthy challenges are bigger than us.

You may have heard some people perform better under stressful situations, while others crumble.

The truth is; persistent challenge-seeking causes fear to perpetuate in most people.

We make everything harder than it is. Fear and anxiety are partners; anxiety will woo you over while fear breaks you apart.

We are big, problems are small

We live in a challenging world, we constantly find a need to challenge ourselves because everyone else is doing it.

I believe beauty is in the eye of the beholder - and so is a bad perspective.

We are actually big, problems are really small. It's Occam's razor: simpler explanations are, other things being equal, generally better than more complex ones.

Big problems are made up of little problems

Well that's obvious, we just don't believe it.

So lets try this instead:
Any big change consists of many small changes.
or consider this quote:
"We have not really looked too hard at low priced stocks over the years. Then we started to look for stocks that could gain hundreds, or even thousands of percent, and we found ourselves with small cap penny stocks. ~ William McKinley

The real challenge lies in the preparation of solving these little problems.

And remember, every small change has an effect.

07/12/2011

3 reasons to include developers in strategy meetings

I'll aim to keep this short and sweet:
“When you're building your strategy around the user, it changes the business imperatives. This world of Web services really is not about the technology itself, it's about business. The business issues are so much at play that they are really more important than the technology.” Herman Baumann quotes
In the end it's all about the business. Software. Strategy. Customer Support. Sales team. Project Managers. Developers. Techies.

Not a lot of software businesses get this and they opt to exclude developers from strategy meetings.

1. You can't code what you don't know
Programmers need to know the industry, because after all - you can't code what you don't know.

2. Know what works and what doesn't
Programmers, UI and UX designers are generally familiar with the needs of their users and are usually the first to know when something doesn't work the way it's supposed to.

3. We create things others use
In general, over a period of 3 years a developer working at a dev shop will probably gain experience developing up to or over 20 applications that consumers or businesses use. In essence, you could almost equate applications developed to businesses started 1 to 1 - or in this case 20 businesses.

Now, wouldn't it be silly to exclude the developers from strategy meetings?

After all, they are the ones who will be doing the work.

14/11/2011

Stop Smoking

Many IT professionals I know, have or are currently smokers.
But sometimes the shoe doesn't fit, especially if you're working in the medical industry.

Last week myself and my wife switched to using TarGuard without reducing the amount of cigarettes we were used to smoking every day.

It is a lot harder for heavy smokers (20+ cigarettes a day) to stop smoking. Well, at least it used to be!

I have found the real cause behind unbearable withdrawal symptoms relating to stopping smoking to be the non-nicotine ingredients in cigarettes.

I was suprised when I first discovered that I was experiencing withdrawal symptoms while using TarGuard and Nicorette to supplement nicotine levels (TarGuard reduces nicotine levels).

At first I thought I was going crazy, but this simply proves a majority of withdrawal symptoms come from the non-nicotine ingredients of cigarettes (tar, cyanide etc.).

It seems to me like smoking hurts the lungs and also numbs them at the same time, so when going without a cigarette for a while - your lungs start hurting again.

Using TarGuard for a week entirely reduced the pressure/pain withdrawal symptoms for me. Currently, I am only using Nicorette (4mg) and swapping to the Nicorette (2mg) later this week before I stop entirely.

Now the only withdrawal symptom remaining is a slight irritability which is easily conquered by staying busy.

If you're a smoker, at the very least consider using TarGuard to reduce the damage of smoking almost entirely to your lungs!

09/11/2011

ASP.NET MVC - Extending HtmlHelper

Today, we will be looking at extending the HtmlHelper for ASP.NET MVC in C# using .NET 3.5sp1/4.

Lets look at some introductory basics:
Syntax for creating Extension methods
public static class {extensionclassname}
{
  public static {returntype} {methodName}(this {objectToExtend} {name})
  {
  }
}
So lets say we want to create an input helper, we could do something like this
public static class HtmlHelperExtensions
{
  public static InputHelper<T> Input<t>(this HtmlHelper<T> htmlHelper)
  {
    return new InputHelper(htmlHelper);
  }
}

public class InputHelper<T>
{
  private readonly HtmlHelper<T> _htmlHelper;

  public InputHelper(HtmlHelper<T> htmlHelper)
  {
    _htmlHelper = htmlHelper;
  }
}

Although it's not necessary to create a separate class to hold the methods for the input helper, it is preferred because of separation of concerns (SoC).

Next, we would add the namespace wherein the HtmlHelperExtensions is located to the <namespaces> section under pages < system.web.webPages.razor in the Web.Config located in the Views directory.

To access our input helper, we would call @Html.Input() and from there on custom methods to render a MvcHtmlString (which is a string - already safe for use as razor output - a normal string would be html encoded).

Here is an interesting use case:
Lets say we want to wrap html in a <div class="input"><- html here -></div> without having to manually write out <div class="input">....</div> every time?

This is done pretty easily, lets add a method to our existing InputHelper<T> class:
public MvcHtmlString Wrap(Func<object, HelperResult> htmlToWrap)
{
  var htmlBuilder = new StringBuilder();

  htmlBuilder.Append("<div class='input'>");

  htmlBuilder.Append(htmlToWrap.Invoke(_htmlHelper));

  htmlBuilder.Append("</div>");

  return MvcHtmlString.Create(htmlBuilder.ToString());
}

Here is an example on how to use this method from within a view:
@Html.Input().Wrap(@<text><label for="name" />@Html.TextBox("name")</text>)

The @<text>...</text> being passed to the method can be seen as a view which gets 'compiled' to html. So instead of writing to ouput:
<label for="name" />@Html.TextBox("name")
  using  htmlToWrap.Invoke(_htmlHelper) compiles down to
<label for="name" /><input type="text" id="name" name="name" />

HtmlHelper extensions are miracilious in the sense they can give you extreme refratoring capabilities and can do much more than one expects.

For example, I have written input extensions that simply calls
@Html.Input().TextBoxFor(model => model.MobileNo)
which in turn adds a label and applies mask behavior and validation logic to the element (behavior and validation via unobtrusive data-* attributes that javascript applies).

All in one line of code - and you could do the same!