Developing Software Together

TDD: Red-Green Part 4: List of Goals

2019-03-25

How do you know which test to write next? How do you make sure you make progress towards your goal, that is, towards implementing a feature that is useful to your customers?

Intro (TL;DR)

When doing test-driven development - or TDD - you must must always choose the next test wisely: It should be small and fairly easy to write and also not too hard to get from red to green. And it should bring you closer to finishing the current feature.

How do you choose that next test? By thinking before you even write the first test.

I am David, a technical agile coach and trainer with over 12 years of experience. If you like my videos, please subscribe to my channel and share them with your friends and followers using the share buttons on the left.

Question / Problem

When I teach trainings, I sometimes see people either

  • Get stuck on a single test, where they do not know how to proceed OR
  • Write a lot of tests in a red-green-red-green-… fashion but not get any closer to their goal

In both cases, people are getting stuck because they did not choose a good next test. In the first scenario, the test and implementation were too big. In the second, they choose things that are easy to test, but not really important right now.

Solution

When you get stuck like that, do not just continue. Do not try to dig yourself out of the hole. Take a short break, then go back to the drawing board.

Make a list of things your system under test should do. Suppose we want to develop a simple hangman game. Write down everything it should do, then sort that list.

  • Shows a placeholder at the beginning of the game
  • Updates the placeholder after every correct guess
  • Player has won when the word was guessed correctly
  • Player has lost after 11 incorrect guesses
  • Counts number of incorrect guesses

Choose the next item from that list that is both easy to implement right now and relevant to end users. Like “Shows a placeholder at the beginning of the game”. Think of the simplest possible test you could write.

  • Placeholder is a single _ when the word to guess is “a”

After this test is green, choose another test that helps you finish this item.

  • Placeholder is “_ _ _” when the word to guess is “the”

And so on. Your list of features / behaviors helps you choose the next test. And when a test comes to your mind that you want to write later, write that down too. You can, for example, create a test list at the end of the file that contains your tests, with comments or disabled tests for future tests you want to write.

Conclusion

To decide which test to write next, create a list of things your system under test should be able to do. And keep a list of future tests you might want to write later.

Update both lists as you go, and do not hesitate to delete stuff from these lists when they are no longer relevant.

And if you still get stuck, undo everything you did since the last green test, take a short break, and go back to the drawing board.

CTA

How do you decide which test or code to write next? How often do you undo code and tests and go back to thinking? Tell me in the comments or on Twitter. I am @dtanzer there.

And if you liked this video, please subscribe and share it with your friends and followers using the share buttons below - That would be awesome!

Read / watch all parts of this series here:

TDD: Red-Green Part 3: Why Red

2019-03-18

The pair of programmers wrote a test. They ran it, and it was “green”. They started to write the next test.

I said: “Wait, stop it! Your test was green!” They were like: “So what?”

Today I want to talk about why “red” is so important in test driven development - Why you must see a test fail first.

Intro (TL;DR)

The first step in the three-step TDD cycle is “Red”. You write a failing test. To be more precise, you write a test that is already implemented correctly and is failing. Let’s explore why this is important.

My name is David, and in my Youtube channel, I show you techniques and tricks that I use myself and teach others to use. And I am currently doing a mini-series around the first two steps of the TDD cylce: “Red and Green”.

You are watching part 3 of this mini series: “Why red?”. By the way, if you like this video, please share it using the share buttons on the left!

Question / Problem

I insist on seeing a test fail before starting with the implementation - especially when I teach TDD in trainings. Sometimes, someone asks me: Why can’t I just write a test that is green?

Well, there are three reasons:

  • To increase trust in the test
  • TDD is not only about testing
  • To challenge my assumptions

Solution

Reason one: To increase trust in the test. If we test all our code, should we write tests for our tests? Some people ask this question, jokingly. But they have a point: Who tests our tests? How can we sure that our tests test what we want them to test?

When I see a test fail, and when I then see it go from red to green after I changed the production code; I can trust that the test worked at one point in time - right now, at the moment when I wrote it. I just saw that it tests what I expect it to test.

Reason two: TDD is not only about testing. TDD is “test driven development”. We develop software in a test-driven way. The tests are a by-product. We use the tests in two ways: To prove that the software did not have a certain feature when the test was red; and to prove that is now has this feature, as the test is green.

“Red” is important because it is our motivation to write more production code. It is part of our measure of progress.

Reason three: To challenge my assumptions. I want to write a test that is red. I run it, and it is green. There is something fundamentally wrong within my mental model of the software I am working on. I should revert my code and learn more about the current state of the code.

Conclusion

When doing TDD, you must see a test fail first…

  • To increase trust in the test
  • Because TDD is not only about testing
  • To challenge your assumptions

If the test is green after you wrote it, revert your changes and go back to learning / thinking.

CTA

Do you care about the “red” phase? Or do you sometimes write tests that are “green” from the start? Or did you even never try test-driven development? Tell me in the comments of the video or on Twitter, where I am @dtanzer.

And if you liked this video, please subscribe and share it with your friends and followers using the share buttons below - That would be awesome!

Read / watch all parts of this series here:

TDD: Red-Green Part 2: Wrong Code

2019-03-11

“Why do you want me to write wong code?” an attendee asked me in the break of one of my test driven development trainings.

At first, I did not understand the question: “No, in an ideal world, I only want you to write correct code! That’s why I teach these trainings.”

Then he explained…

Intro (TL;DR)

In today’s video, I want to show you that there are different kinds of progress you make when doing TDD and that each test should advance your program on one of those axis. I will also discuss why it is important to write what this attendee called “wrong code”.

My name is David, and in this video series, I want to show you techniques and tricks that I use myself and teach others to use.

