How to deal with those TDD breaking people? [closed] - tdd

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Personally I really prefer Unit Testing and write them for "good" coverage. (let's say I try as hard as possible to write good tests ;)
As usual some time later someone different needs to add some features to the code (add methods to classes and so on). He doesn't break those written unit tests but refuses to write additional (which would cover those additional features of the code he wrote).
This leads to a big hole in the tdd process (and even worse maybe a broken window effect)
anything I can do to make him write those tests?
how do you deal with those people?

Remember that TDD isn't primarily about generating good unit test coverage; it's about motivating good design first, about ensuring that the code you write does what you expect second, and about providing a body of high quality tests third.
When another programmer extends a class without writing tests, they miss out on these benefits, and you should feel pity on them. But when you work, you will continue to work the best way you know how (test first) because you know that it you get decoupled code that is easy on the consumer, and that your code does what you expect.
The biggest pain for you is that you have to be careful about what you refactor: if you are refactoring code that is under tests, you can go fast, and design will quickly and safely improve. If you are refactoring code that is not tested, you should be extremely cautious about refactoring it (perhaps only using reliable automated tools to do so) or add the tests.
In the end, you will continue to benefit from your use of TDD, because you produce clearer, correct code, faster, while your TDD-impaired colleague will suffer.

Don't approach this as a confrontation! You're asking how to force a coworker to do something s/he clearly does not see any benefit to. You can't make someone use TDD - as you've already seen yourself. The only way a developer will embrace TDD is when someone else helps them reach that "aha!" moment. Be respectful as one colleague to another and show him/her through your actions and be positive in wanting to help him/her get over the mental hump.

Pair Programming. With two people working on something, programmers are much less likely to take shortcuts like this.

If you have a build process you could use a tool like NCover or PartCover and fail the build if the coverage isn't sufficient.

Aside from a company policy and repercussions from their manager, there's not much you can do about it. Maybe there's some way in your Source Control tool to require that anything public have a unit test that's flagged as such.
You could even write a macro that's part of your build process that looks for anything marked PUBLIC (I'm a VB guy), and then checks to ensure that, somewhere in the solution, there's a unit test with a code comment that sufficiently links it. Failing to have an associated unit test breaks the build and sends out an email to the whole dev group that sufficiently shames said non-tester.
Maybe I'll set that up here, now that I think about it...

Track code coverage with some tool, e.g. for Java there is Emma, and generate a report for management with each release. When numbers are too low or go down management should investigate the causes.

Lead by example. Your coworker may simply not understand how to use TDD appropriately. Next time it happens, write a unit test for them. Make sure to point this out to them: "Hey, I noticed you added x feature to the program without a unit test, so I wrote one for you and put it here." This way they have an example and won't feel embarrassed by having to ask how to unit test.
Only do this once or twice. After that, make sure to mention any future occurrences. You'd be surprised at the difference a polite "Hey, you didn't write a unit test for function y, it'd really help me out if you'd write one for me" will make. Remember, you're goal isn't to try making them write tests. It's to make writing tests less of a hassle than not writing tests.
If the above doesn't work, it's time for a discussion with management. You've already tried to resolve the situation amicably, so it's time to consider a less-than-amicable approach.

Teach your co-workers how to do TDD, so that they can turn their brains upside-down (I had that feeling when I tried TDD the first time) and begin to write tests first.
Once I did an experiment with a programmer friend of mine, who did not know TDD. I came to his house and we started writing Tetris using TDD (we spent about 6 hours that day and progressed nicely). First I wrote a test method, and then he wrote the code to pass the test. In the beginning he was slightly opposed to writing "the simplest thing that could possibly work" (such as hardcoding the return values in the first trivial tests) and not planning much ahead, but anyways he sucked it up and followed my instructions. As we progressed, it appears that slowly he begun to understand what was the point in it all.

Play the video of the "Don't tase me bro!" guy as a warning

Related

