News for hackers. Stuff that matters.
Re:How to avoid brittle code by AnimalMuppet on Monday March 28, 2016 @07:00PM (#11378158)
> It's perfectly possible to write spaghetti code and write a badly written test that notionally covers it.

Absolutely.

> Good coders code well. Bad coders don't.

Also true.

> TDD doesn't help here and if there is any relationship between TDD and good design, I'm certain it's correlation not causation.

I've used TDD and not used it. And when programming using TDD, my code was less "spaghetti" - more modular, better-designed interfaces. There definitely was causation, in my case - it made me write my non-test code differently. So that's anecdote and not data, but holding the programmer constant and changing the methodology, the style and quality of the code changed.

> >No, not "by their nature". Unit tests are supposed to test that a "unit" has the intended external behavior.

> i.e. it couples itself to a unit, which is an underlying implementation detail.

> If it's coupling itself to an externally facing interface it's an integration test or an end to end test.

Let's get specific, so that our terms can be better defined, and we can make sure that we're not just arguing about definitions of terms. Instead of "unit", let's say "C++ class". Now: By my definitions, my unit test should test the behavior of the public API of that class, not the private implementation. So the API is an implementation detail of the project, but not of the class. I will agree that the unit test definitely couples to the interface of the class. Done right, though, it doesn't couple to the implementation of the class.

> How those units talk to one another (their API contracts) is basically the most critical aspect of your project's architecture and the single biggest source of unavoidable technical debt.

A bigger source of technical debt than the bugs you can't find that are buried in the implementation of some class? I doubt it. And good tests mean that those bugs don't make it very far before getting exposed.

A bigger source of technical debt than that API that you don't know how to use, and so you call it wrong? Tests can actually serve as documentation for how to use an API. You have non-test documentation? You're lucky to have that, but the problem is, when the code implementing the class changes, the documentation might well not. If that happens with the tests, you find out the first time you run them.

Re:How to avoid brittle code by crdoconnor on Tuesday March 29, 2016 @05:46AM (#11380434)
>Let's get specific, so that our terms can be better defined, and we can make sure that we're not just arguing about definitions of terms. Instead of "unit", let's say "C++ class". Now: By my definitions, my unit test should test the behavior of the public API of that class, not the private implementation. So the API is an implementation detail of the project, but not of the class. I will agree that the unit test definitely couples to the interface of the class. Done right, though, it doesn't couple to the implementation of the class.

In almost all cases (the exception being if the class is the core of a library's externally facing API), the class itself is an implementation detail.

>A bigger source of technical debt than the bugs you can't find that are buried in the implementation of some class?

Yes, obviously. Bugs are not technical debt.

>And good tests mean that those bugs don't make it very far before getting exposed.

And integration tests are generally better at finding said bugs than unit tests since they test more realistically.

>A bigger source of technical debt than that API that you don't know how to use, and so you call it wrong?

Is again, a bug - not technical debt.

Unit tests are horrible for this since they require you to mock APIs that you're calling. The test which mocks the API wrongly won't catch that bug but the integration test that uses the real API will.

>Tests can actually serve as documentation for how to use an API.

Yes they can. Integration tests can double as a specification for an entire application which is even better than a documentation for a (potentially) badly architected API.