Feedback

People usually say they appreciate direct and honest feedback. But I do know plenty of people, who rather hear only good feedback and praise than “constructive” feedback about themselves or their actions. Of course it is a lot more nicer to hear positive things about oneself but if you only get positive feedback you’re missing a lot of chances to get better in what you do or in what you are. Nobody’s perfect, you can always get better.

Giving Feedback

There are several ways to give constructive feedback. If feedback is given in a wrong way, the person receiving it might take it only as a negative thing which then  prevents getting the message through and the opportunity for learning something is lost due to the counter reaction. There is never need to hurt someone’s feelings by focusing purposely only on negative things to bash someone or someone’s actions. If someone actually did something that made you feel bad, it is naturally all right to tell how you felt about it. Nobody can deny your feelings. Remember then to also tell how you would have wanted the person to act or how you wished the other person to act differently the next time. It is also always good to prepare for the person receiving your constructive feedback not appreciating it. If you give feedback in a good way and the person receiving it doesn’t get the message through it might better then just to be happy about yourself making the best effort of giving another person an opportunity to improve.

Receiving Feedback

Receiving criticism is never easy for anyone. Negative feelings might surface and one might even feel angry, afraid or even sad. Listen any feedback you get carefully and ask clarifying questions if needed so that you really understand what the person giving feedback is after.  Try to focus on those things you can focus on in the future to make yourself a better person and to improve in what you do. Always thank the person giving feedback even though you would have gotten it in an unconstructive way. Naturally not all feedback is such that you could learn something. In those cases you should try to forget it and not think about it too much.

 

Advertisements

Test-Driven Development for Dummies

Kuva
Flickr photo by julyYu. License: Attribution-ShareAlike 2.0 Generic, Some rights reserved.

If you thought this is a technical post you have mistaken. The purpose of this post is to try to explain what test-driven development (TDD) is so that anyone understands it. Or at least almost anyone, with at least some technical background.

Let me start by explaining what TDD is not:

  • It is not one form of software testing nor does it remove the need for that
  • It is not done in order to find defects from the code
  • It does not guarantee that there are no defects in the code
  • It’s primary purpose is not in trying to minimize amount of defects in the code
  • It does not magically solve all your problems

Instead, TDD is primarily a design method which aims in producing least amount of code which satisfies the software requirements. As an added benefit, TDD also ensures that code does what the person who wrote it intended it to do. Naturally, in case the software requirements, use cases or user stories are not right, the code might still not be doing what the user would like it to do, but this is another story and finding this kind of faults is not in scope of TDD.

So, yeah but, no but, yeah but, no but WHAT and HOW?

To begin with starting to design or implement any piece of software, developers needs to have requirements. They can be in any form popular at that time, use cases or user stories being ones often used at the moment. From a requirement, software development team plans the tasks which need to be implemented in order to fulfill the requirement.

Let’s have some example tasks:

  1. “Ask user’s name”
  2. “Ask user’s birthday”
  3. “Show a friendly greeting to the user”
  4. “Show a birthday greeting to the user”

Let’s start implementing those tasks using TDD.

First task, “Ask user’s name”. For this we probably need a method which asks for user’s name and stores it for later use. To begin, we will write a simple test in (pseudocode):

"User name should be stored after it has been entered":
    user_john = new User()
    user_john.set_name("John Doe")
    assert user_john.get_name() equals "John Doe"

This imaginary test doesn’t bother with how the name is asked from the user, it focuses in the storage of the gotten value and asserts that the value given is indeed stored for later use. When this test is run, it will fail as there is no other code written yet. In fact, this code would not even compile.

When a test is failing, the testing result is said to be red. This is always the starting point for adding the actual functionality. The reason for this step is to ensure that the test itself is not accidentally passing when it should fail.

Next step is to write the code to make the test pass:

class User:
    variable username

    method get_name():
        return "John Doe"

    method set_name(variable name):
        return

Now the code compiles and the test passes. Still this doesn’t look like it is ready to production yet, or does it? Anyway this state of TDD cycle is called green. Only at this stage, it is allowed to refactor the code. Refactoring means changing the structure of the code without altering any functionality. It is done in order to make the code cleaner e.g. by removing any unnecessary duplication, magic strings and numbers etc. It is a necessary step to be done during development although in this example of ours there is not much to refactor. After refactorings have been done, all the tests are run again in order to make sure none of the functionality was altered or broken.