TDD in an large project: How do you get started? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
Simple question. Let's put on our engineer/project manager hat for a second:
You have a large project and you will have several different developers working on different parts. You have a solid functional spec and are ready to start figuring out your implementation. You want to practice Test Driven Development. Assume you will be given reasonable but not infinite time and money.
How do you start preparing the modules for implementation by the other developers? Do you start writing interfaces or do you start writing tests? Do you mix n' match?
How would you change your answer if you had a team of veteran coders? A team of less experienced folks? Would your coding environment change your decisions?
Strictly speaking - if you are doing TDD (not just Unit Testing) then you start with the tests first before writing the function that the Unit tests actually test.
All functionality that you write needs to have tests written to verify the code that you are about to write.
The developers themselves would be the ones writing the unit tests - functional/acceptance tests are a separate issue and could be (partially) written prior to work commencing.
If the team is not experienced with Unit Testing, they should start implementing features and then writing Unit Tests as soon as each little class/small piece of functionality is finished
Unit Tests (and TDD as a result) are not to test modules of systems - they are to test at a more granular level - that is that functions and classes do what the dev expects them to.
Testing at a higher level is outside the bounds of TDD, and stepping into other types of tests
If you have a good functional spec, I'd split the work...and start working on test cases.
Once you've got the test cases worked out, the developers can begin coding their modules and the tests to go with them.
...and the approach wouldn't change with different developers or coding environment.
Without searching and being fairly new here, I'm guessing there's been a lot of discussion around this, but let me give an answer anyway.
First, I'd ask what you mean by a 'large' project? I've seen some people label a project taking a few months and involving 4 or 5 programmers as a 'large project'. To others, a 'large project' means a multiple year duration and 30 or 40 devs. I'll assume it's somewhere in the middle, given you mention 'several developers'. To be safe, let's assume it's a half year to a year in duration with 5-10 devs.
As others have said, if you're doing TDD you'd start with the tests first, not a lot of design work. The design is emergent. In practice, however, I think there's a balance between the TDD approach (which I see as valuable but not essential) and simply ensuring you have good unit test coverage, which is essential in my view.
If you're a coder yourself and you have experience with TDD, I'd suggest you should be practicing what you'll be preaching. Rather than trying to design the whole system at an abstract level, definining interfaces, and so on, choose a core piece of the system. Make sure to do the simplest thing possible, get a green bar, refactor, add another test, and so on.
The biggest impediment to using TDD on a project with multiple developers is lack of experience with the methodology. Give your programmers a concrete example (even if it's a small bit of functionality) that really shows them how to do it the right way, pair with people as they come onto the project, have regular reviews of people's unit tests, and make sure it continues to be a topic that's at the forefront of what you're doing, not just an afterthought. If you're doing Scrum, make it part of your definition of 'done' for any task/story.
I'd also spend some time setting up something like EMMA or Cobertura (big fan of Cobertura), so you have some hard metrics by which to assess people's tests . effective your tests are, but they are a data point. If you have 20% test coverage, you can be pretty sure people aren't writing the tests they should. Conversely, just because you have 90% test coverage doesn't ensure the tests are good, which is the reason for things like pairing and reviews.
So, the simple answer is: give your guys an example, focus on pairing/reviews, and put some things in place like a code coverage tool to help keep the team honest.
TDD isn't exactly what you're looking for. TDD happens at the beginning of the project and drives development, hence Test Driven Development.
What you're likely looking for is a test writing strategy. From being on numerous big projects that have implemented testing later on, here are some tips:
Start small. Don't try to get 100% coverage on the entire project, choose one class or one set of functions and begin there.
The impulse will be to start with your smallest/simplest class/functions just to get some quick wins and have code coverage at 100% for one file. Don't.
Instead, as you get bug reports and fix them, write tests to support yourself. It becomes an incredibly effective exercise to write tests to demonstrate bug, fix bugs, run tests and not see a bug.
As you get new feature requests, write tests to support yourself. It's the same effect as fixing bugs.
Once you have a few tests written, run them continuously. There's no point to having tests if they're all broken and/or not being run.
True, you don't end up with 100% code coverage, but you can steadily and regularly apply more and more tests and after a dozen bugs or so, you'll have quite a few useful tests. And more importantly, you'll get more and more tests is the "worst" or most problematic areas of the system. We're doing this now with web2project: http://caseysoftware.com/blog/unit-testing-strategy-web2project.
In traditional development (non TDD), between having a functional spec and writing the first line of code there is a lot of designing involved. You would still need to go through this process and this definitely depends on the skill level of the team. The only thing that would be different in TDD is to write the test cases just before writing the code. You obviously cannot write the tests without knowing what classes/interfaces are involved.

To be a lazy developer or not to be a lazy developer? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Am I a lazy developer?
Is it being lazy to use automated tools, such as code generators and such?
Now, I could, if I had to, create all the data layers and entities I needed, but I choose to use CodeSmith to generate my datalayers and entities.
I also use Resharper and I would say it fights with MSDeploy as to which gets installed first after Visual Studio.
Again if I had to, I could code without it, but prefer not to.
Both these tools from my point of view are no brainers as they improve output massively.
But is this lazy?
I'm sure there are purists out there that would say everything should be wirtten by you so you know what everything is doing, but if you can read through the code and see what is happening is that ok?
So am I being lazy or am I just using all the cards in my hand?
In programmers, laziness is a virtue, so don't worry.
It's only lazy if you use a tool to produce code and use it as-is without verifying that the code meets your needs and abides by your standards.
You don'nt need to reinvent the wheel n times, this is done often enough. Briefly I'd state that using tools like the ones you mentioned (within reason) is absolutely no problem...
For you? No, you're not being lazy.
For the guy that doesn't understand what code generators are doing and how they do it? Yes, it's being lazy.
That's the important distinction: You have to know what you gain and know what you're missing by using a code generator. If you don't, it's only a matter of time before you come across a case where you have to be able to produce those classes and not know how.
Both these tools from my point of view are no brainers as they improve output massively.
This means you're not being lazy, you are using the appropriate tools to enable you to concentrate on the important aspects of the job.
It's not being lazy - it's being smart. There's nothing wrong with using every tool at your disposal...as long as it makes you more productive. Using tools for the sake of using tools is a bad idea.
However, if you don't know what your tool is doing under the hood, you should learn about it so if you don't have the tool available for some reason, you can get the job done.
I think that's the wrong question. Laziness is a virtue. I've seen too many programmers who do things the hard way rather than sitting back and thinking for a few minutes to come up with an easier way. I've had so many times that I've said to a junior programmer something to the effect of, "Yes, I respect your diligence in working through lunch and staying late to write the code to do X, but if you'd taken a few minutes to check the documentation you might have seen that there is already a function in the library that does that". Or similar stories.
I'm not familiar with the specific tools you describe, but to me, the question always is, Does this tool actually save me any work? I've tried plenty of "code generators" that basically just create code stubs. So gee, thanks, you wrote the "function x(int, float)", now all I have to to is fill in the actual parameter names and write the code. What did that save me? I've also seen plenty of code generators that write really awful code. So now I have to try to add the "custom" code to this jumbled mess. Wouldn't it have been easier to just write the whole thing cleanly the first time? I've seen plenty of productivity tools where I found it takes me more time to set up the parameters to run the tool than I actually saved by using it. (Like the old joke that it's been proven that jogging regularly really does make you live longer: for every 60 minutes you spend jogging, it adds 30 minutes to your life.) Some tools may produce code or data structures or whatever that is difficult to maintain, so you save an hour today but it costs you ten hours in maintenance over the life of the project. Etc.
My conclusion isn't that you shouldn't use productivity tools, but rather that you should make sure they really are increasing your productivity, and not just giving an illusion of doing so. If in your case you find these tools really do help you, then using them is not "cheating", it's simply smart.
As everyone else already pointed out there's nothing wrong in your use of code generators.
Still I can see downsides and reasons to avoid it in certain particular sitations.
choice of language. Sometimes the very same fact you need a code generator to get your coding started could imply you're using the wrong language for the task. Most times language cannot really be chosen, so code generators remain the best way to go.
code redundancy. Depending on the actual generators used, generated code could be redundant, if this happens and generation happens once, isn't automated, and generated code goes into the main repository maintenance problems could arise in the long run. Not really a problem with code generation itself, but with the way it should and should not be used.
adding development platforms requirements. We have to concede many programmmers out there work on bread-toasters doubling as PCs. It's really a bad, (and sad) reality of cheap business practices meeting sharp minds. (sharp minds go to waste in the process) It could become a concern if our project (which could have a port in store for the future, and in an external facility either) needs an hefty, ram hogging, not enough cross platform, IDE handy to compile every little modification.
So, no definitive answer on code generating lazyness and programmming: it depends. Then again, using the wrong tools for the job is bad for your health, (and business) so... don't.
You're using all the cards in your hand. Why reinvent the wheel when there are tools available to make your job easier. Bear in mind these tools DON'T do your job, they only assist.
What you create is down to you, so using the tools is not lazy... it's just intelligent.
I'd say you're more efficient rather than lazy.
Programming is primarily a thinking exercise not a typing one. So long as you understand what the tools are doing you're shifting the balance away from typing to thinking. Doing more of what your job is about? Doesn't sound like lazy to me!
I'm sure there are purists out there that would say everything should be wirtten by you so you know what everything is doing
This might have been a viable point of view during the early days of programming. But nowadays, this is simply not feasible (or even preferable). After all, you've already obscured a certain level of understanding just by using a high-level language.
That said, I've found it to be a great learning exercise to write some of these things by hand occasionally. Not only do you get to learn more, but they teach you how helpful these tools really are (or aren't). Note that I'd only do this on a personal project though. I wouldn't do this for any project someone was paying me for (unless I were working for a masochist or something).
Ask yourself why there are so many ORM and other code-generation tools around. I'd say go for it with the proviso that you leave it maintainable for the next guy/gal.
Programming is about being lazy, about automating repetitive tasks. If you can't do that inside your language, using code generators and similar things is a useful workaround.
It depends on what you're writing, of course. I am suprised nobody's brought this up. If you're writing device drivers, operating systems, protocols, or server software (web servers, tcp driven servers, etc), you should probably do it by hand.
But with what I do and probably what a lot of us do is implement business processes in code for web pages or web services. And in those areas, if you can improve on your code with code generators, go for it.
Yes you are being a lazy developer, be honest to yourself, if you take the time to do it the hard way you can call yourself less lazy than you are now.
The point is, being lazy isn't inefficient at all.
Lazy people take time to look at the problems from different direction before acting upon it, this avoids unnecessary errors which saves you valuable time.
So you're being lazy, but that's ok. People don't hire hyperactive coders that make 10 applications each day but leave a trail of bugs on their path. bug-fixing costs time, time is money.
conclusion:
Laziness = profit
Go for it.
I think the best developers are also the laziest. Basically, all you're doing should be focused on getting the end result with the least amount of work. This often provides the best result and also avoids developers from being distracted by fun things to include in a project. A lazy developer would e.g. never add an easter egg to his code, simply because this would be more code, which could introduce more bugs that need to be fixed later on. Adding code is bad, since you'd also add more bugs that you need to resolve later. Still, you will need to add code, else you won't get paid. So, as a lazy developer you would of course choose for the most optimized code, the best-tested code which would almost never fail and you'd work in a way that the chance of errors is reduced to a minimum.
Do keep in mind that lazy developers should focus on avoiding work in the future, not on avoiding work right now! So stop reading here and get back to work! ;-)
Laziness is a trait that most good programmers have. Unless they work for Adobe, in which case they are often lazy in a bad way.

