software development

Make It Anyway: Why Hand-Built Code Matters

Make It Anyway: Why Hand-Built Code Matters

At 11:47 p.m., a blank main.cpp file can feel less like a beginning than an accusation. A coding assistant can suggest a function before you have decided what that function should mean. Modern coding assistants now go beyond autocomplete: official documentation describes inline suggestions, multi-file edit sessions, and agent modes that can choose files, propose terminal commands, and iterate on changes. (docs.github.com) The power is real. So is the odd feeling that the most interesting part of your project has been handed to someone else.

That tension sits inside generative artificial intelligence, software that creates new text, images, or code from instructions. Many coding tools use a large language model, a system trained on enormous collections of examples to predict plausible next pieces of language. Why would anyone still build a small program by hand when a prompt can produce a working prototype? Because speed is only one reason to program.

A project can have two jobs

Some software is a product. It has deadlines, users, maintenance costs, and a team waiting for the next feature. In that setting, reducing repetitive typing can be sensible. The finished behavior matters more than who wrote every line.

A personal project may have a different job. It can be a workshop, a notebook, or a place to notice how a renderer works and why a data structure behaves the way it does. If we judge that project only by shipping speed, we may be measuring the wrong thing. A tool can reduce friction, but friction is not always waste.

Start with a loop, not a feature list

Suppose we decide to make a tiny top-down game: one square, four directions, one room. A game loop is a repeating cycle that reads input, updates the world, and draws the latest state. State means the values that describe the world right now: the player’s position, whether a door is open, or how many points remain.

Game engines package this pattern in different ways. Godot exposes _process for work tied to rendered frames and _physics_process for fixed-rate physics, while Unity describes its Player loop as a repeated sequence of input, updates, and rendering. (docs.godotengine.org)

The smallest version can look like this:

struct Player {
 float x = 40.0f;
 float y = 40.0f;
 float speed = 120.0f;
};

void update(Player& player, const Input& input, float dt) {
 if (input.left) player.x -= player.speed * dt;
 if (input.right) player.x += player.speed * dt;
 if (input.up) player.y -= player.speed * dt;
 if (input.down) player.y += player.speed * dt;
}

A struct is a small bundle of related values. Here, it stores the player’s position and movement speed. The dt parameter means delta time, the number of seconds since the previous update. The ampersand in Player& tells C++ that the function should change the original player object rather than a temporary copy.

Around that function, the loop might read like this:

while (running) {
 Input input = read_input;
 float dt = seconds_since_last_frame;
 update(player, input, dt);
 draw(player);
}

These snippets do not make a complete game. They give you a place where decisions become visible. Should up move toward negative y or positive y? Does the player stop at the room edge? Does diagonal movement become faster? Where do collisions happen? Each answer is a small piece of design, not filler between prompts.

Using dt matters because frame times vary. If movement advances once per frame without it, a machine drawing twice as many frames moves the player twice as fast. When collision or physics becomes important, many engines separate rendered-frame processing from fixed-rate physics processing so simulation does not depend entirely on display speed. (docs.godotengine.org)

Friction is feedback

Hand-written code has a nasty habit of making the missing idea obvious. A compiler, the program that translates source code and reports many mistakes, complains about types. A debugger, a tool that lets you pause execution and inspect values, shows that x is changing while the drawing code keeps reading y. Those moments are slow, but they are also information with edges.

Generated code can be correct and still skip that encounter. It may introduce an abstraction, a boundary that hides implementation details, before you know which details matter. Later, you inherit a neat MovementController with three layers of indirection and no memory of why the coordinate system was chosen. Manual work lets repetition earn the abstraction. After writing the same collision check three times, extracting a function feels like relief rather than ceremony.

A humane way to make things by hand

Working manually does not mean refusing every tool. It means deciding which part of the work you want to experience.

  • Choose one verb: move, sort, save, or collide. A project about moving a square can teach more than a project about making an entire game that never runs.
  • Keep the first version in one file. Split it when the code becomes painful to navigate, not because a template says every class needs a separate home.
  • Use documentation, the compiler, a debugger, and tests. Treat an API, the names and rules a library exposes, as a reference rather than a replacement for understanding.
  • Make small commits. Version control records changes over time, so each commit can preserve one meaningful behavior and the reasoning behind it.
  • Stop at a satisfying milestone. A square that moves, hits a wall, and resets is a finished experiment. That matters.

Where assistance fits

None of this creates a purity test. A coding assistant can help with repetitive migrations, spelling-heavy configuration, or comparing several ways to use an unfamiliar API. The useful boundary is more personal: do not delegate the first encounter with a concept you are trying to learn.

Write the first renderer, parser, or save file yourself. Once its shape is familiar, assistance becomes a shortcut you are choosing rather than a road you never walked. That distinction is easy to lose when a tool can produce a plausible answer before you have finished forming the problem.

The feature list will always be larger than the evening. Resist it. A finished program that moves a square, survives bad input, and can be rebuilt tomorrow has more value than a grand design trapped in generated scaffolding.

The point is not to pretend powerful tools do not exist, or to turn slower typing into a virtue. It is to keep some part of making where your attention remains the active ingredient. We build odd little tools, games, and experiments because the act changes us while the thing takes shape. When speed becomes the only measure, make something small, deliberate, and yours anyway.

ahsan

ahsan

Hello! I am Mr Ahsan, the writer of the Website. I am from Netherland. I like to write about technology and the news around it.

Comments (0)

No comments yet. Be the first to respond!

Leave a Comment

Your comment will be visible after review.