As we see, our code is not yet ready so we need to do some work with it. The TDD cycle begins from the beginning, by writing another failing test or extending an existing one. We now choose the latter alternative:

"User name should be stored after it has been entered":
    user_john = new User()
    user_jane = new User()
    user_john.set_name("John Doe")
    user_jane.set_name("Jane Doe")
    assert user_john.get_name() equals "John Doe"
    assert user_jane.get_name() equals "Jane Doe"

Now when we kick off the tests run, it will end up in failing, red state. This means we can hop on to write some functionality again:

class User:
    variable username

    method get_name():
        return username

    method set_name(variable name):
        username = name

Behold, our tests are turning green again. After refactoring we would hop on to write first failing test for asking the birthday and so on and so on.

The TDD cycle is often called Red-Green-Refactor and it is essential that it is followed strictly. Only this ensures that developer writes as little production code as possible and that the code written does what it is intended to do. Refactoring step makes the code more clean, helping in maintaining that code later on. Good tests written during development also work as a splendid documentation of the code. A new developer getting familiar with code written using TDD will easily see what the developer who wrote the code intended it to do not to mention that such code is usually also easier to understand as it is cleaner. Good to remember here also that less code = less defects. So even though the main purpose of TDD is not to try to minimize the defects in the code, it sure does help in that.

If one follows the TDD discipline, the produced code will get 100% unit test coverage. This is something which is really hard, if not impossible to retro-fit in the code later on. Unit test coverage itself doesn’t make the code any better than code without any coverage, but it makes it easier, faster and more safe to change the code later. I claim that an average developer spends at most 10% of her time writing new code and rest of the time goes reading and changing old code. Developers in general do spend a lot more time reading code than writing it. So if we can make the code easier to read, it will save a lot of money in form of saved development time.

Git is not Subversion

We decided in Spring 2011 to take Git in use as our only version control system. Original ambitious goal was to get rid of all existing Subversion and CVS repositories by the end of year 2012. That didn’t quite work out, we still have a lot of stuff in the old repositories. I can understand this with old not active repositories where nobody sees added value in moving them to Git, but a lot of active development is still done in Subversion repositories.

We’ve had several debates over the issue, latest was today. Some developers were complaining that Git is too complex, it is too difficult to learn to use correctly and it doesn’t explain what went wrong clearly enough. “With Subversion things are just a lot simpler and easier.” When digging deeper with this I found out some of the (Windows) developers are trying to use Git as they have used Subversion. So no use of local branches, no use of stashing, no use of rebasing… And they don’t want to use Git command-line, but GUI tools instead. Because that’s how they have always done.

I admit, if you use Git like you would use Subversion, Git is worse. It sucks. And if you don’t familiarize the fundamentals of distributed version control, Git will never be easy for you. It becomes the necessary evil of version control and you will never learn to use it properly. You start to hate it. And you won’t do anything in order to move ye old Subversion repositories to Git.

Git is not Subversion. Git is a distributed version control system and fundamentally different from Subversion, CVS or (dear god almighty) Source Safe. In order to properly learn Git, one should forget everything they’ve learned from source code version controlling using Subversion or CVS. Git is different. Even though it can be used like you would use Subversion, it is not meant for that. It is a powerful and sophisticated tool which helps you version control exactly the stuff you want. Git is your friend.

So give it another try, but this time start fresh. And uninstall that GUI tool or at least forget it. Git should be first learned using the command line version, it’s the best way to learn the usage properly.

Internet is full of resources for learning Git. Here’s for example one I presented in the Tampere Goes Agile conference in 2011: Up to speed with Git.

Unit Testing Is Boring

Unit testing is really really boring. It is waste of time and productivity, writing unit-tests is hard, takes long and might require time-taking refactorings to the code for it to be unit-testable. Regression testing is anyway a lot more effective in finding mistakes. Besides, unit testing provides very little value as it doesn’t tell anything about the quality of the software. Adding unit tests to code which has already been proven working by functional testing is just stupid.

That may sound a bit exaggerated, but I’m almost serious here. There are times when adding unit tests is really waste of time. There’s a lot of code which is hard or near impossible to unit test properly. But the last part about code being proven working by functional testing is in my opinion bullshit. Functional testing tests functionality and can prove that desired functionality has been achieved, but it cannot prove that the code does what the developer intended it to do. And no matter how much functional tests you add on top of your software, it doesn’t make the code any more maintainable.

Let me tell you  how I define testing and unit testing.

