Notes from episode 1
Notes from episode 2
Notes from episode 6
Here are my notes from
Comparative Design episode 3,4 and 5 by Sandro Mancuso and Uncle Bob. There were less new things for me in these episodes, more of applying the approach from previous episodes on other use cases (so the notes are going to be short on this one) . Still, I enjoyed it and consider the watching time well-spent. As with previous posts, I will only list stuff that was new or controversial to me as that's what I use the notes for. There's lots of great stuff in these videos that I don't write about because I know them from womewhere else. Also, as these are notes, they are a bit unsolicited and messy - get over it.
- I learned IntelliJ IDEA's shortcut ALT+SHIFT+F10 for launching tests from current class. I didn't know that - thanks Sandro & Uncle Bob!
- A nice comment from Sandro: In outside-in approach, each test represents a design decision
- When doing validation whether a post contains inappropriate words, Sandro delegates the validation (at least the condition) to a separate collaborator and calls it language service instead of "validator" - nice, I never really liked the name "validator". After that, he extracts the condition together with decision to throw exception to a separate method called validate(). Typically, I call methods that throw when a condition is not met assert...() by analogy to how they are called in xUnit frameworks.
- When implementing the "adding posts" requirement, Sandro leaves the repository empty since there is no requirement for reading from the repository yet. I like that - there was no point inventing a speculative reading feature for the class only to see it turn out different in the future when driven by a real use case. On the other hand, however, this might be a singnal that the acceptance tests do not revolve around use cases. Is "add a post and receive OK" really a valid customer use case? What use is adding a post if the post cannot be read? Thus, I would probably have a test where I would add a post and then read it, because from the user point of view, only then is the API useful at all. Well, there may be a case where someone writes their own GUI client and wants to integrate with each method as fast as possible (thus having POST only would be beneficial to them as it would allow them check their client compatibility), but I didn't find anything to confirm this is the assumed scenario here. Also, if I only could do one of read/write in an iteration, I would pick reading first as it would already allow showing the customer how posts look like on the GUI.
- When testing the language service (a piece of code that rejects inappropriate words), Sandro picks "elephant" for a bad value (because "elephant" is one of the inappropriate words), but uses "OK text" for a good value. I would probably pick some text that's closer to the boundary, e.g. "elephan" to show that the whole word has to match to reject it. Several seconds later, Sandro picks some more examples of bad values, some of which I wouldn't think of (e.g. all uppercase ELEPHANT). Sandro's comment on this: "I don't like baby steps". I can understand that - baby steps are typically for exploratory stuff and this is a CRUD app so no surprises are expected here.
- When testing with APIs that accept collections, Sandro uses a single-element collection. I typically prefer 3 elements although I must say that this time Sandro's preference is closer to boundary value testing - interesting :-).
- Another interesting observation is that Sandro does sorting of posts (to have the latest post first) in the repository but filtering of logged-in user (when showing all users) in the GUI. I have to admit (and Sandro does as well) these are hard decisions to make and typically an assumption made on these things gets validates as more code appears.
- The rest of the episodes 4 and 5 are more or less about the same stuff, so I see no point taking too much notes from them. The only interesting fact is that when Sandro registers a following (a relationship saying that one user follows the other) - and, while there is some validation whether the following already exists, there is no validation whether the users exist at all. I wonder why - does Sandro trust that only the UI will use the API and hence no one will send IDs that don't exist?
And that's it. This concludes my notes on Sandro's part (of course, after Bob's part there will be some dicsussion between both of them). As a final note on this part of episodes, I'd like to comment on the example problem that is used in comparative design case study. It's about writing a backend API for a twitter-like app. The best part about the chosen problem is that it is a realistic one and allows showing TDD with randomness, I/O and some other stuff that usually gets left behind in simple examples, end to end from controller to cache (without a real database though). The worst part of it is that it lacks a significant amount of logic around the use cases. Basically, it's almost a plain CRUD app and if we dropped the layering from the design, each use case would take around 10-15 lines of code to implement. And now we come to my greatest source of confusion. Sandro deciding to introduce the layering means he clearly wanted to show how to design something maintainable. On the other hand, some of the choices he made looked to me like cutting corners because this is a very simple app. No thread safety, no authorization, no authentication. Also, unfortunately, no elaborate requirements like "when you create a post and this is a 10th post created during the last second, we will consider you are a bot and disallow you from posting for 10 minuts". The resulting domain model turned out very anemic and consisting mainly of DTOs. I'd rather see less use cases but more elaborate because interactions between entities and domain concepts is where GOOS authors wrote this style really shines. Still, I enjoyed the episodes and I think this part is something that every senior coder should watch as even without an elaborate domain, it contains lots of great insight, tips, tricks and discussion. I look forward to Uncle Bob's episodes and the concluding discussion!