CleanCoders - Mobile App Case Study Review

Learning is hard and comes in many forms. I have recently finished watching "Mobile Development with Swift" an online ~10 hour video series by Robert C Martin of the Clean Coders website. It aims to teach you about mobile development, test driven development and clean code. What did I learn? Was it worth it? And should you give it a go? Let's find out.

In this blog post I’m giving a personal review with my thoughts and opinions. Uncle Bob himself is an opinionated guy and I get the impression he can appreciate this style of post. My aim is to help you understand what I saw as the key takeaways of this video series so you can make an informed decision about watching them yourself. I’m also hoping that this feedback can inform your approach for any video series you might want to make in the future.

Get ready for quite a trip as we spend 7 episodes (21 tomatoes) TDD our way to a GoMoku application using XCode and Swift.

As you watch us you'll see the problems we had with the IDE, with the language, and with the framework. You'll also see how we solve them, and drive the application from it's initial meager beginnings to a final scalable architecture.

The video series comes in seven parts. Uncle Bob and Justin Martin sit down together and create a Swift application of the board game Gomoku using Xcode. They use a test driven development (TDD) approach and work in pomodoros - meaning they code for 25 minutes, take a 5 minute break and then repeat for three sessions per video. In the break they try to reflect on their decisions so far and discuss the direction they are taking.1

My initial feeling before I watched the videos was one of excitement. This is going to be great, getting to watch a legend writing code, seeing all his tricks of the trade. Watching a TDD master flex his testing muscles. I also don't know Swift that well and iOS application development at all so this series gives me insight into the platform to start writing an app myself. Let's see how those thoughts pan out.

Test Driven Development

XCode and the standard tooling was used for writing and running tests. Bob was spot on with his criticisms here, the speed of iteration when running the tests is super slow. When doing TDD you want your tests to run instantly; if you have a single test it should run in something like 0.001s. Instead, the test suite as they had it set up would have like a 3-5 seconds cycle. This becomes painful when you want to run the tests over and over.

it seems like the IDE developers have never done TDD

I noticed Bob would start doing changes without updating the test name, so I wasn't sure sometimes what they are attempting to do or change in the code. I feel this is a pairing faux pas. The first thing you declare and agree on as a coding entity together is the test name, this sets the direction and the scope of what you want to do together.

The great thing about these videos is when a discussion happens around the code. The Swift language is very type safe and Bob was feeling this was leading to verbose code at times. This lead to the declaration that if you are doing TDD it doesn't matter how much power the type safety of a language gives vs a more dynamic language, the tests you have written will keep you more safe than anything.

one gets the feeling that the people that wrote this testing framework did not write a lot of tests

A lot of people talk about TDD and how they "do it all the time". My opinion has always been that it is a tool, and each tool has a time and place. I noticed this happening in the videos. Bob was coding the board to be shown on the screen and using maths to display 20 vertical and horizontal lines. This is not something I have much experience of and so I would have definitely TDD'd this area, however they did not! They did look back in the pomodoro break and mention this, but I like to see it as an acknowledgment that just because you know TDD doesn't mean you have to TDD every single thing ever. If you understand the problem space and feel you don't need that support, then don't use it.

For what concerns that age-old question of when to deduplicate code, there’s different schools of thought. Some do it at the first duplication, when the same snippet appears two times; some when it appears three times. Apparently Bob likes to remove it when it's twice in the code; I disagree and think it should be 3 times. The first duplication is to me some kind of “coincidence”, that can be tolerated, but when that duplication occurs again, it’s time to refactor.. This saves a bit of premature optimisation and the risk of creating the wrong abstraction. It was also painful to watch them refactor as XCode does not make it simple. Possibly another reason would be to wait until three times.

doing UI changes can be an alternative to TDD at the GUI level

A great point was that TDD gives a quick feedback loop and so doing small GUI changes quickly can be an alternative to TDD at the unit level. This is a great way to think about the GUI, running the UI code and testing it with your eyes. I always had a problem with the lack of TDD at the user interface level and I was glad to hear this little factoid.

Learning Swift & iOS

One takeaway is definitely that XCode sucks as an IDE. Bob attempted to be political in the video and not blame the IDE but the more they wanted to use the tools they realised the tools were lacking. Swift is a typesafe language but there is no support for refactoring in the IDE. The closest you get to automated refactoring (for example: extracting a method) is search and replace, which is stone-age stuff for those used to JetBrains’ and Microsoft IDEs.

