
How TDD Can Prevent Over-Engineering - kiyanwang
https://itnext.io/how-tdd-can-prevent-over-engineering-1265a02f8863
======
dkrikun
Nice article, the problem though, is that TDD'ing might already be over-
engineering in the first place.

~~~
Arnt
Well, possibly, and the dark side moon might be made of green cheese.

"X _is_ … because y _might be_ " is poor rhethoric. "Is" is the indicative
mood, "might be" is the conditional mood, so such an argument lets the
conditional overwhelm the indicative. That's useful if you wish to mislead or
confuse, less useful if you wish to clarify.

Please supply an argument that TDD sometimes/often is overengineering.

In my experience (such as it is) the tests are shaped by the best-understood
parts of the business goals. I've seen some ugly overengineering in the past
decades, but most of them happened when people went off and implemented parts
of the system that were not yet well understood.

~~~
eesmith
"Please supply an argument that TDD sometimes/often is overengineering."

Sure. TDD encourages building so things can be tested. This often results in
creating code with small functions, each of which can be isolated and tested.

However, these small functions are not part of the external API, that is, they
are not meant for general consumption from the rest of the system. Sounds
great, right?

If you want to refactor the code, eg, to merge 5 functions into 3 different
ones because you have a better idea of how the code works, or it's more
maintainable, or because it gives the compiler more abilities to optimize,
etc. then you've changed the internal API - which is find because it's not
supposed to be stable.

But it now means you now need to change all of your test code. That is, you've
over-engineered your system so it gives a strong preference for one specific
design, and inhibits changes towards other designs.

A better way to handle this is by figuring out what the (semi) stable API is
supposed to be, and test through that API. This moves the tests towards
integration testing or system testing, and away from classical unit testing.

It's entirely possible to do TDD this way, but it's not how TDD is often
taught or described.

I've seen this in the small, at our local Python user group meeting, when we
worked on a challenge programming project. The TDD expert wrote about 4x the
code that a "spike and stabilize" programmer did, because the TDD code
resulted in several functions - each with tests - while the latter had just
one - again, with appropriate tests. Each of those function defs takes up
space. Each of those tests take time to write.

I've also seen this in the large, by analyzing the source code for TDD
projects like FitNesse.