By the way, if you like this video, please share it using the share buttons on the left.!

Question / Problem

In my trainings, I usually ask attendees to write a short program in a test-driven way on their own. And after that, we do the same exercise again together. Only this time, I stop them when they make a mistake, I nudge them to take small steps and I help them when they get stuck.

The question came after this second exercise.

“You wanted us to return a single underscore, and we already knew that this would not be the final implementation. We knew we would change this code five minutes later. You forced us to write wrong code!”

OK, if you put it like that, I wanted them to write wong code. The simple solution would be to answer: “The code was right at the time. It passed all tests we had so far”.

But there is more to that.

Solution

Two things are important here:

  • Axis of progress
  • Enabling the next red test

When we do one TDD cycle - red, green, refactor - we usually make progress on one or more of these axis:

  • The test suite
  • The design of the production code
  • The features of the system under test

Axis of Progress

This test and its implementation meant progress in the test suite: We now have a first, correct test that must always pass from now on. And it meant progress in the design of the production code: We now know how we want the Hangman class to keep the secret and to generate the hint.

It did not advance the “features” axis, but our next tests will do that.

This truly simplistic implementation also enables the next red test. Had we written a more complete - a more correct implementation, we would have a hard time to write the next test so that it is both

  • Failing (Red) and
  • Correct

Conclusion

So, taking these small steps is important because it enables you to write the next red test. And it is OK to write code that will be proven to be “wrong” later, as long as it is correct at the time you wrote it.

Even those small steps will mean progress at least on some of the three axis

  • Test suite
  • Design
  • Features

And that’s it for this week. What do you think about those small steps? Did this video answer some questions, or did it raise new ones? Tell me in the comments or on Twitter, where I am @dtanzer.

And if you liked this video, please subscribe and share it with your friends and followers using the share buttons below - That would be awesome!

Read / watch all parts of this series here:

Red-Green Part 1: Introduction

2019-03-04

One of the first things you must learn when starting with test driven development - or TDD - is how to write a good, “red” test and how to make this test green.

And this is already harder than you might think.

A good red test constrains the implementation you are about to write in just the right way - not too little and not too much. It takes you one step closer to your overall design goal; that might still be pretty far away. It enables you to write an implementation that will allow you to make the next test red again.

To make the test green, you must write the smallest possible implementation that will pass the test. And most people I know were surprised - schocked! - how small is sometimes necessary.

Intro (TL;DR)

My name is David, and in this video series I am showing techniques and tricks and other interesting stuff around the general topic of software development.

By the way, if you liked this video, please subscribe and share it with your friends and followers - That would be awesome!

A good red test enables...

How do you get from “red” to “green”? You know TDD is “red-green-refactor”, and the “refactor” step is crucially important.

But when I teach it to developers and teams, I often see people people struggle much earlier. They do not know how to write the first test, how to get that test to green “correctly” and how to write the next test.

So in this video (and in some future ones) I want to talk about the basics you will need at the beginning of the TDD cycle.

Question / Problem

When I teach TDD trainings (or when I teach TDD as part of a larger training), I usually ask people to test-drive a “Hangman” game at the very beginning, before I explain anything but the basics.

All of them manage to write a red test and to write an implementation that makes this test green. But then they start to experience problems…

A good red test enables...

They write more tests, and all of those are green (but they do not mind because they do not know yet that this is a problem). Or they do not know how to write the next test.

Solution

What they must learn is take smaller steps. Sometimes comically small. And to still keep the overall goal in mind and take steps that take them closer.

This means: Think about the overall goal before you even write the first line of code. Have a rough list of things you are trying to achieve. Break this list down into even smaller items as you go.

In the hangman game, test the simplest possible start of the game in your first test. “Placeholder is a single ‘_’ when the word to guess is ‘a’”. Then write the simplest possible implementation: Return a single underscore.

@Test
public void placeholderIsSingleUnderscoreWhenWordToGuessIsA() {
    Hangman hangman = new Hangman("a");

    assertThat(hangman.hint()).isEqualTo("_");
}

//...

public class Hangman {
    public Hangman(String wordToGuess) {
    }

    public String hint() {
        return "_";
    }
}

Conclusion

In this video, I showed you how even getting started with the TDD cycle is hard and unintuitive for many developers. And how you must learn to take small - sometimes comically small - steps in TDD.

In some future videos, I want to get into some more detail about how to do this: Why to take small steps, Triangulation, the Specific/Generic Rule, and so on. And I also want to show you some code.

CTA

What was your biggest problem when you started with TDD? Or what keeps you from starting? What are your challenges nowadays? Tell me in the comments or shoot me a Tweet to @dtanzer.

And if you liked this video, please subscribe and share it with your friends and followers - That would be awesome!

Read / watch all parts of this series here:

Refactoring: Move to Value Object

2019-02-25

Let’s talk about refactoring again: How can you move some code to different value objects using small, safe steps? In this video, I want to show you exactly which refactoring steps I take to extract a factory method, move it to one value object and move some code around it to another value object.

In my last video about “Refactoring Primitive Obsession”, I did all that very quickly to give you an overview about the whole process. I have added a link to that video in the description.

Today I want to show you a small step from this process and explain exactly what I did.

Intro (TL;DR)

My name is David and I am a trainer and technical agile coach with over 12 years of experience. In my videos, I want to show you techiques and tricks that I use and that I also teach when training or coaching teams.

Today I want to try something new: A very short video that focuses on a single thing. In this case, one refactoring step.

By the way, if you like this video, please subscribe to my channel and share it with your friends and followers - That would be awesome!

Question / Problem

In the code I want to start with, I already created a type for TaxAccountNumber but it does not do anything yet. It only wraps a single string.