I felt the videos didn't allow you to learn much Swift or gain much iOS knowledge, which was a shame. I watched them coding and so I wasn't hands on, which is one downside in addition to that they weren't Swift experts themselves. That’s fine to an extent, although when they had problems it seemed they would go away off camera and find out the answer then come back with the solution. It would have been nicer to go on this journey with the developers watching them "google it".

swift has type safe exceptions, every other language has abandoned them

A thought provoking storyline of the videos was the use of exceptions. It seems that you cannot have runtime exceptions in Swift, so any exception that is stated has to be declared by all calling methods up the chain. After a while this got too painful for Bob and they switched to returning a tuple from these methods with an optional result and optional error. It was a really interesting discussion and good to watch the code evolve. I'm still not sure that the tuple was the answer but the app works, that's the main thing.

I'm not sure why but they kept fighting against the language to avoid using the named arguments. I disagreed with them but I quite enjoyed (and learned from) watching them lament and argue with the codebase. It reflected a lot on conversations I've had when coding.

Named arguments allow you to have more readable methods invocations, such as fireMissile(at:England, lat:35, long:32). Here, the at, lat, and long are the named arguments. If you want to, you can declare that you don’t need to name them explicitly, so the invocations would look like this: fireMissile(England, 35, 32). Unfortunately, this got them into a corner. They decided to change the parameter order of two methods but without named arguments they were not sure what method invocations they had done and which were still left.

Keeping the named arguments would have helped so much and I really like that feature in Swift. On a similar note, they got rid of an object they had called Intersection (this was an X,Y position) in favor of an int X and int Y. The videos seemed to gloss over why they removed it but I felt this was a good abstraction that would have minimised the named args problem to a single object construction.

I did learn a few parallels with what I’m used to in Android development:

• gesture recogniser & custom view constructors are the same as Android
• setNeedsDisplay() is the same idea as invalidate()
• paint.stroke() is similar in idea to a custom views onDraw()

I felt the videos were lacking a real discussion about the iOS framework. Making a game you get away with not knowing as much about the framework (vs writing an app) but I was disappointed to not learn how to navigate around or understand the iOS lifecycle. A lot of time was used talking about how to find the win conditions in Gomuku, not something I can easily transfer.

A lot was promised in the first video and it felt like they'd already planned to write 8 hours of video so when they realised they wouldn't get it all done in that timeframe they sped up at the end and skipped pieces out.

Organisational techniques

I know I'm an organised person so maybe my next point is an over specification, a TODO list is something I like to practice when I pair and I think it really benefits both of us, before, during and after each pairing session. Contrary to what I had expected, they did not keep any notes or a step by step TODO list. It was not until episode three that they got to writing a high level list on the whiteboard—and then they didn’t follow it explicitly anyway.

