DEV Community

Discussion on: What programming best practice do you disagree with?

Collapse
 
nickhristov profile image
Nick Hristov

TDD. In any environment which is somewhat agile you will have evolving requirements. Evolving requirements means evolving code or even design.

This means that you will end up writing a lot of test code which gets thrown away.

You should totally write unit tests for your code. And you should think how to split your code to make it testable. But don't put the carriage before the horse.

Collapse
 
darbyo profile image
Rob Darby

Would you not change the test first to reflect the impending code refactor? Do you only see value in refactoring production code and not unit tests?

The whole point of TDD is to give you confidence in what you a writing.

Collapse
 
nickhristov profile image
Nick Hristov

My point is that tests have a tendency to solidify existing code.

If the code is changing before it's even released, this is time wasted.

Write the code, solve the use cases, then write your tests. Before you have something concretely written, things are in flux and writing tests at that point is a waste of time.

That said, sometimes I break this philosophy. Sometimes I write unit tests immediately after I have written a small component.

But to take tdd as an overall approach to development would be hard to justify in my opinion. Maybe exceptions are if you are writing machine control software, or mission critical application. But in such cases you are probably using waterfall.

Thread Thread
 
darbyo profile image
Rob Darby

Sorry but I have to disagree. A large point of TDD is to allow for this. You write a test that describes the functionality that you want, then write the implementation. After you can refactor, change, rewrite the implementation as much as you want and the test it still valid. If you need to change the functionality then this can be done be first updating the tests.

If you work in an agile environment as you suggested you should be creating small, potentially shippable products. So once you have implemented something, it shouldn't be changing too much especially before you release, as it will have been agreed before brought into sprint.

Thread Thread
 
ghost profile image
Ghost

I don't understand the benefit of doing the tests first, the important thing is to test everything possible, doing the test first is very weird to me; I think that it depends of how you solve a problem, your mental frame it may work for you but to force it to everyone I think is a mistake. Is like forcin to make a drawing when you take notes or to make a mind map, do it if it helps but force someone who doesn't is just cumbersome. And agile is not always best or even possible.

Collapse
 
richardcochrane profile image
Richard Cochrane

It probably sounds wishy washy but I hate (and my team hate) HAVING to do TDD - preferring to have it as another tool in the toolbox, to be used when the requirement supports it. I find TDD works really well when I know just what I want, i.e. I need a class for a report that can print, download via csv or display onscreen - I can take what was requested, write tests and then make sure that my code works all nicely. But sometimes dev is a bit more exploratory - the exact solution provided is one that we have to feel our way towards, where the requirements themselves are not completely certain and you have users who need to spend some time actually working with a rough version of the feature to refine their own requirement, TDD doesn't help. One could argue that this would necessitate a prototype stage as part of requirements (that occurs before dev starts) but when that prototype needs to be functional and it would be quicker (or more resource efficient) to show something in real code rather than building a completely separate prototype, tests first is a really big hindrance to exploring solutions.

Collapse
 
ianisfluent profile image
IanIsFluent

Interesting! I couldn't disagree more :) to give you the confidence to refractor and improve your code (making it more readable, maintainable and easier to extend) you need good resting coverage. And if you use TDD for a while you realise that it actually makes the process of writing deep internal functions in your software faster, because of the much tighter feedback loop as you make changes.

Collapse
 
nickhristov profile image
Nick Hristov

So curious. When you write your code, do you end up writing it and structuring it correctly on the first go?

My process is always write some code, evaluate the abstractions, write some more code and see if the abstractions present are still good enough. This sometimes means that I need to refactor something pretty much immediately after I have written it because I made an assumption about something or I forgot about something. Or I realize that I have repeated functionality which needs to be dried.

In other words, when I write code, the first 40% of the effort is quite fluid and subject to change.

This does not mean that I start without having a solution in my head, or a plan. It doesn't mean I haven't thought about the problem. But the reality is that my solution are never 100% on point.

Thread Thread
 
rossdrew profile image
Ross • Edited

This sometimes means that I need to refactor something pretty much immediately after I have written it because I made an assumption about something or I forgot about something.

And that is exactly what TDD is supposed to support. You write a test that describes stepwise functionality until you have your application. Then you can refactor, change, rewrite as you desire and the tests still describe your use case.
I find people who are strongly against TDD tend to be the people who have been exposed to it wrongly.

The only people I think have a healthy view of TDD are those who say it's useful but not as a religious dogma. Essentially, anyone but obsessives and dismissives, which is true for any technology or methodology.

Take one of my personal projects. 100% TDD developed. Which -while not perfectly designed- lends itself to a very easy to understand, compose and modify structure and through TDD is forced to evolve positively.

Thread Thread
 
ianisfluent profile image
IanIsFluent • Edited

Yeah, this is interesting. Like anything it doesn't apply 100% of the time. The place where TDD works well is once you know what you're doing! Because otherwise, of course, you can end up testing things in the wrong place, as you realise things won't work and have to refactor them.

But in the case of bug fixing and adding simpler cases, where your tests are already there, writing a failing test first is an amazing habit to get into.

I think the counter argument to the whole 'but I'll have to keep rewriting my tests!' is, if you're not sure how to structure stuff, write the acceptance / integration test first - because you probably won't have to change that - and then start trying to work out how to satisfy that. Once you have something working, you can start TDDing with your unit tests until it is complete :)

Thread Thread
 
rossdrew profile image
Ross

While I wouldn't push anyone towards TDD, I would strongly push people away from integration test based development. The testing is not fine grained enough and test only a "walking skeleton", they are slower and they allow for terrible design. It's very easy to write integration tests which pass with a mess of interdependent code but very hard to do it with unit tests.

The major benefit of (Unit)TDD is that is pushed you to think about separation of concerns, ergo, good design.

Thread Thread
 
ianisfluent profile image
IanIsFluent

Cool. I am trying to do as Uncle Bob says ;) I want integration tests to check that the code does as the end-user needs, regardless of its internal structure.

Agree that doing ONLY end-to-end / integration tests is a bad idea, as you say.

Collapse
 
aturingmachine profile image
Vince

I used to be super against testing, more so testing every edge case. Until I worked on a large project and was tasked with refactoring a complex and extremely important part of our application.

Being able to make changes confidently backed up by the tests is an amazing feeling.

Thread Thread
 
ianisfluent profile image
IanIsFluent

Once you've had that feeling - you realise how precarious things felt before!