TaxAccountNumber taxAccountNo = TaxAccountNumber
    .fromString(taxAccountNoUnvalidatedUserInput);
String taxOfficeIdInput = taxAccountNo.asString().substring(0, 2);
Integer taxOfficeId = Integer.valueOf(taxOfficeIdInput);

Now, I want to create a new type for the taxOfficeId, complete with a factory method, and move the code for extracting the first two digits and creating the taxOfficeId to TaxAccountNumber.

Solution

First, I create a class TaxOfficeId that wraps the taxOfficeId integer. I create a new variable, taxOfficeIdObject, for it and replace all usages of the integer with the new object.

TaxAccountNumber taxAccountNo = TaxAccountNumber
    .fromString(taxAccountNoUnvalidatedUserInput);
String taxOfficeIdInput = taxAccountNo.asString().substring(0, 2);
Integer taxOfficeId = Integer.valueOf(taxOfficeIdInput);
TaxOfficeId taxOfficeIdObject = new TaxOfficeId(taxOfficeId);

TaxOffice taxOffice = taxOfficeRepository.findByNumber(taxOfficeIdObject.asInteger());
if(taxOffice == null) {
    payTaxesView.showTaxOfficeError(
        "The tax office \""+taxOfficeIdObject.asString()+"\" does not exist.");
} else {
    //...
}

I can extract the two lines that convert the ID string to an integer and create the object to a new method on the controller class, named fromString. When I make this method static, I can then move it to the class TaxOfficeId.

TaxAccountNumber taxAccountNo = TaxAccountNumber
    .fromString(taxAccountNoUnvalidatedUserInput);
String taxOfficeIdInput = taxAccountNo.asString().substring(0, 2);
TaxOfficeId taxOfficeIdObject = TaxOfficeId.fromString(taxOfficeIdInput);

As a last step, I can now extract the two lines that get the sub-string and create the tax office ID to another method and move it to the class TaxAccountNumber. So, I first extract a method from the two lines, then I move it and last I inline the redundant call to asString in the moved method.

I can also rename taxOfficeIdObject to taxOfficeId again, because there now is no name clash anymore.

TaxAccountNumber taxAccountNo = TaxAccountNumber
    .fromString(taxAccountNoUnvalidatedUserInput);
TaxOfficeId taxOfficeId = taxAccountNo.getTaxOfficeId();

Conclusion

The tax office ID is a part of the tax account number (encoded in the first two digits), so it makes sense to have the code to extract and create it on the class TaxAccountNumber.

The code I created with this refactoring now reflects the domain concept of a tax account number much better than the old version.

I was either adding code or using built-in IDE functionalty to transform existing code. Both operations are reasonably safe. And I ran the tests after every step. This allowed me to change the code and be very sure that I did not change any functionality.

CTA

What do you think? How would you refactor this code? Please tell me in the comments on youtube or on Twitter, where I am called @dtanzer.

And if you liked this video, please subscribe and share it with your friends and followers (using the share buttons below) - That would be awesome!

Red, Green, ... Part 0: All Posts

2019-02-23

I sometimes teach test-driven development, or TDD, to developers who have never done it before. And at the beginning of those trainings, most of them struggle a lot with the first two steps of the “Red, Green, Refactor” cycle: How to write a failing test correctly and how to make this test pass correctly.

In this series of blog posts and videos, I want to focus on those first two steps: “Red” and “Green”. You can find all the parts of the series here:

Refactoring: Primitive Obsession

2019-02-18

“How did you refactor that?”

After my video about “Primitive Obsession”, a viwer asked me on Twitter how exaclty I refactored the code towards the final result.

Which steps did I take? Which transformations did I perform in the code?

In this video, I want to show you how I would refactor this piece of code to get rid of the primitive obsession.

Intro (TL;DR)

My name is David and I am a trainer and technical agile coach with over 12 years of experience.

Today I want to show you how to refactor some code that over-uses primitive data types. I will not talk about why this is a problem - I already did this in the video “Primitive Obsession”, and I have added a link to that video in the description.

Now, I only want to get rid of the problem.

So, let’s look at the original code again.

By the way, if you like this video, please subscribe and share it with your friends and followers. That would be awesome.

Question / Problem

It is a controller from an application that helps people pay their taxes. The controller gets a tax account number, validates it, reads the tax office ID from it and then displays information about the tax office.

If the first two digits of the tax account number - which are the tax office ID - are “46”, it will display “Linz” as the tax office name and the IBAN of the tax office in Linz.

I have added some more code compared to my last video. I have added a view for this controller. It is mostly empty, but here you can see how the controller would be called from the view.

The controller registeres a TaxAccountNoChangedListener with the view, and every time the text field changes, the view will call all these listeners. Then, the method onTaxAccountNoChanged of the controller will do it’s thing, and this is the method I want to refactor.

In addition to what I showed in the last video, I have added a constructor with dependencies. And I have added some more validation: The method now outputs an error when the tax office was not found.

public void onTaxAccountNoChanged(String taxAccountNo) {
    String errorMessage = TaxAccountNoUtil.validateTaxAccountNo(taxAccountNo);
    if(errorMessage != null) {
        payTaxesView.showTaxAccountNoValidationError(errorMessage);
    } else {
        String taxOfficeIdInput = taxAccountNo.substring(0, 2);
        Integer taxOfficeId = Integer.valueOf(taxOfficeIdInput);

        TaxOffice taxOffice = taxOfficeRepository.findByNumber(taxOfficeId);
        if(taxOffice == null) {
            payTaxesView.showTaxOfficeError("The tax office \""+taxOfficeIdInput+"\" does not exist.");
        } else {
            String taxOfficeName = taxOffice.getName();
            String taxOfficeIban = taxOffice.getIban();

            payTaxesView.showTaxOfficeName(taxOfficeName);
            payTaxesView.showTaxOfficeIban(taxOfficeIban);
        }
    }
}