Testing gives quality information about software. Qualities being e.g. functionality, usability, reliability, performance etc. We do testing in order to determine the current quality level of a certain software. This information can be further used to make decisions e.g. whether to release the software now or later (or never which is a brilliant decision in some cases).

Unit testing does not give you any quality information about the software or it’s functionality, but it does give you information about the  quality the code. There is a difference. Unit testing, if done properly, can prove that the code does exactly what the developer intended it to do. Of course there might be mistakes made when deciding what the code should do, but that’s a different story. Unit testing also makes code easier to maintain and further develop.

To be able to unit test code, the code needs to be unit testable. This usually also means the code is cleaner (clean as in Clean Code) which makes it easier to understand and change the code. And when the code is covered with good set of unit tests, it is also safe to change the code. Every code written has a price. There’s a price to develop the code, but there’s (often even larger) price to maintain the code. Clean code which is covered with unit tests has a smaller price tag than code which is not that clean and/or is not covered with unit tests.

Adding unit tests to code is boring. This is true. And if the code will not be further developed, it is complete waste of time as well. Unit tests do not add much (or any) value when written afterwards, specially if long time has passed since the code to be tested was written. As said, adding unit tests to code which was not written to be unit testable in the first place is laborious and often requires big refactorings to be made before unit testing can take place. And as there are no unit tests to cover poor developer’s ass, those refactorings might break things really badly. Luckily there are good old books to help in tasks like this. Do read Martin Fowler’s Refactoring and Michael C. Feather’s Working Effectively with Legacy Code.

So, this far we’ve learned that unit tests often don’t add any value, are difficult to write and the whole thing is also really boring. Forget unit tests completely? No, I’ve found a nice solution which you’ve probably heard earlier as well. It’s called test-first programming or test-driven development (TDD). I personally like most the term red/green/refactor. After I learned to do TDD (as if I meant it) I’ve enjoyed writing code a lot more. Nowadays I don’t often get to write code, but when I do, I use TDD and I love it.

And even if you didn’t like TDD or don’t want to try it (if this is so, I’d like to know why), you can still add the unit tests while you’re writing your code. Then you must think about unit testability before you write the first line of production code. Code design must be done so that adding unit tests is easy.

As a final note, consider Martin Fowler’s words and think about this the next time you’re writing code:

Whenever you are tempted to type something into a print statement or a debugger expression, write it as a test instead.

On Unit Test Coverage and Code Complexity

A team lead approached me asking what should they define as minimum unit test coverage percentage and code complexity metrics. I had to think about my answer a bit and came up with following, which I think is worth sharing to others as well.

Unit-test Coverage %

The more good unit tests there is covering the code, the easier it will be to read, understand and change the code later on. Excellent answer to the question of what should the coverage be can be found from StackOverflow: http://stackoverflow.com/questions/90002/what-is-a-reasonable-code-coverage-for-unit-tests-and-why

If you still insist on having a target percentage, I’d personally recommend to aim for 100%, which is achievable if you use strict TDD. By strict I mean following the Red-Green-Refactor pattern with discipline. There’s a good presentation about this on InfoQ: http://www.infoq.com/presentations/TDD-as-if-You-Meant-It.

Being more reasonable, specially if you already existing code base, you might set the target to 70-80%. Keep in mind though not to stare at the numbers only! Bad tests also give you high coverage but not much confidence or easier refactoring. For this as well, there’s an excellent article available: http://www.sustainabletdd.com/2011/12/lies-damned-lies-and-code-coverage.html

Code Complexity

Code complexity  figure tells quite well how easy it is to read and change the code. It also affects unit testability as smaller methods are generally easier to unit test. I’d aim for cyclomatic complexity of less than 10 per method. More complex code usually contains more bugs as well, so if you find some parts of the code to be more complex, do focus your testing efforts on that area.

We have one project where we have set up our Jenkins job so that it becomes unstable if the amount of complex methods grows. This project now has average method complexity of 5.25. Still there is one methods with high complexity (23 in fact) and about 50 methods of medium level of complexity (10-20).