Should I start using TDD on a project that doesn't use it already

I have a project that I have been working on for a while, just one of those little pet projects that I would like to one day release to open source.
Now I started the project about 12 months ago but I was only working on it lightly, I have just started to concentrate a lot more of my time on it(almost every night).
Because it is a framework like application I sometimes struggle with a sense of direction due to the fact I don't have anything driving my design decisions and I sometimes end up making features that are hard to use or even find. I have been reading about how to do TDD and thought maybe this will help me with some of the problems that I am having.
So the question is do you think it's a good idea to start using TDD on a project that doesn't already use it.
EDIT: I have just added a bit to clarify what I mean by struggle with a "sense of direction", it properly wasn't the best thing to say without clarification.
In my opinion, it's never too late to adopt a better practice - or to drop a worse one - so I'd say "Yes, you should start".
However ... (there's always a "but") ...
... one of the biggest gains of TDD is that it impacts on your design, encouraging you to keep reponsibilties separate, interactions clean and so on.
At this point in your project, you may find it difficult to get tests written for some aspects of your framework. Don't give up though, even if you can't test some areas, your quality will be the better for the areas you can test, and your skills will improve for the experience.
Yes.
Basically, you can't do any harm by adding TDD for any new code you write, and any changes you make to existing code. Obviously it would be tricky to go back and retro-fit accurate tests to existing code, but it certainly couldn't hurt to cover the primary use-cases.
Maybe consider having a look at Brownfield Application Development in .NET? It is full of pragmatic and practical advice for exactly this scenario (one of the definitions offered for "Brownfield" is "without proper unit tests").
Yes, absolutely a good idea to start doing TDD.
You will pay a start-up cost for at least two reasons:
Learning a new skill TDD/unit testing.
Retrofitting your code to be testable.
You'll need to do some of both, but as you work if you find yourself struggling think of which of those two is the source of the effort.
But the end result is worth it. From what you describe this is a project you intend to live with for quite a while. Remember that when you lose an hour here or there. In a year you'll be very happy that you made this investment both in your skill set and the code base.
At worse, you can just do TDD on new stuff, while you slowly create tests for your existing code base.
Yes, it's never too late to start using TDD. I have introduced TDD to a commercial project that was already running for five years when I joined, and it was definitely a good decision.
While you are new to the technique, you should probably concentrate on using it for the code that you are writing from a clean slate - new classes, new methods etc. Once you got a hang on it, start writing tests for code that you change.
For some of the code, the latter might prove to be difficult, because the code you have written until now is unlikely to be written with testability in mind. There are some techniques to deal with that, but it's probably too early to care about them.
If you are missing a sense of direction, though, I doubt that TDD will help you a lot. You might want to look into Acceptance Testing instead, which is at least as important as unit testing, and will help you focus on the functionality of the system instead of single units of code. The TDD book by Lasse Koskela is a good introduction to both techniques.
Another technique that might help you is the Extreme Programming planning game, where you put pieces of functionality on index cards and prioritize them. I typically notice that getting ideas out of my head and in prioritized order helps me a lot in understanding where I want to go next.
As others have said, TDD shouldn't hurt a project in progress, but think carefully if you're tempted to do large-scale refactoring just to allow testing. Make sure the benefits justify the cost.
I'm a little concerned that you "struggle with a sense of direction." I don't know that TDD will help you there. I find it's a great help for low-level design decisions, but not so great for architecture decisions. Adding TDD to a directionless project sounds a bit like having a baby to save a marriage - unwise. Hopefully I misread your intention.
Yes.
TDD makes it easier for other people to understand the code, as well as it gives the application a better design over time
In theory you were supposed to test first, but you didn't. In this scenario, contrary to others opinion, I wouldn't start with new features.
Take advantage of the 80:20 rule, run a profiler, and put the test cases to the most frequently called piece of code.
Put tests around the house jewel, gut, most-important code.
Put tests around the annoying, always-breaking, recurrent déjà vu buggy code.
Put tests around all bugs you come across before fixing the bug for failing test.
Warning: Putting test cases will require refactoring, which means you must fix something that's not breaking.
If you still love unit tests at this point, you'd be Red, Green, Refactoring on your own.
Absolutely.
Introduce TDD to new code and if time allows, introduce "Comment Driven Design" with your existing code if it's not already tested.
Comment out the block of existing code you need to test
Write your test
Uncomment your original code one statement at a time (if you have an if block, uncomment the entire block)
Determine if your original code ultimately passes your test and if not, re-write to pass your tests accordingly
Writing tests for existing, working code that you don't plan to change doesn't fit with the thrust of TDD, which is to write tests that teach you about the system you're building.
My approach to bringing in TDD mid-stream has been to:
write tests for all new features, and
when changing a piece of code, write a test that covers the existing functionality (to make sure I understand it), then change the test before changing the code.
It can also be beneficial to write tests for code related to code you're changing - e.g., if you're altering a parent class, you may want to build tests around child classes first to protect yourself from potential damage.
Yes, you should. I'm currently working on a project that until recently wasn't covered with unit tests, but we decided that we should start testing our code, so we started writing them now. Unfortunately, I'm the only developer that practices TDD, others just write tests after writing their code.
Still, I found that practicing TDD helps me write better code, and I write it faster than before. Now that I learned how to do TDD, I just don't want to go back to writing code the way I used to.

What are some reasons why a sole developer should use TDD? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I'm a contract programmer with lots of experience. I'm used to being hired by a client to go in and do a software project of one form or another on my own, usually from nothing. That means a clean slate, almost every time. I can bring in libraries I've developed to get a quick start, but they're always optional. (and depend on getting the right IP clauses in the contract) Many times I can specify or even design the hardware platform... so we're talking serious freedom here.
I can see uses for constructing automated tests for certain code: Libraries with more than trivial functionality, core functionality with a high number of references, etc. Basically, as the value of a piece of code goes up through heavy use, I can see it would be more and more valuable to automatically test that code so that I know I don't break it.
However, in my situation, I find it hard to rationalize anything more than that. I'll adopt things as they prove useful, but I'm not about to blindly follow anything.
I find many of the things I do in 'maintenance' are actually small design changes. In this case, the tests would not have saved me anything and now they'd have to change too. A highly iterative, stub-first design approach works very well for me. I can't see actually saving myself that much time with more extensive tests.
Hobby projects are even harder to justify... they're usually anything from weekenders up to a say month long. Edge-case bugs rarely matter, it's all about playing with something.
Reading questions such as this one, The most voted on response seems to say that in that poster's experience/opinion TDD actually wastes time if you've got less than 5 people (even assuming a certain level of competence/experience with TDD). However, that appears to be covering initial development time, not maintenance. It's not clear how TDD stacks up over the entire life cycle of a project.
I think TDD could be a good step in the worthwhile goal of improving the quality of the products of our industry as a whole. Idealism on it's own is no longer all that effective at motivating me, though.
I do think TDD would be a good approach in large teams, or any size team containing at least one unreliable programmer. That's not my question.
Why would a sole developer with a good track record adopt TDD?
I'd love to hear of any kind of metrics done (formally or not) on TDD... focusing on solo developers or very small teams.
Failing that, anecdotes of your personal experiences would be nice, too. :)
Please avoid stating opinion without experience to back it. Let's not make this an ideology war. Also the skip greater employment options argument. This is simply an efficiency question.
I'm not about to blindly follow anything.
That's the right attitude. I use TDD all the time, but I don't adhere to it as strictly as some.
The best argument (in my mind) in favor of TDD is that you get a set of tests you can run when you finally get to the refactoring and maintenance phases of your project. If this is your only reason for using TDD, then you can write the tests any time you want, instead of blindly following the methodology.
The other reason I use TDD is that writing tests gets me thinking about my API up front. I'm forced to think about how I'm going to use a class before I write it. Getting my head into the project at this high level works for me. There are other ways to do this, and if you've found other methods (there are plenty) to do the same thing, then I'd say keep doing what works for you.
I find it even more useful when flying solo. With nobody around to bounce ideas off of and nobody around to perform peer reviews, you will need some assurance that you're code is solid. TDD/BDD will provide that assurance for you. TDD is a bit contraversial, though. Others may completely disagree with what I'm saying.
EDIT: Might I add that if done right, you can actually generate specifications for your software at the same time you write tests. This is a great side effect of BDD. You can make yourself look like super developer if you're cranking out solid code along with specs, all on your own.
Ok my turn... I'd do TDD even on my own (for non-spike/experimental/prototype code) because
Think before you leap: forces me to think what I want to get done before i start cranking out code. What am I trying to accomplish here.. 'If I assume I already had this piece.. how would I expect it to work?' Encourages interface-in design of objects.
Easier to change: I can make modifications with confidence.. 'I didn't break anything in step1-10 when i changed step5.' Regression testing is instantaneous
Better designs emerge: I've found better designs emerging without me investing effort in a design activity. test-first + Refactoring lead to loosely coupled, minimal classes with minimal methods.. no overengineering.. no YAGNI code. The classes have better public interfaces, small methods and are more readable. This is kind of a zen thing.. you only notice you got it when you 'get it'.
The debugger is not my crutch anymore : I know what my program does.. without having to spend hours stepping thru my own code. Nowadays If I spend more than 10 mins with the debugger.. mental alarms start ringing.
Helps me go home on time I have noticed a marked decrease in the number of bugs in my code since TDD.. even if the assert is like a Console trace and not a xUnit type AT.
Productivity / Flow: it helps me to identify the next discrete baby-step that will take me towards done... keeps the snowball rolling. TDD helps me get into a rhythm (or what XPers call flow) quicker. I get a bigger chunk of quality work done per unit time than before. The red-green-refactor cycle turns into... a kind of perpetual motion machine.
I can prove that my code works at the touch of a button
Practice makes perfect I find myself learning & spotting dragons faster.. with more TDD time under my belt. Maybe dissonance.. but I feel that TDD has made me a better programmer even when I don't go test first. Spotting refactoring opportunities has become second nature...
I'll update if I think of any more.. this is what i came up with in the last 2 mins of reflection.
I'm also a contract programmer. Here are my 12 Reasons Why I Love Unit Tests.
My best experience with TDD is centered around the pyftpdlib project. Most of the development is done by the original author, and I've made a few small contributions, but it's essentially a solo project. The test suite for the project is very thorough, and tests all the major features of the FTPd library. Before checking in changes or releasing a version, all tests are checked, and when a new feature is added, the test suite is always updated as well.
As a result of this approach, this is the only project I've ever worked on that didn't have showstopper bugs appear after a new release, have changes checked in that broke a major feature, etc. The code is very solid and I've been consistently impressed with how few bug reports have been opened during the life of the project. I (and the original author) attribute much of this success to the comprehensive test suite and the ability to test every major code path at will.
From a logical perspective, any code you write has to be tested, and without TDD then you'll be testing it yourself manually. On the flip side to pyftpdlib, the worst code by number of bugs and frequency of major issues, is code that is/was solely being tested by the developers and QA trying out new features manually. Things don't get tested because of time crunch or falling through the cracks. Old code paths are forgotten and even the oldest stable features end up breaking, major releases end up with important features non-functional. etc. Manual testing is critically important for verification and some randomization of testing, but based on my experiences I'd say that it's essential to have both manual testing and a carefully constructed unit test framework. Between the two approaches the gaps in coverage are smaller, and your likelihood of problems can only be reduced.
It does not matter whether you are the sole developer or not. You have to think of it from the application point of view. All the applications needs to work properly, all the applications need to be maintained, all the applications needs to be less buggy. There are of course certain scenarios where a TDD approach might not suit you. This is when the deadline is approaching very fast and no time to perform unit testing.
Anyways, TDD does not depend on a solo or a team environment. It depends on the application as a whole.
I don't have an enormous amount of experience, but I have had the experience of seeing sharply-contrasted approaches to testing.
In one job, there was no automated testing. "Testing" consisted of poking around in the application, trying whatever popped in your head, to see if it broke. Needless to say, it was easy for flat-out-broken code to reach our production server.
In my current job, there is lots of automated testing, and a full CI-system. Now when code gets broken, it is immediately obvious. Not only that, but as I work, the tests really document what features are working in my code, and what haven't yet. It gives me great confidence to be able to add new features, knowing that if I break existing ones, it won't go unnoticed.
So, to me, it depends not so much on the size of the team, but the size of the application. Can you keep track of every part of the application? Every requirement? Every test you need to run to make sure the application is working? What does it even mean to say that the application is "working", if you don't have tests to prove it?
Just my $0.02.
Tests allow you to refactor with confidence that you are not breaking the system. Writing the tests first allows the tests to define what is working behavior for the system. Any behavior that isn't defined by the test is by definition a by-product and allowed to change when refactoring. Writing tests first also drive the design in good directions. To support testability you find that you need to decouple classes, use interfaces, and follow good pattern (Inversion of Control, for instance) to make your code easily testable. If you write tests afterwards, you can't be sure that you've covered all the behavior expected of your system in the tests. You also find that some things are hard to test because of the design -- since it was likely developed without testing in mind -- and are tempted to skimp on or omit tests.
I generally work solo and mostly do TDD -- the cases where I don't are simply where I fail to live up to my practices or haven't yet found a good way that works for me to do TDD, for example with web interfaces.
TDD is not about testing it's about writing code. As such, it provides a lot of benefits to even a single developer. For many developers it is a mindshift to write more robust code. For example, how often do you think "Now how can this code fail?" after writing code without TDD? For many developers, the answer to that question is none. For TDD practioners it shifts the mindset to to doing things like checking if objects or strings are null before doing something with them because you are writing tests to specifically do that (break the code).
Another major reason is change. Anytime you deal with a customer, they can never seem to make up their minds. The only constant is change. TDD helps as a "safety net" to find all the other areas that could break.Even on small projects this can keep you from burning up precious time in the debugger.
I could go and on, but I think saying that TDD is more about writing code than anything should be enough to justify it's use as a sole developer.
I tend to agree with the validity of your point about the overhead of TDD for 'one developer' or 'hobby' projects not justifying the expenses.
You have to consider however that most best practices are relevant and useful if they are consistently applied for a long period of time.
For example TDD is saving you testing/bugfixing time in a long run, not within 5 minutes after you've created the first unit test.
You're a contract programmer which means that you will leave your current project when it will be finished and will switch to something else, most likely in another company. Your current client will have to maintain and support your application. If you do not leave the support team a good framework to work with they will be stuck. TDD will help the project to be sustainable. It will increase the stability of the code base so other people with less experience will not be able not do too much damage trying to change it.
The same applies for the hobby projects. You may be tired of it and will want to pass it to someone. You might become commercially successful (think Craiglist) and will have 5 more people working besides you.
Investment in proper process always pays-off, even if it is just gained experience. But most of the time you will be grateful that when you started a new project you decided to do it properly
You have to consider OTHER people when doing something. You you have to think ahead, plan for growth, plan for sustainability.
If you don't want to do that - stick to the cowboy coding, it's much simpler this way.
P.S. The same thing applies to other practices:
If you don't comment your code and you have ideal memory you'll be fine but someone else reading your code will not.
If you don't document your discussions with the customer somebody else will not know anything about a crucial decision you made
etc ad infinitum
I no longer refactor anything without a reasonable set of unit tests.
I don't do full-on TDD with unit tests first and code second. I do CALTAL -- Code A LIttle, Test A Little -- development. Generally, code goes first, but not always.
When I find that I've got to refactor, I make sure I've got enough tests and then I hack away at the structure with complete confidence that I don't have to keep the entire old-architecture-becomes-new-architecture plan in my head. I just have to get the tests to pass again.
I refactor the important bits. Get the existing suite of tests to pass.
Then I realize I forgot something, and I'm back to CALTAL development on the new stuff.
Then I see things I forgot to delete -- but are they really unused everywhere? Delete 'em and see what fails in the testing.
Just yesterday -- part way through a big refactoring -- I realized that I still didn't have the exact right design. But the tests still had to pass, so I was free to refactor my refactoring before I was even done with the first refactoring. (whew!) And it all worked nicely because I had a set of tests to validate the changes against.
For flying solo TDD is my copilot.
TDD lets me more clearly define the problem in my head. That helps me focus on implementing just the functionality that is required, and nothing more. It also helps me create a better API, because I'm writing a "client" before I write the code itself. I can also refactor without having to worry about breaking anything.
I'm going to answer this question quite quickly, and hopefully you will start to see some of the reasoning, even if you still disagree. :)
If you are lucky enough to be on a long-running project, then there will be times when you want to, for example, write your data tier first, then maybe the business tier, before moving on up the stack. If your client then makes a requirement change that requires re-work on your data layer, a set of unit tests on the data layer will ensure that your methods don't fail in undesirable ways (assuming you update the tests to reflect the new requirements). However, you are likely to be calling the data layer method from the business layer as well, and possibly in several places.
Let's assume you have 3 calls to a method in the business layer, but you only modify 2. In the third method, you may still be getting data back from your data layer that appears to be valid, but may break some of the assumptions you coded months before. Unit tests at this level (and above) should have been designed to spot broken assumptions, and in failing they should highlight to you that there is a section of code that needs to be revisited.
I'm hoping that this very simplistic example will be enough to get you thinking about TDD a little more, and that it might create a spark that makes you consider using it. Of course, if you still don't see the point, and you are confident in your own abilities to keep track of many thousands of lines of code, then I have no place to tell you you should start TDD.
The point about writing the tests first is that it enforces the requirements and design decisions you are making. When I mod the code, I want to make sure those are still enforced and it is easy enough to "break" something without getting a compiler or run-time error.
I have a test-first approach because I want to have a high degree of confidence in my code. Granted, the tests need to be good tests or they don't enforce anything.
I've got some pretty large code bases that I work on and there is a lot of non-trivial stuff going on. It is easy enough to make changes that ripple and suddenly X happens when X should never happen. My tests have saved me on several occasions from making a critical (but subtle) error that might have gone unnoticed by human testers.
When the tests do fail, they are opportunities to look at them and the production code and make sure that it is correct. Sometimes the design changes and the tests will need to be modified. Sometimes I'll write something that passes 99 out of 100 tests. That 1 test that didn't pass is like a co-worker reviewing my code (in a sense) to make sure I'm still building what I'm supposed to be building.
I feel that as a solo developer on a project, especially a larger one, you tend to be spread pretty thin.
You are in the middle of a large refactoring when all of a sudden a couple of critical bugs are detected that for some reason did not show up during pre-release testing. In this case you have to drop everything and fix them and after having spent two weeks tearing your hair out you can finally get back to whatever you were doing before.
A week later one of your largest customers realizes that they absolutely must have this cool new shiny feature or otherwise they won't place the order for those 1M units they should have already ordered a month ago.
Now, three months later you don't even remember why you started refactoring in the first place let alone what the code you are refactoring was supposed to do. Thank god you did a good job writing those unit tests because at least they tell you that your refactored code is still doing what it was supposed to do.
Lather, rinse, repeat.
..story of my life for the past 6 months. :-/
Sole developer should use TDD on his project (track record does not matter), since eventually this project could be passed to some other developer. Or more developers could be brought in.
New people will have extremely have hard time working with the code without the tests. They will break things.
Does your client own the source code when you deliver the product? If you can convince them that delivering the product with unit tests adds value, then you are up-selling your services and delivering a better product. From the client's perspective, test coverage not only ensures quality, it allows future maintainers to understand the code much more readily since the tests isolate functionality from the UI.
I think TDD as a methodology is not just about "having tests when making changes", thus it does not depend on team- nor on project size. It's about noting one's expectations about what a pice of code/an application does BEFORE one starts to really think about HOW the noted behaviour is implemented. The main focus of TDD is not only having test in place for written code but writing less code because you just do what make the test green (and refactor later).
If you're like me and find it quite hard to think about what a part/the whole application does WITHOUT thinking about how to implement it, I think its fine to write your test after your code and thus letting the code "drive" the tests.
If your question isn't so much about test-first (TDD) or test-after (good coding?) I think testing should be standard practise for any developer, wether alone or in a big team, who creates code which stays in production longer than three months. In my expirience that's the time-span after which even the original author has to think hard about what these twenty lines of complex, super-optimized, but sparsely documented code really code do. If you've got tests (which cover all paths throughth the code), there less to think - and less to ERR about, even years later...
Here are a few memes and my responses:
"TDD made me think about how it would fail, which made me a better programmer"
Given enough experience, being higly concerned with failure modes should naturally become part of your process anyway.
"Applications need to work properly"
This assumes you are able to test absolutely everything. You're not going to be any better at covering all possible tests correctly than you were at writing the functional code correctly in the first place. "Applications need to work better" is a much better argument. I agree with that, but it's idealistic and not quite tangible enough to motivate as much as I wish it would. Metrics/anecdotes would be great here.
"Worked great for my <library component X>"
I said in the question I saw value in these cases, but thanks for the anecdote.
"Think of the next developer"
This is probably one of the best arguments to me. However, it is quite likely that the next developer wouldn't practice TDD either, and it would therefore be a waste or possibly even a burden in that case. Back-door evangelism is what it amounts to there. I'm quite sure a TDD developer would really appeciate it, though.
How much are you going to appreciate projects done in deprecated must-do methodologies when you inherit one? RUP, anyone? Think of what TDD means to next developer if TDD isn't as great as everyone thinks it is.
"Refactoring is a lot easier"
Refactoring is a skill like any other, and iterative development certainly requires this skill. I tend to throw away considerable amounts of code if I think the new design will save time in the long run, and it feels like there would be an awful number of tests thrown away too. Which is more efficient? I don't know.
...
I would probably recommend some level of TDD to anyone new... but I'm still having trouble with the benefits for anyone who's been around the block a few times already. I will probably start adding automated tests to libraries. It's possible that after doing that, I'll see more value in doing it generally.
Motivated self interest.
In my case, sole developer translates to small business owner. I've written a reasonable amount of library code to (ostensibly) make my life easier. A lot of these routines and classes aren't rocket science, so I can be pretty sure they work properly (at least in most cases) by reviewing the code, some some spot testing and debugging into the methods to make sure they behave the way I think they do. Brute force, if you will. Life is good.
Over time, this library grows and gets used in more projects for different customers. Testing gets more time consuming. Especially cases where I'm (hopefully) fixing bugs and (even more hopefully) not breaking something else. And this isn't just for bugs in my code. I have to be careful adding functionality (customers keep asking for more "stuff") or making sure code still works when moved to a new version of my compiler (Delphi!), third party code, runtime environment or operating system.
Taken to the extreme, I could spend more time reviewing old code than working on new (read: billable) projects. Think of it as the angle of repose of software (how high can you stack untested software before it falls over :).
Techniques like TDD gives me methods and classes that are more thoughtfully designed, more thoroughly tested (before the customer gets them) and need less maintenance going forward.
Ultimately, it translates to less time doing maintenance and more time to spend doing things that are more profitable, more interesting (almost anything) and more important (like family).
We are all developers with a good track record. After all, we are all reading Stackoverflow. And many of us use TDD and perhaps those people have a great track record. I get hired because people want someone who writes great test automation and can teach that to others. When working alone, I do TDD on my coding projects at home because I found that if I don’t, I spent time doing manual testing or even debugging, and who needs that. (Perhaps those people have only good track records. I don’t know.)
When it comes to being a good automobile driver, everyone believes they are a “good driver.” This is a cognitive bias all drivers have. Programmers have their own biases. The reasons developers such as the OP don’t do TDD are covered in this Agile Thoughts podcast series. The podcast archive also has content on test automation concepts such as the test pyramid, and an intro about what is TDD and why write tests first starting with episode 9 in the podcast archive.