I needed this to be able to add some tests. And I needed some automated tests to show me that I did not break anything.

Remember: Refactoring means changing the structure of the code without changing the functionality. It means applying small, safe transformations to the code. And then, after every small step, I must check whether I did not change the functionality.

Yes, I can never proof or be 100% sure that I did not change any functionality. But when I work in small, safe steps and use the compiler and some automated tests to verify every step, I can be pretty sure. I would even argue that when I did not do that - work in small, safe steps and verify every step - then it would not really be refactoring, just some changes to the code.

So, I needed those tests before refactoring but how I wrote them is not important right now. That’s maybe a topic for a later video.

Solution

So, small, safe steps. And I want to get rid of the primitive data types.

As a first step, I introduce an object for taxAccountNo. I give it an ugly name for now, to remind me that I am not done here: I want to later remove the string from most parts of the code.

I press Alt+Enter to and let my IDE create the field automatically. I also create a getter (by pressing Alt+Enter again), but I rename it to “asString” because this is the string representation of that object. I do not use the name “toString” here because toString should be human readable and is not supposed to be used by other code.

Now I replace all other uses of the method argument taxAccountNo with my newly created object. The tests still pass. Now I rename the parameter and the variable so that their names indicate better what they represent. Now, the parameter gets the ugly name because it contains the “uglier” value.

I press Ctrl+Alt+Shift+T here to open the “Refactor This” menu. I am sure other IDEs have similar functionality.

public void onTaxAccountNoChanged(String taxAccountNoUnvalidatedUserInput) {
    TaxAccountNumber taxAccountNo = new TaxAccountNumber(taxAccountNoUnvalidatedUserInput);

    String errorMessage = TaxAccountNoUtil.validateTaxAccountNo(taxAccountNo.asString());
    if(errorMessage != null) {
        payTaxesView.showTaxAccountNoValidationError(errorMessage);
    } else {
        String taxOfficeIdInput = taxAccountNo.asString().substring(0, 2);
        Integer taxOfficeId = Integer.valueOf(taxOfficeIdInput);

        TaxOffice taxOffice = taxOfficeRepository.findByNumber(taxOfficeId);
        if(taxOffice == null) {
            payTaxesView.showTaxOfficeError("The tax office \""+taxOfficeIdInput+"\" does not exist.");
        } else {
            String taxOfficeName = taxOffice.getName();
            String taxOfficeIban = taxOffice.getIban();

            payTaxesView.showTaxOfficeName(taxOfficeName);
            payTaxesView.showTaxOfficeIban(taxOfficeIban);
        }
    }
}

Now I want to move the validation into a factory method of TaxAccountNo since it should never be possible to create a valid object from an invalid input. I extract a static factory method from the constructor call and then I move this method to the TaxAccountNo class.

I will move the validation code into this method soon, but first I want to create a second variable for the sanitized input that will be available after validation.

public void onTaxAccountNoChanged(String taxAccountNoUnvalidatedUserInput) {
    TaxAccountNumber taxAccountNo = TaxAccountNumber.fromString(taxAccountNoUnvalidatedUserInput);

    String errorMessage = TaxAccountNoUtil.validateTaxAccountNo(taxAccountNo.asString());
    if(errorMessage != null) {
        payTaxesView.showTaxAccountNoValidationError(errorMessage);
    } else {
        String taxOfficeIdInput = taxAccountNo.asString().substring(0, 2);
        Integer taxOfficeId = Integer.valueOf(taxOfficeIdInput);

        TaxOffice taxOffice = taxOfficeRepository.findByNumber(taxOfficeId);
        if(taxOffice == null) {
            payTaxesView.showTaxOfficeError("The tax office \""+taxOfficeIdInput+"\" does not exist.");
        } else {
            String taxOfficeName = taxOffice.getName();
            String taxOfficeIban = taxOffice.getIban();

            payTaxesView.showTaxOfficeName(taxOfficeName);
            payTaxesView.showTaxOfficeIban(taxOfficeIban);
        }
    }
}

I want to change the error handling to Exceptions, so I first duplicate the validation and add an exception.

public static TaxAccountNumber fromString(String taxAccountNoUnvalidatedUserInput) throws TaxAccountNumberFormatException {
    String taxAccountNoSanitized = sanitize(taxAccountNoUnvalidatedUserInput);

    String errorMessage = TaxAccountNoUtil.validateTaxAccountNo(taxAccountNoSanitized);
    if(errorMessage != null) {
        throw new TaxAccountNumberFormatException(errorMessage);
    }
    return new TaxAccountNumber(taxAccountNoSanitized);
}

I could later inline the validation method from the util class; and if this was the last method on that class, I could remove the util class completely. But that would require some changes to the validate method.

public void onTaxAccountNoChanged(String taxAccountNoUnvalidatedUserInput) {
    try {
        TaxAccountNumber taxAccountNo = TaxAccountNumber.fromString(taxAccountNoUnvalidatedUserInput);
        String taxOfficeIdInput = taxAccountNo.asString().substring(0, 2);
        Integer taxOfficeId = Integer.valueOf(taxOfficeIdInput);

        TaxOffice taxOffice = taxOfficeRepository.findByNumber(taxOfficeId);
        if(taxOffice == null) {
            payTaxesView.showTaxOfficeError("The tax office \""+taxOfficeIdInput+"\" does not exist.");
        } else {
            String taxOfficeName = taxOffice.getName();
            String taxOfficeIban = taxOffice.getIban();

            payTaxesView.showTaxOfficeName(taxOfficeName);
            payTaxesView.showTaxOfficeIban(taxOfficeIban);
        }
    } catch (TaxAccountNumberFormatException e) {
        payTaxesView.showTaxAccountNoValidationError(e.getMessage());
    }
}

