Measure by Math
It's surprising that there's not more math involved in computer programming, since computers are essentially number-processing machines. Words, images, and music are all reduced to numbers for processing. Yet, we rarely need to solve equations as programmers.
Recognizing these opportunities can save us from trouble later on. If we overlook the math and follow an approach that won't work, we'll be disappointed. It's better to do the math upfront.
The Choice to Automate
Automating a process? Let's do the math!
If you'll spend less time writing the code than doing the task by hand, it's worth doing. Otherwise, it isn't.
Many programmers skip this step, but it's crucial. For example, a programmer spends two days automating a task, only to save 15 seconds each time they use it.
To decide, measure the process, then estimate the time it takes to automate it and compare the two.
Let's take a concrete scenario: writing a book about programming. You use Visual Studio for code examples, but Word for the book. The manual process is simple:
- Select code block
- Unindent
- Copy to clipboard
- Undo
- Switch to Word
- Create paragraph
- Paste code
Is this worth automating? Do the math:
Cost side: time to implement automation Benefit side: time saved by automating
Some steps won't change, so ignore those. The rest can be automated, taking effectively zero time.
Time the manual process: 6 seconds. Average 8 code samples per chapter, 20 chapters, and 3 revisions each. That's 48 minutes of saved time.
Now, estimate the time to automate: 1 hour.
The math says don't automate, but it's close. Maybe the estimates were off. Which is more likely: underestimating the benefits or overestimating the time to automate? As a programmer, you know the answer.
If the cost-benefit math is a toss-up, don't automate.
Find Hard Limits
Respect hard limits in your design process to simplify decision-making.
Video game consoles provide fixed limits, such as memory, disk space, and frame rate. We also invent hard limits to clarify our design process. For example, we can set a hard limit on network bandwidth to ensure good performance for most players.
Accepting hard limits can make design decisions easier. For instance, a console's memory limit is fixed, which prevents performance issues caused by virtual memory.
Hard limits are better than trade-offs and soft limits, which can be complex and difficult to understand. In our example, we need to respect a 1 Mbps network bandwidth received and 256 Kbps sent to ensure good performance. We'll design a peer-to-peer game where each machine broadcasts the state of its characters with a fixed amount of information each frame.
In summary, respecting hard limits can simplify our design process and make it easier to create a game that performs well for most players.
In the simplest version of the design, we'll use the native representation for the data to be transmitted. Character positions are three 32-bit floating-point numbers, and orientation is a compass heading also in floating-point. This covers position and orientation, leaving the remaining information needed to reconstruct animations.
We measured the single-player game and found that each character uses six animations on average. To send this information, we'll need to send an animation count, plus data to reconstruct each active animation. This includes an 8-byte ID, a 4-byte timeline value, and a 4-byte blend factor.
The math for each character is:
- Position: 12 bytes
- Orientation: 4 bytes
- Animation count: 4 bytes
- Each animation: 8-byte ID + 4-byte timeline + 4-byte blend factor = 16 bytes
- Total: 12 + 4 + 4 + 6 × 16 = 100 bytes per character
This seems manageable.
Your game design needs to broadcast information about each character 60 times per second. You send three copies of this information to each of the three peers, and also receive information from them. This means you need to multiply the numbers to calculate the bandwidth usage.
You have 30 characters, and each one takes up 116 bytes. You need to multiply these numbers by 3 (for the copies) and 8 (for the bits per byte).
30 (frames per second) × 3 (copies) × 30 (characters) × 116 (bytes per character) × 8 (bits per byte) = 2.5 Mbps
This is 10 times your available bandwidth, which means your design won't work. However, it will work fine on your internal 1G network.
To fix this, you can compress the data sent about each character. You can reduce the number of bits needed to represent coordinates and animation names.
After compressing, the math still doesn't work out:
30 (frames per second) × 3 (copies) × 30 (characters) × 16 (bytes per character) × 8 (bits per byte) = 345 Kbps
You still need to make changes to fit within your bandwidth limit. You could reduce the number of characters or send data about characters less often.
The key point is to do the math before implementing the design. This helps you identify potential problems early on and make changes before it's too late.
When the Math Changes
Let's revisit an example where you had to decide whether to automate a manual process to cut-and-paste code samples from Visual Studio into Word. The original process focused on normalizing indentation, and the math showed that automation wasn't worth it.
However, your understanding of the problem was incomplete. The publisher now requires converting tabs to spaces in code samples, too.
Does the original math still apply? No, because the manual process needs to be updated. You need to tweak the process by installing a Visual Studio plug-in that converts tabs to spaces and adding extra undo steps. This affects both the benefit and cost sides of the equation.
The extra steps slow down the manual process, increasing the time it takes to complete. The tweak also adds time spent researching and installing the plug-in, which could have been spent on automation.
New estimates:
Manual process: 10 seconds/operation × 8 samples/chapter × 20 chapters × 3 revisions = 80 minutes + 45 minutes (new time spent on manual process)
Automation: 90 minutes (with extra work of converting tabs to spaces)
The math now favors automation. While you could still do the manual process, it would be slower and require more time to figure out. Automation becomes a better option.
When the Math Problem Changes Back into a Word Problem
When faced with a problem, look for quantifiable constraints and measurable solutions. If you find both, do the math to identify potential solutions that won't work.
But beware that not all problems have a straightforward mathematical solution. Automating a task, for instance, isn't just about saving time. Errors, annoyance, and team sanity can also be considerations.
When deciding whether to automate a task, consider multiple factors, such as the time spent, error frequency, and the impact on team morale. If a task is annoying or can be fixed easily, it may be worth automating, even if the time saved is small.
If you're unsure about a task, don't automate it, even if the numbers look good. Take the time to understand the task and its nuances.
Ultimately, trust the numbers. If you can quickly do some arithmetic to verify the logic of your approach, do the math.