How do you prevent over complicated solutions or designs? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Many times we find ourselves working on a problem, only to figure out the solution being created is far more complex than the problem requires. Are there controls, best practices, techniques, etc that help you control over complication in your workplace?
Getting someone new to look at it.
In my experience, designing for an overly general case tends to breed too much complexity.
Engineering culture encourages designs that make fewer assumptions about the environment; this is usually a good thing, but some people take it too far. For example, it might be nice if your car design doesn't assume a specific gravitational pull, nobody is actually going to drive your car on the moon, and if they did, it wouldn't work, because there is no oxygen to make the fuel burn.
The difficult part is that the guy who is developed the "works-on-any-planet" design is often regarded as clever, so you may have to work harder to argue that his design is too clever.
Understanding trade-offs, so you can make the decision between good assumptions and bad assumptions, will go a long way into avoiding a needlessly complicated design.
If its too hard to test, your design is too complicated. That's the first metric I use.
Here are some ideas to get design more simpler:
read some programming books and articles, and then apply them in your work and write code
read lots of code (good and bad) written by other people (like Open Source projects) and learn to see what works and what does not
build safety nets (unit tests) to enable experimentations with your code
use version control to enable rollback, if those experimentations take wrong turn
TDD (test driven development) and BDD (behaviour driven development)
change your attitude, ask how you can make it so, that "it simply works" (convention over configuration could help there; or ask how Apple would do it)
practice (like jazz players -- jam with code, try Code Kata)
write same code multiple times, with different languages and after some time has passed
learn new languages with new concepts (if you use static language, learn dynamic one; if you use procedural language, learn functional one; ...) [one language per year is about right]
ask someone to review you code and actively ask how you can make your code simpler and more elegant (and then make it)
get years under your belt by doing above things (time helps active mind)
I create a design etc., and then I look at it and try and remove (agressively) everything that doesn't seem to be needed. If it turns out I need it later when I am polishing the design I add it back in. I do this over several iterations, refining as I go along.
Read "Working Effectively With Legacy Code" by Michael C. Feathers.
The point is, if you have code that works, and you need to change the design, nothing works better than making your code unit testable, and breaking your code into smaller pieces.
Using Test Driven Development and following Robert C. Martin's Three Rules of TDD:
You are not allowed to write any production code unless it is to make a failing unit test pass.
You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
In this way you are not likely to get much code that you don't need. You will always be focused on making one important thing work and won't ever get too far ahead of yourself in terms of complexity.
Test first may help here, but it is not suitable for all situation. And it's not a panacea anyway.
Start small is another great idea. Do you really need to stuff all 10 design patterns into this thing? Try first to do it "stupid way". Doesn't quite cut it? Okay, do it "slightly less stupid way". Etc.
Get it reviewed. As someone else wrote, two pairs of eyes are better. Even better are two brains. Your mate may just see a room for simplification, or a problematic area you thought was fine just because you spend many hours hacking it.
Use lean language. Languages such as Java, or sometimes C++ sometimes seem to encourage nasty, convoluted solutions. Simple things tend to span over multiple lines of code, and you just need to use 3 external libraries and a big framework to manage it all. Consider using Python, Ruby, etc. - if not for your project, then for some private use. It can change your mindset to favor simplicity, and to be assured that simplicity is possible.
Reduce the amount of data you're working with by serialising the task into a series of smaller tasks. Most people can only hold half a dozen (plus or minus) conditions in their head while coding, so make that the unit of implementation. Design for all the tasks you need to accomplish, but then ruthlessly hack the design so that you never have to play with more than half a dozen paths though the module.
This follows from Bendazo's post - simplify until it becomes easy.
It is inevitable once you have been a programmer that this will happen. If you seriously have unestimated the effort or hit a problem where your solution just doesn't work then stop coding and get talking to your project manager. I always like to take the solutions with me to the meeting, problem is A, you can do x which will take 3 days or we can try y which will take 6 days. Don't make the choice yourself.
Talk to other programmers every step of the way. The more eyes there are on the design, the more likely an overcomplicated aspect is revealed early, before it becomes too ossified in the codebase.
Constantly ask yourself how you will use whatever you are currently working on. If the answer is that you're not sure, stop to rethink what you're doing.
I've found it useful to jot down thoughts about how to potentially simplify something I'm currently working on. That way, once I actually have it working, it's easier to go back and refactor or redo as necessary instead of messing with something that's not even functional yet.
This is a delicate balancing act: on the one hand you don't want something that takes too long to design and implement, on the other hand you don't want a hack that isn't complicated enough to deal with next week's problem, or even worse requires rewriting to adapt.
A couple of techniques I find helpful:
If something seems more complex than you would like then never sit down to implement it as soon as you have finished thinking about it. Find something else to do for the rest of the day. Numerous times I end up thinking of a different solution to an early part of the problem that removes a lot of the complexity later on.
In a similar vein have someone else you can bounce ideas off. Make sure you can explain to them why the complexity is justified!
If you are adding complexity because you think it will be justified in the future then try to establish when in the future you will use it. If you can't (realistically) imagine needing the complexity for a year or three then it probably isn't justifiable to pay for it now.
I ask my customers why they need some feature. I try and get to the bottom of their request and identify the problem they are experiencing. This often lends itself to a simpler solution than I (or they) would think of.
Of course, if you know your clients' work habits and what problems they have to tackle, you can understand their problems much better from the get-go. And if you "know them" know them, then you understand their speech better. So, develop a close working relationship with your users. It's step zero of engineering.
Take time to name the concepts of the system well, and find names that are related, this makes the system more familiar. Don't be hesitant to rename concepts, the better the connection to the world you know, the better your brain can work with it.
Ask for opinions from people who get their kicks from clean, simple solutions.
Only implement concepts needed by the current project (a desire for future proofing or generic systems make your design bloated).

Resources