I want to continue with the onTaxAccountNoChanged - method for now. The next type I want to get rid of is the taxOfficeId. I basically apply the same steps again: I create a new class, extract a factory method and move that method. But now I also extract another method, getTaxOfficeId and move it to TaxAccountNo.

public class TaxOfficeId {
    private final Integer taxOfficeId;

    private TaxOfficeId(Integer taxOfficeId) {
        this.taxOfficeId = taxOfficeId;
    }

    public static TaxOfficeId fromString(String taxOfficeIdInput) {
        Integer taxOfficeId = Integer.valueOf(taxOfficeIdInput);
        return new TaxOfficeId(taxOfficeId);
    }

    public String asString() {
        return String.format("00",taxOfficeId);
    }

    public Integer asNumber() {
        return taxOfficeId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TaxOfficeId that = (TaxOfficeId) o;
        return Objects.equals(taxOfficeId, that.taxOfficeId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(taxOfficeId);
    }
}

I can now use the new class TaxOfficeId in the query method of the repository. But now I also have to change a test, since the old method is not called anymore on the mock object.

public void onTaxAccountNoChanged(String taxAccountNoUnvalidatedUserInput) {
    try {
        TaxAccountNumber taxAccountNo = TaxAccountNumber.fromString(taxAccountNoUnvalidatedUserInput);
        TaxOfficeId taxOfficeId = taxAccountNo.getTaxOfficeId();

        TaxOffice taxOffice = taxOfficeRepository.findBy(taxOfficeId);
        if(taxOffice == null) {
            payTaxesView.showTaxOfficeError("The tax office \""+taxOfficeId.asString()+"\" does not exist.");
        } else {
            String taxOfficeName = taxOffice.getName();
            String taxOfficeIban = taxOffice.getIban();

            payTaxesView.showTaxOfficeName(taxOfficeName);
            payTaxesView.showTaxOfficeIban(taxOfficeIban);
        }
    } catch (TaxAccountNumberFormatException e) {
        payTaxesView.showTaxAccountNoValidationError(e.getMessage());
    }
}

The last step now is to create new classes for the tax office name and the IBAN. Then I can rename the methods for diplaying to only show. But I also have to change the tests again.

@Test
public void showsTaxOfficeInformationIfTaxOfficeWasFound() {
    TaxOffice taxOffice = mock(TaxOffice.class);
    when(taxOffice.getName()).thenReturn(new TaxOfficeName("Linz"));
    when(taxOffice.getIban()).thenReturn(new TaxOfficeIban("AT03 0100 0000 0552 4464"));
    when(taxOfficeRepository.findBy(TaxOfficeId.fromString("46"))).thenReturn(taxOffice);

    controller.onTaxAccountNoChanged("46-999/9460");

    verify(payTaxesView).showTaxOfficeName(new TaxOfficeName("Linz"));
    verify(payTaxesView).showTaxOfficeIban(new TaxOfficeIban("AT03 0100 0000 0552 4464"));
}

I can now, as a final step for this video, move some value classes to the class TaxOffice and give them nicer names.

Conclusion

Now look at the code. This does look nicer than before.

I could refactor even further. For example, the classes for the value objects all have very similar functionality. They all wrap a single primitive value. They all have a hashCode and equals method and they look very similar.

I am sure I could unify or simplify some things here. But for now, I am done here.

CTA

What do you think of these refactoring steps? What would you have done differently? Please tell me in the comments or on Twitter, I am @dtanzer there.

And if you liked this video, please subscribe and share it with your friends and followers using the share buttons below - That would be awesome!

Improve Retrospectives

2019-02-11

Quick show of hands: Who here likes retrospectives? Who loves them?

Many people I have met so far would have kept their hands down. They would rather work on the next feature than sit in a retrospective.

That’s because, in many teams, retrospectives are boring and ineffective.

Intro (TL;DR)

In many teams, retrospectives are boring and ineffective. But that does not mean that it has to be like that.

If this is your team, change something. Working on having better retrospectives is one of the cheapest things you can do to improve your overall situation.

Some time ago, I wrote a book about “Agile Anti-Patterns”. And most of the problems I described there could be cured by better retrospectives. At least to some extent.

By the way, there is a link to the book in the description of this video!

And “better”, or “good”, in this case means that

  1. The retrospective is not boring
  2. People talk about the “big”, “systemic” problems
  3. The retrospective results in real, positive changes

But before I’ll talk about those three points, let’s look at the problem again, in a bit more detail.

Question / Problem

Imagine a team that is doing some “agile” “process”. Like, Scrum, or whatever. Every two weeks, the team has a “Retrospective”.

But those retrospectives are boooring. Nobody likes them. People would rather work on their next task than be sitting in this meeting.

And nothing ever really changes - at least, nothing important. Yes, the team records action items at the end of each retrospective. But sometimes they don’t get done at all. Sometimes they get done, but have no visible effect. And sometimes they did solve the problem, but it does not matter because the problem was very small and unimportant.

Now imagine a team that does not do any retrospectives at all. Which team is using their time more efficiently?

The second team, of course. The first team not only wasted the time it took to have the retrospective and to work on the action items, it also had a meeting that demotivated everyone who was there. Those people will probably not go back to their desks afterwards and work on happily and fully motivated.

Does this mean you should stop doing “Retros”? NO! But if there’s one thing you could do now to improve your way of working, then look at your retrospectives and try to improve them.

Solution

To get better, your retrospectives should not be boring, they should tackle the big problems and they should result in real, lasting change.

To avoid that your retrospectives become boring,