There might be a good reason for high complexity number e.g. an event handler with a long switch clause. While this might be avoided with polymorphism (see http://sourcemaking.com/refactoring/replace-conditional-with-polymorphism), but this might also make the code more difficult to maintain.

Summary

It’s good to early enough think about code maintainability and the speed of development in the future. Unit test coverage and code complexity are factors which affect those a lot. Other things worth investing to are code reviews as a standard practice and pair programming. Both work as fast feedback cycles to catch not only defects but also code which is difficult to maintain.

In the end it’s up to you and your Product Owner to decide how much do you invest in code quality. Code which is simple, produced with TDD and covered with good unit tests is cheaper to maintain in the future. On the other hand, if these factors are not taken in account, it’s like taking a loan from the bank. You’ll manage a long time by just paying the interest, or parts of that, but eventually you need to start paying back the debt as well. Or take another loan.

It’s more likely that you will produce Clean Code when you have proper measures in place to early detect code going bad. Also worth to note is that you should always aim for writing as less code as possible. A nice article on this subject: http://mikegrouchy.com/blog/2012/06/write-less-code.html

Benefits of Git for a developer

We have few teams who have used Subversion for a very long time. When they were told that Subversion is past and Git is future and that eventually we will move all our source code to Git, they weren’t really happy.

So I decided to gather a list of things which make developer’s life easier when using Git, focus being in the stuff which is real.

With Git…

You are in control

  • You decide when (and how) to integrate changes from others.
  • You decide when and what to commit
  • You decide when the commits are published to others
  • You decide how your commits will look like when published
  • You decide what kind of workflow you want to use

You can truly isolate your tasks

  • You can do as many local branches as you want
  • You can stash your changes aside (or in a branch) whenever you want
  • You can start a branch from any point in the history
  • There’s never need to have same repository checked out more than once on your computer

You can do things fast

  • Really many operations are local
  • You’re not limited by the access speed to the source code server
  • If source code server is offline, you’ll be able to continue working
  • Even though Git repositories come with full history, Git uses disk space sparingly. In most cases repositories on disk are smaller than equivalent Subversion repositories.

You can learn from the past

  • You can really easily check out any version of any file at any time. You don’t even need access to the source code server.
  • You have full history of the repository available at all times.
  • You can quickly view log, blame, branch or diff whatever and whenever you want

You can easily correct your mistakes

  • You can perfect your commits before you publish them. If you want, you can squeeze your 28 commits into one.
  • Totally messed up everything? Just scratch everything since last update from the server and start over.
  • Want to revert what you already published? No problem, you can safely revert any commit when ever.
  • Want to correct type in a commit message? If you didn’t publish your commits yet, it’s easy as taking a lollipop from a child.

You have plenty of backups

  • Every clone of your repository is the whole repository. If your source code server blows up, repositories can be restored really quickly.

You can focus on the most important things

  • Want to ignore some files relevant only for you? Easy.
  • Want to ignore certain files on all clones of your repository? Easy.
  • Want to create a new repository? Shouldn’t take longer than few minutes.
  • Want to publish your local branch to others? It’s one command.

 

Test Driven Sprint Planning – Retrospect

A while ago I blogged about trying out a different method for sprint planning.

The sprint went well, but unfortunately I had to leave that team so I couldn’t continue my experiment for longer than one sprint. I gathered some feedback from the team members to get some idea about whether the experiment was in any way good and if it’s worth to continue it at some point.

Here are the results:


The method of planning tasks as tests-based during sprint planning session:
  • Most team members thought that it wasn’t more complex than usual way of planning
  • One team member thought that it was simpler than the usual way of planning
Benefits for the sprint planning part:
  • Most team members thought it provokes thinking about how specific tasks will be tested
  • One team member thought it makes it easier to find all tasks related to a certain story
  • One team member thought that the tasks also work as acceptance criteria
Sprint execution:
  • Half of the team members had to add more tasks during the sprint, because:
    • wanted to make sure that some minor feature details were working ok
    • the tasks in a story were too little to cover it
Task granularity:
  • Most team members thought the task granularity was good
  • One team member thought the tasks were too big to be able to use them as unit-tests but too small for the story to get fulfilled. This team member wasn’t present in the planning.
Tasks as basis for the  list of unit-tests:
  • Most team members used the tasks as basis for their list of unit-tests
  • One team member couldn’t use the tasks as basis for the list of unit tests. This person wasn’t present in the planning.

So, what did we learn from this experiment? To me this looks promising, there was no single person in the team who thought this was rubbish and shouldn’t be tried again. On the other hand, there were few team members who weren’t part of the planning session and the method wasn’t explained to them in more detail. As a result one team member thought we were trying ATDD, which wasn’t the case. Several people said one sprint is too short time to make any good conclusions and I fully agree.

Regardless of this, I have heard the team still does the sprint planning using traditional methods.