Skip to main content

Be Aware of Context

Much inefficiency in the world arises from the lack of understanding of context. When large tasks requiring many people are broken down into chunks manageable by single persons, the big picture context can get lost from the detailed description of the task. The individual may then take the task handed to them, and make it their sole goal to complete the task as stated. But the statement of the task is never perfect, and there’s always room for interpretation. So what seems like a perfectly completed task, when brought back to the big picture, may in fact be a rather poorly fitting piece. Great parts, put together, may yield a mediocre result.

So if you really want to make a contribution towards the goals of your organization, and not just take your tasks to some artificially constructed image of completeness, you need to be aware of the context, of the big picture. Depending on who hands you your tasks, you may need to proactively seek out context, check your assumptions with somebody who is looking at the big picture, make sure your mental models of the situations match.

Writing code is just a means to an end, so you’d better understand the end, lest you risk doing pointless work[1].

My experience is mostly at startups, but I’m certain that it generalizes well to any organization. The rule of thumb I’ve found that works well is

Understand the context and root reasons for the problem that you’re asked to solve. Then solve it doing minimum work required without shooting your future self in the foot.

This boils down to taking shortcuts from the ideal solution. To do that well, you need two things: understand what the ideal solution is, and consider each possible shortcut’s future-foot-shooting-score.

Understanding the ideal solution is a purely engineering exercise. If you had unlimited resources, what would be the state-of-the-art, most elegant, cleanest solution? It’s important to be able to design these, yet you should almost never actually implement them — if you do, you are likely wasting resources. But knowing what the ideal is allows you to correctly evaluate the future-foot-shooting score of all the shortcuts that you can possibly take.

The future-foot-shooting score is roughly a product of how much time/effort you save from taking the given shortcut, multiplied by the severity of the demerits associated with it. Let’s look at some examples.

Example 1

Say you have users in your system, and you need to add the ability to store the user’s address. Say you also have a UserProfile entity in place.

Planning for potential future requirements, the ideal solution would involve something like having Address entities, with userId and isCurrent fields on them. This allows for storing multiple addresses, or history of address changes, and is quite flexible and thus adaptable to future requirements.

Implementing this is not cheap, though — you need to write a fair bit of CRUD code, new APIs to fetch addresses, or add them to existing payloads and plumb the changes through.

A shortcut would be to just add a field or two to the UserProfile entity. The entire CRUD pipeline is already established and working, all you need to do is add columns to the DB tables and update the type definitions. Savings are clearly large. What about the future-foot-shooting score?

Is the address only used in a small subset of the use sites where UserProfile is used? Then you’re carrying extra data around for little reason. Does it matter? Probably not, since the amount of data is small.

Do you have private and public versions of the profile, so need filtering logic to filter out private data? Is it already in place, so it’s just a matter of adding a field name, or do you need to build the private/public split from scratch? Is it good enough in your case to just hide the data from UI but still transfer it over the wire, or do you need to make sure it never leaves the backend in the public case?

Do you need address change history? In the current setup, unless you have edit tracking on the UserProfile table (with a trigger and an archive table, perhaps), edits will cause irrecoverable data loss. Is that okay in your use case? If not, would adding an addressHistory field along and just storing an array of previous versions suffice? Could be just a DB level thing, so that you don’t drag useless data to the front end, but the data is still recoverable if necessary in the future.

Are you planning to do computation based on address? At the DB query level, or in code?

If you go with the "field on UserProfile" for now, but eventually decide to go the full-blown Address entity way, how easy is the conversion, multiplied by how likely it is? Seems easy, so likelihood isn’t even a concern in this case. Sometimes a conversion is fairly involved, but the likelihood is low enough that it’s well worth the time savings.

Next: Do Code Reviews ⇒

[1] There’s plenty that you personally can gain from what, for your organization, will be pointless work. I’m working under the assumption that you buy into the company’s vision, want to contribute to that, and also have team members or managers that want you to grow, and are aware of how to optimize for employee productivity, which often involves a balance between output towards the company’s goals and personal development.

Comments