  1. Keep them short
  2. Make sure everyone is involved and
  3. Have some variety in how you do them

Keep the meeting short - but not too short. To facilitate a good retrospective with actionable results, you will probably need 90 minutes. Longer than that will be too long for a sprint retrospective, but longer retrospectives might be necessary at the end of a quarter, year or project.

Maybe you can do a great retro in 60 minutes sometimes, but shorter than this is definitely too short. I would even consider 60 minutes too short for most teams, most of the time.

At the beginning, make sure that everyone will be involved. Try to get everyone to say something within the first few minutes, otherwise some might not say anything during the retrospective at all.

Get the book “Agile Retrospectives: Making Good Teams Great” by Esther Derby and Diana Larsen and also have a look at the “Retromat” by Corinna Baldauf. Both will teach you activities that will help you get everyone involved at the beginning.

Also, both follow a structure with 5 distinct phases and activities for each phase. Following this structure will help you to add some variety to your retrospectives, so they will be less boring.

But even when your retrospectives are not boring and when everyone is involved, the time will be wasted when you do not tackle important problems or when you spend the retrospective finding out whom to blame. So,

  1. Remind people that we believe performance is mostly determined by the system
  2. Create an environment where everyone feels safe
  3. Spend time not only looking at symptoms, but also at root causes.

The “retrospective prime directive” is one way of reminding people that we are not here to assign blame, but to improve the system. It says:

"Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand."

Norm Kerth, Project Retrospectives: A Handbook for Team Review

But do not only read it out loud, talk about it. Talk about what it means and what it means to you, as a team, for this retrospective.

You need an environment where everyone feels safe. Make sure people know that, whatever they say, there will be no finger pointing, no loughing and no shouting. Let them know that in this meeting, they can talk about everything and point out any problems - and that this will not have negative consequences for them in the future.

And make sure that nobody ever breaks these rules. At one past client, an influential team member shouted at the team during a retrospective once. Called them unprofessional. Threatened to have some fired. Every retro after that was a complete waste of time because nobody would ever talk about the interesting problems again.

Also, do not only look at symptoms and simple solutions. It will not help to treat the brain tumor only with aspirin to make the headache go away. Before brainstorming possible solutions, dig deeper and try to find the real problem.

The retrospective should also result in real, lasting change.

If your retrospectives do not yield some visible results, the other two qualities - not boring, tackles big problems - won’t rescue your retros. If there are no results, people will still consider the meeting a waste of time, and it will become boring and shallow again.

To get started,

  1. Create less action items at the end
  2. Define success criteria and measure success before the next retrospective
  3. Use your influence or find people who can help you

Create less action items. Why do I want you to try that? Because with less action items, chances are higher that they will be done within reasonable time.

Some teams identify five problems, then 5 ways to tackle the problem for each. And at the start of the next retrospective, none of the 25 action items are “done”.

So, choose one problem. Define one or two experiments - things you want to try to solve the problem or to make your life a little bit better. Then make sure they are done next time to meet.

Also, define success criteria for these experiments. And say when you want to measure success. In two or four weeks, or whenever you want to measure, is not enough that the experiment was “done”. You also want to know whether it was successful and what exactly has changed.

Sometimes, especially in large companies, all the interesting problems cannot be solved by the team alone. They are caused by the processes, the rules and the culture of the oranization.

But just because you cannot solve those problems alone does not mean you should not try to solve them. Find people who can help you. Or find people who can help you find people who can help you. Make your problems and impediments known.

Conclusion

When you have retrospectives that are not boring because

  1. They are short
  2. Everyone is involved and
  3. There is some variety in how you do them

When you have retrospectives that tackle the big, systemic problems because

  1. People know that performance is mostly determined by the system
  2. The retro happens in an environment where everyone feels safe
  3. People spend time not only looking at symptoms, but also at root causes

When you have retrospectives that result in real, positive changes because