I find it really important when working in a pair that you both understand what you are working on (and if I'm watching a video of pairing, then me knowing what you are working on). TDD is great for understanding the current task, you always have the current red test that you are trying to make pass, and both of you know this is the current aim. However in the refactor step of TDD there is no test name telling you what to refactor.

Time and time again Bob & Justin would be talking and say "oh we should fix this later", "ah that'd be nice if we renamed this", "we could extract a class here, maybe once the tests pass". However this knowledge was just kept as a verbal acknowledgement, and throughout the videos they would forget they had said these things. As a result, they missed several opportunities to refactor and clean up the code. In my experience, a notepad shared between the pair to write down these notes works great. I have also watched JB Rainsberger's Intro to TDD which is a great example of what I am talking about.2

Pomodoro technique

I'd heard of the pomodoro technique but never actually done it myself. The explanation in the video of how it works was a bit confusing as a starting point, but then I learnt by example. Each time a pomodoro ended a clip of a tomato being chopped in half would play. I hated that tomato cut scene though, it got so repetitive and I was actually analysing the chop downwards and thinking how unrealistic it looks (instead of thinking of code). Maybe a bit of variety would have stopped me from obsessing over it.

Sometimes the pomodoro allows them to brainstorm for a solution "away from the camera". In the breaks they’d resolve the problem then come back and say “eureka this is the answer”. As a spectator I felt I was missing the real world action of maybe a more heated or confusing discussion or some Googling. In one instance, Justin’s hair changed from one pairing session to the discussion that was supposedly happening straight after, so that gave it away a bit. However it has inspired me to try Pomodoros when pairing, to have that discussion of where are we up to and what do you think of our decisions so far.

I have some minor gripes over the way the pomodoros were treated in this series. Sometimes Bob felt he had to keep talking up until the pomodoro ended but I think you should be more flexible. If there is one minute until the end of the cycle and you have reached some type of milestone, I believe it's ok to finish early and ignore the tomato. That's exactly what Bob did at another time, ignored the tomato to ensure a refactoring was completed and running 2 minutes over. It’s nice to see some pragmatism.

There was no discussion after the final tomato of the final episode, which I found very disappointing. It would have been really nice if they had a little retrospective about what went well, what didn't go so well.

Architecture, or the lack thereof... then, magic ✨

At the very beginning they discussed a global architecture, from the games point of view. This helped direct the responsibilities of some of the code but not everything. I was looking forward to the discussion about what had been created and how this could be refactored into something more fitting with the original episode one discussion. Sadly, this didn't happen. An architecture diagram appeared out of thin air, showing what we had now and what we wanted to aim at. This felt slightly like the architecture was coming from an ivory tower, and an ex post facto rationalisation of what had been already done. I wanted to see some insight in the videos of how this came about and how it was built up from its pieces rather than handed to us on a plate.

Bob reviewed the architecture diagram they had created, they laughed at the mess they'd made "because that's what developers do". However I feel they arrived at this point because they missed the TDD opportunities in refactoring after green tests. This would avoid having to do this "tech debt" and reimplementing the architecture.

I missed understanding the reason for splitting the board model into state and data, with duplicate methods due to the fact the Architecture diagram was just handed to us and only then implemented. That was quite annoying.

I was hoping to learn a lot more about how Bob examined a current architecture then how he would find responsibilities, define interfaces and separate things, but that process was done off camera.

Conclusion

After a while it feels like you are pairing with them, not concentrating on the video of them coding. Rather, you just focus on the code that is being written and the conversation being had. However every time I noticed one of the small issues outlined above it would take me out of this mindset and remind me I was just watching a video (as I couldn't feed back into the pair), which negatively impacted on my learning.

All in all, I enjoyed the video and felt I learnt more insight into TDD and pairing techniques. It gives me confidence that everyone is the same once they sit down in front of that keyboard; 2 years experience or 22 years of experience doesn’t make much difference. I enjoyed Bob's reaction to the tooling for Swift in XCode, and would love to see Apple take this feedback on board. I am disappointed there wasn't more about the iOS framework itself, but making a game is an easy way to avoid this.

There was so much more I could have written but I tried to pick out the major talking points rather than nitpicking or repeating the video content. I would totally recommend any developer watching this. You don't need to want to learn Swift or iOS, but you do have to find and dedicate ~8 hours of your life to this series. My top tip for watching is to have a text editor open and write down anything you find interesting or want to look up more information on later. This way you can watch the videos without pausing.

Here is a link to the video series, https://cleancoders.com/videos/mobile-app-case-study and an acknowledgement that all video image rights are belong to them.

1. From here on out I will say "Bob" to refer to either developer in the pairing session. I didn't write in my notes who actually said what nor do I remember and it flows much better for you reading. So just take "Bob" as either Robert C Martin or Justin Martin.

2. Talking about organisation and the benefits of TDD, reading and responding to email is something all developers have to do when not coding, Inbox 0 is TDD for email. A sneaky clip in one of the videos when Bob was tabbing showed 16,319 unread emails :-) tut tut

3. I was pretty annoyed that the video recording of the first pomodoro of episode 4 was lost. This meant the discussion and resolutions of the two main points from episode 3 (speed of tests and use of exceptions) were lost. Granted these things happen, but the overview that was given instead was really disappointing and it felt the answers were selected without me (like if your pair works on a story with you, but makes major decisions while you’re out for lunch).

4. I had to watch these videos with headphones. The recordings didn't appear to use one microphone for each presenter, just a single shared mic. This means they could not be separately equalised and Bob's voice and Justin's voice are at two different levels. It was really hard to pick a volume level where you could hear them both clearly and not pierce your eardrum when the louder of the two spoke.