1. 19
    1. 4

      I do actually enjoy to write quite a bit of code before I hit compile. It depends on the problem at hand, and for some things surely it makes sense to have a faster feedback loop.

      But having just spent half a year working on a game every day, there are cases when I write a bunch of complicated code for even an hour, without getting anywhere near to running it and testing. Some code has to be written in larger chunks.

      A lot of times I don’t need to run my code to know that it is correct. Surely I could make a mistake, but I try to program somewhat defensively, throwing asserts whenever there’s a precondition that isn’t completely trivial. People frown upon asserts these days, saying that TDD is the holy grail … but what if the code I need to write is just a 300 lines of an algorithm that can’t simply be split into tiny 3 line methods that are red-green-refactored? What if the problem being solved is more conscise and readable as a 300 line bunch of switch/if statements and bare for loops with indices? Do I really need to run it every 5 seconds to stay on track?

      Say that you’re writing a basic pathfinder, starting from scratch. First you probably want to have some representation of the graph, so you pick one and code it. There’s a clear idea of what the data structure looks like, what the invariants should be, and you just write it. Then when you’re writing the traversal algorithm, you just write down the algorithm with all the invariants as asserts. Surely it’d be nice to have some tests along the way to verify that the code is correct, but those don’t have to be run when writing those 50 lines.

      One might suggest you’d want tests early if you don’t know if the code is really solving the problem you’re trying to solve. I’m not going to argue with that, but there’s great value in looking at a piece of code and thinking about it, instead of just running it and seeing what happens.

      In my opinion, this is what it comes down to. Programmers these days like to run code instead of just looking at it and creating a mental model of what it does. Surely your mental model can be wrong, and you should definitely run and test the code, but you should first be fairly confident in what it will do. There’s nothing wrong with writing 100 lines in one go, reading them over and thinking to yourself “yes, this is definitely correct, I don’t need to run it for now”.

      What if the code has a bug in it? People immediately reach for a debugger and try to step through the code to find the error, instead of just reading the code without executing it first.

      This all breaks down especially in cases when you can’t actually run/test the code and you’re left with just your mind, trying to read the code and make sense of where the error might be. The debugging code by reading it line by line might be the only thing you have left in a lot of cases, and I’d much rather prepare myself to solve the difficult problems, than to optimize for the easy ones.

      Is it more valuable to have a super fast feedback cycle when writing trivial lines of code, or to train yourself in keeping a strong mental model, so that you can use it when the time comes and you can’t use your fancy tools anymore?

      1. 3

        The fact that you occasionally spend more time thinking/coding than running/debugging doesn’t negate the need for fast compiles and, ideally, hot code swapping of some kind.

        I’ve written games with pathfinding and complex fiddly bits of logic and such before. In my experience, even if your code is 100% correct on the first try, games need lots of rendering hooks in to subsystems for visualizing what’s happening. Maybe the AI does something surprising and you want to understand why it does it. Or maybe performance isn’t great and you want to watch the navmesh while you tweak the assets to minimize the work the engine is doing. Being able to change a color or a formula or something, then Edit & Continue is an incredible time saver that leads to better outcomes.

      2. 2

        I’m sympathetic to this argument, but have historically struggled to develop this skill deliberately, not for lack of trying. Any tips for working towards mastering this skill, outside of just doing it in your day-to-day? In particular, I find the right modality for building my mental model of the code typically falls somewhere between verbal and visual, but I’m not sure whether this is habit or optimal.

        I was excited to see this post so I look forward to hearing any tips or further reading you’d recommend on this topic.

        1. 2

          Generally you’d want to have a clear idea of what you want to write before you write it. Almost to the point when you could just tell a robot the instructions and he could do it for you. The mental model doesn’t have to be 1:1 copy of the code though, it may be more abstract, but you should be able to extrapolate the code from it.

          If you’re having trouble imagining how an existing codebase works, then that’s a problem in and of itself, and making changes to it while instantly checking if they’re correct is bound to introduce bugs at some point.

          Say that you want to make a change in a piece of code someone else wrote. You’re not exactly sure what it will do, so you change it, run the tests and see what happens. If it does the right thing, you might convince yourself that the change is correct and move on … but it might also be the case that the tests just don’t cover a new type of bug you’ve introduced.

          The problem was a bit earlier when you start thinking “I’m not exactly sure what this does”. Don’t make changes to code you don’t have a clear mental model of (unless in hurry hehe). Build the mental model first, read through the code and try to understand how it works. You should be able to answer questions like “are there any invariants that I might be in danger of breaking?”.

          It takes a lot of patience to do this, especially the first time around a particular type of code it might take a while before you get used to thinking about it. There are no magic bullets really, you just have to get familiar with the type of program you’re working with.

          One thing that I find very helpful at times is to read the code outside of an editor. If it’s short enough, you can print it out and read it on a paper while scribbling on it with a pencil. Or you can just use a phone/tablet, or just another computer that doesn’t have an editor and read it in a web browser or something.

          Not being able to make changes will force you to focus on what is important.