  1. The team creates less action items at the end and makes sure they get done
  2. The team defines success criteria and measure success before the next retrospective
  3. The team uses their influence to find people who can help them

People will start to enjoy retrospectives again. They will participate more, and the whole team will benefit.

CTA

Tell me in the comments how your retrospectives work for your team, and what could be improved about them. Or shoot me a Tweet to @dtanzer, if you prefer discussing on Twitter.

And if you liked this video, please share it with your friends, followers and colleagues (e.g. with the share buttons below)!

Primitive Obsession

2019-02-04

Did you ever see some piece of code that uses primitive data types, like Strings or integers, in it’s public API? I am sure you have, because most code is written like that.

But that can cause problems. Today, I want to talk about a code smell called “Primitive Obsession”. And I want to show you how code often becomes easier to understand and “nicer” by eliminating primitive data types - especially, but not only, from it’s public API.

Intro (TL;DR)

My name is David and in this video series, I am talking about things you can do to become a better software developer.

I am a freelance consultant and coach - and in the last 12 years I have strived to constantly learn and improve my skills as a software developer, architect, and also as a tester, team coach and trainer.

I have learned that improving your software design is crucial for delivering better software faster and cheaper. Having a low internal quality in your software costs you a lot, and in many different ways.

Today I want to talk about a very specific design smell: Primitive Obsession. You can notice this smell when your code uses a lot of primitive data types, like integers or booleans but also strings and dates, especially in its public API.

Primitive Obsession is a more general version of “Stringly Typed Code”, a code smell where strings are used in places where other data types would be more appropriate.

Question / Problem

How does primitive obsession look like and what exactly is the problem? Consider the following piece of code…

This code comes from a hypothetical software that helps me pay my taxes in Austria. In a first step, users would input their tax account number.

The software would first verify that the tax account number is correct and also load some information about the tax office, which the software will display to the users. And because we are only selling to Austrian customers and only support Austrian tax account number, it can use the first two digits - the tax office number - for doing so.

46-999/9460

The tax account number looks like this: The first two digits are the tax office number. In this example, 46 means “Linz”. The next six digits, ususally written with a slash in the middle, are the account number within this tax office. And the last digit is a checksum.

The example code gets the tax account number that was entered by the user, validates it, extracts the tax office number and loads the tax office information. If everything worked out correctly, it displays the tax office information. Otherwise, it outputs an error.

For some reason, maybe a performance optimization or because it is required by some backend, the tax office number string is also converted to an integer. If you think, right now, “Nobody would ever do that”: I have seen very similar things at multiple past clients. Well, maybe a little bit less obvious stuff. And not with tax account numbers, but with other structured data.

public void onTaxAccountNoChanged(String taxAccountNo) {
    String errorMessage = TaxAccountNoUtil.validateTaxAccountNo(taxAccountNo);
    if(errorMessage != null) {
        showTaxAccountNoValidationError(errorMessage);
    } else {
        String taxOfficeIdInput = taxAccountNo.substring(0, 2);
        Integer taxOfficeId = Integer.valueOf(taxOfficeIdInput);

        String taxOfficeName = taxOfficeRepository.findByNumber(taxOfficeId).getName();
        showTaxOfficeName(taxOfficeName);
    }
}

The first version of the code

This code uses primitive data types - Strings and Integers - all over the place. validateTaxAccountNo returns the error message as a string. The taxAccountNo is a string. We get the tax office number as a string and convert it to an integer. The tax office name is returned as a string by taxOffice.getName()

Use of primitive values in this code

But the code is reasonably short and easy to understand, so where is the problem?

First, these data types are too general. They allow more operations than should be possible with an tax account number or a tax office number. Integer allows us to add, substract, … and also to compare to other numbers. All of that should never be possible for a tax office number.

On the tax account number, we can again do operations that should not be possible, like calling the string manipulation functions, searching inside, and so on.

If you think, right now, “nobody would ever do that”, think again.

Second, the use of types does not add clarity or allow you to remove duplication. It’s even the other way around: To add functionality around tax account numbers, we needed a class called TaxAccountNoUtil. Now there are two places in the code that know about tax account number. We have duplicated the knowledge about tax accounts.

And third, you are voluntarily giving up compile time safety. Suppose you see a method call like this:

A function call - Which parameter is which argument?

When the first two parameters are integers and the other three are strings, nothing is stopping a programmer from supplying them in the wrong oder. When some programmer decides to re-order the arguments or add another argument, it will be really hard to find all the effected places.

The compiler could help you detect defects like that. But in this case, it cannot because you are using primitive data types.

Solution

As a first step, I will do the most simple thing. I will introduce types for TaxAccountNumber, TaxOfficeId and TaxOfficeName - and there is already a class for TaxOffice. They only wrap the primitive value - They do not do anything in addition.

public void onTaxAccountNoChanged(String taxAccountNo) {
    try {
        TaxAccountNumber taxAccountNumber = TaxAccountNumber.fromString(taxAccountNo);

        String taxOfficeIdInput = taxAccountNumber.asFormattedString().substring(0, 2);
        TaxOfficeId taxOfficeId = TaxOfficeId.fromString(taxOfficeIdInput);

        TaxOfficeName taxOfficeName = taxOfficeRepository.findBy(taxOfficeId).getName();
        showTaxOfficeName(taxOfficeName);
    } catch (TaxAccountNumberFormatException e) {
        showTaxAccountNoValidationError(e.getMessage());
    }
}

Even though this was just an intermediate step, I already made some progress. The fromString method of TaxAccountNumber should never return an invalid object. So I had to move the validation there. That’s what J.B. Rainsberger calls “Attractive Code” - Once you have a place where you can put code for a certain concept, this place will attract other code.

This method can still use the old TaxAccountNoUtil class, but I will later even inline the methods from there and remove TaxAccountNoUtil. Another win: We should not have “Util” classes anyway.

And if you do not like that exception being thrown, there would be other solutions. But that would be too much change for this video.

I now have types for TaxAccountNumber and TaxOfficeId, and so far, they only wrap the primitive type. But they already give me two other advantages:

