Rubberduck Developing: Forced Explanation

Rubber Duck Behind those lighthearted, unassuming eyes is the cold and weathered soul of an invaluable partner in development

Being forced to explain your decisions to someone else will be where you get the most value and learning, not the actual development. If you were to say this to our team at the beginning of the project, our response would have been, "What!? No, we are developers, we learn from doing!" Which, to an extent, we still agree with. However, our documentation forced us to understand; it may have been adding more to the insane workload, but having to write blogs about our process was a blessing in disguise.

From just developing a feature, you won't fully understand what you've done. You will probably have difficulty implementing it again without referencing your code or articles, and you will not remember the downsides of your implementation as compared to the other solutions you could have chosen. You will forget about the answer to these if you just keep continuing to develop the engine, but forcing yourself to explain what you implemented and why you chose this solution will help you remember your decisions (and if you don't remember, writing these explanation down can help you revisit them!).

Although writing for another person, the actual audience of your explanations can just be yourself or your team. Testing documentation is an involved process, one that you won't have time for while developing an engine, but this doesn't mean you can't write as if it were going to be given to someone else. It is similar to the API design of an engine: even if you will be the only one using it, you want it to be understandable by more than just yourself. You won't be able to retain all the decisions you've made when you've finished developing your engine, so your documentation will be there to remind you of certain quirks to a feature and the assumptions you were making.

Pairing an explanation with diagrams of the problem and videos of before and after will take even more of your time away from development, but you will typically learn something that you missed during development. Each of us on the team had some moment during the semester where we were explaining what we had done, only to realize there was an absent optimization, another solution, or even a flaw in our assumptions! While writing about our collision solving system, we were evaluating three different cases for capsule collisions: one for each end, and one for mid-segment intersections. If you're familiar with what a capsule is, you'll know that it's a radius from any point on a line, which means the edge cases are really just the same as the mid-segment case—your intersection point will always be the same distance from the line regardless! This was an optimization that wouldn't have been very apparent to someone looking at the code, as much of our collisions code was riddled with cases.

Collision Solving Image This was the image the tipped us off that we have been thinking too complicated...

You could argue that this takes time away from learning the next system or growing the engine, but making your engine as fast as possible shouldn't be your main objects. Explaning your decisions forces you to slow down and actually digest what you've just done and typically reconsider all the decisions you made along the way. Although this takes more time, it will help you make an engine that is more thought through, and it will stop you from having to investigate many mysterious bugs because you will already know some of the specific drawbacks of your implementation. The next thing to do isn't going anywhere; you will only rackup more technical debt by going as fast as you can, especially if there is an assumption in your implementation that you know now but will forget tomorrow.

Our team feels we must also state that there is something magical between the extremes of documentation. The first extreme, where you only develop and don't reflect or explain, seems easier to fall into; however, as we mentioned abovem, it's not as useful for learning. The other extreme is much less common, where you only write documentation about engine development without any development. The two pitfalls we see from this are 1) this sounds miserable from a developer perspective and 2) you would be writing from a theoretical stance, and theory never translates directly to practice; there are strange bugs that you don't see from just thinking. Pairing application with reflection brings about something unique. Do, then explain.