# Reflections on Game Programming

Lessons on programming, technical leadership, open source, delivery, overtime, and pragmatic engineering.

> While taking some time off at home, I looked back on my work over the past few years. Here are a few lessons from that experience.

## What makes a strong game programmer?

- The ability to argue a case constructively. Persuading someone to change their mind and cooperate is difficult. Pulling rank—“I am your manager” or “my manager said so”—does not count. A stronger approach is to understand the people involved, consider several perspectives, and propose a sound solution.
- Foresight. When designing a framework, consider future iterations and anticipate requests designers may eventually make, even if they deny needing them today. Make those requests quick to implement within the existing architecture.
- Ownership. Become the person who knows a module inside out. Deliver your own work well, but also help drive requirements forward and suggest solutions to colleagues in other roles.
- Efficiency. Use tools well, or write automation for coding and testing. The practical results should be faster delivery, fewer bugs, less rework, and less overtime.
- The ability to tackle hard problems, such as a critical algorithm or a fatal bug.
- Breadth of knowledge. Do not limit yourself to a single language or technology. Each has strengths; use it where it fits.

## What makes a strong lead programmer?

- First, be a strong programmer, and then go further.
- Judge people well. During a short interview, identify candidates who suit the team. Being a good fit is not the same as reciting interview answers: look for the qualities above, or the potential to develop them.
- Assign work thoughtfully rather than treating people as interchangeable tools. Match tasks to strengths or skills that need development, and give people substantial autonomy. Good work should also help them grow.
- Keep the schedule under control. Estimate requirements accurately, allow team members some buffer, and show designers a prototype as early as possible.
- Understand the game deeply. Know both what designers ultimately want and what matters most to them right now. That helps with iteration and scheduling.
- Retain people. Advocate for their interests and give them room to grow. Put plainly: pay them adequately, or at least do not let them feel mistreated.

## Thoughts on open source

- Code is a programmer's underwear: it is not something you show everyone casually. Publishing it means exposing what is underneath. If you show it, make sure it is worth showing.
- Do not open-source something just for the sake of doing so. Build something useful rather than another unnecessary wheel. A project or library should help other people, not merely show off how impressive an old project was. I will leave aside projects that use gimmicks to collect stars.
- Open source can improve your overall ability quickly. In a sense, it is a mutual exchange of free work. Communities contain all kinds of people, each with their own needs. Contributors and users can both benefit. Every interface and feature makes you ask: is this useful to most users? Does it add unnecessary bulk? Could it be more general? Is it extensible? We rarely ask those questions as consistently in our own closed-source projects. Over time, that habit leads to better code, with the high cohesion and low coupling we aim for.

## Improving feature-development efficiency

This workflow came from a more experienced developer, and it has worked well for me:

1. **Review the requirements with the designer.** Before the cross-functional meeting, read the document, record questions, and ask for clarification where possible. In the meeting, go through it line by line and resolve every uncertainty. This step matters.
2. **Agree on configuration-table fields and formats with the designer.** Ask for temporary data that covers testing, then implement import validation. This step matters even more: once the configuration is settled, the whole data model is usually clear in your mind.
3. **Agree on the client-server protocol.** The backend should also define the persistent database structure. Communication and interaction between the two sides are now established.
4. **Write test cases.** Include this step whenever possible, before implementation.
5. **Write the code.** By this point, you should understand the system's requirements thoroughly.
6. **Hand it over for testing**, then enjoy a well-earned breather.

## Thoughts on overtime

- Nobody likes overtime, but it can be difficult to avoid in game development. It is often about a shared deadline, such as finishing a particular build, when the whole team needs to be available.
- I see overtime as sometimes reflecting insufficient capability or time wasted during normal hours. Working with full concentration from 9 a.m. to 9 p.m. is exhausting.
- I can accept overtime when it is not imposed as a blanket company policy. Even when the extra hours are less intense, they can be used productively—for example, to improve something or prepare for a future version.
- Game teams need considerable face-to-face communication, so their schedules should overlap. If some people work very late and arrive late the next day, while others keep the opposite schedule, it becomes difficult to find someone for a quick requirements discussion. That can block progress unnecessarily.

## Other lessons

- A technical expert is a bonus for a team, not an absolute prerequisite. Technical research should ultimately serve delivery.
- Code should be simple and easy to understand. Ideally, colleagues outside programming should be able to read it and even spot a bug.
- In most game-development work, unless you are pushing the frontier, someone has already solved the problem. Be cautious when a design or implementation departs from established approaches. If you thought of it, others probably did too; there may be a reason they did not choose it.
- When you discover a bizarre piece of old code, do not rush to delete it. Code does not lie; an unusual product or design requirement may explain it.
- Code itself is often the best documentation. Still, explain special handling and temporary code—at least leave a `// TODO`, or expect criticism later.
- Programmers bridge human intent and computers. Ideally, every line we write reduces repetitive manual work in the future, even if getting there requires considerable thought. A good programmer should be eager to think and reluctant to repeat manual work.
- Avoid over-optimization, particularly on the server. Debating whether `++i` is faster than `i++` misses the bigger picture. Hardware is comparatively inexpensive; project progress matters far more than meaningless micro-optimizations. Optimize when something becomes a real bottleneck, rather than for its own sake.