  • I can make the constructor private, forcing everyone to use the factory methods. There I can do very specialized validation, depending on which factory method was called. Also, the factory methods allow me to give a “name” to the constructor, which would otherwise be impossible in Java.
  • I can make the wrapped primitive final. The classes now start to represent what “Domain Driven Design” calls a value object.

Private constructor, immutable fields

Now I have my attractive code. What else could I do with that?

What I will do now is “just” cleanup. I can remove the redundant calls to “fromString” and “asFormattedString” and move this code to the specialized types. And since I now also have a type for the tax office name, I do not have to name the mehtod for showing it showTaxOfficeName. I can name it showNameOf and rely on the fact that the compiler will select the right method.

Final result

Conclusion

The code now is shorter and easier to read.

It has added compile time safety: It is now impossible to supply the wrong number to findBy or to call the wrong method for showing the name. The compiler even forces me to deal with the validation error that I could have ignored in the first version of the code.

Yes, I wrote a lot of code around this method, so the overall amount of code was increased. That took me maybe half an hour.

But this code was easy to write. And it allows me to encapsulate the data better. It allows me to make all these objects immutable - that is, read-only - which makes writing correct correct easier.

The code also added clarity to onTaxAccountNoChanged which will be the first method a programmer will see when they debug a problem with tax account numbers later. If I can save the next programmer a few minutes of debugging time, and if I maybe can prevent a simple parameter ordering mistake, saving another programmer a few minutes, this change was already worth it.

CTA

Have you ever seen code with primitive obsession? What about the software you are working on right now - What are the worst places regarding to this, and did it ever cause a (small or larger) problem?

Or, do you already create classes for value objects and entities, like in the last version of my code? How does that feel? Which advantages does it give you?

Tell me in the comments or shoot me a Tweet to @dtanzer. And do not forget to subscribe to this channel or follow me on Twitter, so you’ll never miss any updates.

Object-Oriented Design Pitfalls

2019-01-28

Do you remember how you first learned about object-oriented software design? How they teach it at University?

You probably looked at objects from the real world and their is-a or extends relationships. A circle is-a shape, and it extends shape. A cat is-an animal, and it extends animal.

Today I want to re-visit this kind of approach to learning object-oriented design and discuss it’s advantages and shortcomings.

Intro (TL;DR)

My name is David and in this video series, I am talking about things you can do to become a better software developer.

I’ve been working as a freelance developer, technical coach and trainer for some time now. I am helping my clients - among other things - to handle their legacy code bases better.

And many problems I see in those legacy code bases are caused by not putting enough emphasis on software design. By taking a simplistic approach, almost as simplistic as the one described before.

Like, find the nouns and verbs in the specification and that’s basically the design.

So, when we talk about software design in the workshops I teach, I also spend some time trying to show people that the “first-gut-feeling” approach to design does not work.

Because when you know why and how this approach does not work, you will understand the techniques you need to learn more easily.

Question / Problem

Some software designs look like someone searched for nouns and verbs in the specification (or the business domain). Then they made classes directly from the nouns and methods from the verbs.

And designs like that seem right at the first glance, because they model the objects from “the real world”.

But then you run into problems. Writing tests is hard. There are a few classes that are huge and do all the work, and other classes that barely do anything at all. There are big domain objects that contain 15, 20 or more fields.

There are services that depend on services that depend on services - many layers down the onion - even though all of them are stateless.

There are classes that have many dependencies which contributes to your testability problem.

The design is neither extensible nor portable. You cannot re-use the business logic in a slightly different situation because of technical limitations. Adding additional features requires you to change many pieces of code in many different locations.

And all of that slows you down. Every. Time. You. Want. To. Change. Something.

What happened here? Well, the “objects from the real world” approach to software design almost inevitably leads to bad design.

Let me give you a little example.

Solution

I want to design a very simple class hierarchy with you. There are Cats and Dogs, and both of them are Animals. An Animal has a position and we can tell it to move to another position.

Animals also have a method speak. When we call this method on an object of type Cat it would output “meow”, when we call it on a Dog it would output “woof”.

Class diagram showing a hierachy of animals with Cat and Dog

But now we got new requirements and we need a new class Worm. “Easy”, we think, it’s also an animal.

But how do we implement “speak” here?

Class diagram showing a hierachy of animals with Cat and Dog

All right, leave it empty. Worms don’t speak. That’s not really nice, because even calling “speak” does not make sense on a worm.

But we can live with that. There is not much harm in leaving a method empty. Right?

Wait, we got new requirements again. And we need another class to support them. We need a Coral.

Now, corals do not speak too, but they also do not move.

We have the same problem as before, but slightly worse: How can we implement moveTo here?

Class diagram showing a hierachy of animals with Cat and Dog

Think about it for a moment… I think in this class hierarchy, there are only two reasonable ways to implement moveTo: Do nothing or raise an error (like, throw an Exception).

What if we did nothing? A programmer would never call moveTo on a Coral, right?

Maybe they wouldn’t, but they might not know that what they have is a Coral. They get an Animal object, call moveTo, at some point later in time call getPosition - and the animal would still be at its old position.

That would be surprising to the programmer. I am almost certain that they would fire up the debugger to find out what’s going on here. This behaviour violates the “Principle of Least Surprise”.

So, it’s “raise an error”, right? Well, not so fast…

Suppose there is some code that iterates over all animals and moves them. This code now does not work anymore.

By adding the coral class the way we did it - By raising an error in a situation that is perfectly fine from the caller’s perspective - We broke some totally unrelated code.

How can adding new code break existing code?

It was possible because we violated the “Liskov Substitution Principle”: We wrote a class that, for some calling function, is not compatible with its base class.

Conclusion

How can we add the coral class without causing any problems? We cannot - because this is the wrong question.

We cannot do it because looking at the “static structure” of the “real world” and creating a software design from it does not work. At least it does not work in most cases.

The objects and relationships we - humans - see are often not the objects and relationships our software is interested in.

In software, we try to implement some behaviour. We want to make computers do something. In order to do that, we must understand and model behaviours from the real world.

And we must take care to only model the behaviours and objects our software needs to do its job. Whenever we model less or more, we make our design needlessly complicated.

The simplistic object oriented design we learn at school - “Cat is-an Animal” or “Car has tires” - is useful for learning to think in objects. But it is not necessarily useful for creating real software systems.

We must do more in order to model those real software systems. We must think about coupling and cohesion. Follow software design principles. Know about design patterns. Know the rules so well that we know when to follow them and when to break them.

But those are topics for upcoming videos. Today I wanted to show you how a too simplistic design can fall short pretty quickly.

CTA

How do you and your team design your software? Do you have a process? Does your design look like “nouns+verbs” or is it more sophisticated?

Did you already experience situations where a design that looked absolutely reasonable stopped working because of new requirements? What are you planning to do next?

Tell me in the comments or on Twitter - I am @dtanzer there. And do not forget to subscribe to this channel, so you do not miss any updates!