I strongly recommend against reading Clean Code, because it only applies to Java-like languages, and it doesn't really make good advice anyway. It doesn’t even properly apply to C++, and certainly doesn’t apply to languages with different models (like Ruby or Python).
Uncle Bob has made a very successful business out of saying things that sound profound, become popular, but are at best the technical equivalent of fortune cookies, and at worst are profoundly bad advice.
Seriously, in TypeWars[1], he says “My own prediction is that TDD is the deciding factor. You don’t need static type checking if you have 100% unit test coverage. And, as we have repeatedly seen, unit test coverage close to 100% can, and is, being achieved. What’s more, the benefits of that achievement are enormous.”
This is so profoundly wrong on so many levels that it isn’t funny. How do you measure coverage? If you’re doing it by lines hit (which is how most dynamic language coverage tools do it), then you’re not getting any sense of how good your boundary conditions or branch coverage is. If you have a better way of measuring coverage (typically branch coverage), then maybe aiming toward 100% is good, but hitting 100% coverage is a complete waste of time. (I aim for ~85% coverage, depending on the code base and how much is boilerplate code.)
In Ruby, do you really need a unit test for:
attr_accessor :foo
If you don’t at least
access `foo`, SimpleCov will say that line isn’t covered. You know what? It doesn’t
need coverage, because when you write a unit test for that you’re writing a unit test for the language.
Unless you’re actively adding “attack tests” to make sure you have all of your boundary conditions covered, and at least know you can abort or recover from an error condition properly, your 100% coverage means absolutely nothing. Property Checks are better for this. Fuzzing and mutation tests matter to help find this. Even static typing (of which I’m not actually a fan, because 15 years with C++ makes it clear that static typing is not that useful in weakly typed languages) can help find certain types of boundary conditions (look to Ada, where if you declare a type as a range 1..100, only values within that range, or variables that can never exceed that range, can be used with that range).
And people take Uncle Bob seriously, even when he posts things that are just asinine attacks on people who have taken him to task when he is wrong (which, IMO, is far more often than he’s right).
[1] http://blog.cleancoder.com/uncle-bob/2016/05/01/TypeWars.htm...