Code Style & Taste
A blog where I share thoughts on code and practices

This article doesn't apply to creating a file format, protocol, or public APIs that third parties will rely on, which all need planning. This article is about software that may change after the public has access to it, which is most software.

Plan Everything?

While I was in school, people would tell me I should plan out my software. They suggested I should have it planned in such detail that I'd know all the functions I'd implement before I start. That irked me back then. It was obviously wrong, and I thought they were full of 💩, but as a student who am I to say they're wrong?

I'll use a text editor (or IDE) as an example since we all used one before. I'm writing one right now so for me these were real problems. Some features a text editor might have

One of the goals is to support large files. Friends (who work on distributed systems) tell me they open >4GB log and json files. It's not unusual for me to open a 600MB json file so a 4GB json file didn't sound like an unreasonable request.

Planning The Text Rendering

One of the key features of a text editor is displaying the text. I could display text by using a GUI system, or I could use a graphic API and do it myself. I choose the latter because there would be fewer limitations even if it's more work. Another goal is to support 4K screens that have a 144hz refresh rate (that's about a 6ms budget).

The first font API I looked at was SDL TTF. It supports

Some people have told me I should plan what functions are called too. Why this is in the planning phase and not real code I don't know. They said it's less work than writing code, but it sounds like they're saying it's less work when you can ignore bugs. If we plan this we'll notice

1) There isn't a way to get the kerning information. You can get a bitmap of "ab" with proper kerning but you can't directly query how much space should be in between. It's possible to figure out the information but it'd be very slow since you'd need to look up every unique pair and it'd involve building a bitmap every time.

2) There's no glyph iterator so to find every letter you'll have to make a call for every glyph in unicode range which is over a million. Since you're in the planning phase, I have no idea how you're supposed to know if the documentation is correct or if making a million calls will be fast enough? IIRC it took 1-2 seconds, which made the startup not great.

Why I don't plan implementation

Once you have plans you'll try to stick to them even after it's clearly a bad idea. Do you want to jump through hoops to find kerning information? Ligatures weren't part of the plan, would they interfere with the workaround code to figure out kerning? If I try to find pairs when they're on screen how am I supposed to know if it can run within the 6ms budget? If I search all pairs on file load how long will that take? Do I assume it'll be long and implement code to block scrolling until a background task figures out all the kerning pairs?

You know what's a better idea than sticking to the plan? Finding out what's important or if anyone will use the feature. Out of all the people I talked to only 2 didn't want to use monospace font for programming. Only 2 people would have used the kerning functionality. The better idea is to drop the feature or put it off until another time.

Another reason I don't like planning is documentation can be bad, wrong, or outright lie. Here's one example that frustrated me. I tried getting nc (also known as netcat) to listen on port 4455 in one terminal and connect to it + send messages on another. If you look at the "-l" flag it says "It is an error to use this option in conjunction with the -p, -s, or -z options." The example shows you can use "nc -l 4477" yet it doesn't work.

The solution is... to use -l and -p together. Try writing "nc -l -p 4477" in one terminal, "nc 127.0.0.1 4477" in another, then type and press enter to send text. If you look at the top of the documentation page it says "Linux man page", I clearly wasn't looking at the wrong OS. This was the first result on a google search and bing first result said the same thing. However, this man page has an example that shows I should use -l -p together 🤯 Ever since, if the man page was online I would always confirm that the domain is man7, archlinux, or debian.

What do I like more than planning?

Iteration. Once you understand the problem you can take a moment to plan, but at a high level. I don't like planning things when I have to guess or rely on documentation. The more you iterate the more you understand the problem you're trying to solve. You don't need everything to be perfect, you don't need to work around every bug you hit.

Write code, see what problems you run into, think about potential solutions, how important the feature might be, if it's worth the workaround code, and if switching to another library (or writing one yourself) might be a good idea. As long as you're not guessing or writing too much workaround code it's usually a good idea to write code even if it's a prototype you throw away. Not guessing means you'll need to read the documentation so if you're avoiding that you'll be spending hours of debugging to save minutes of reading.