How much should we dig before we ask?
Clearing away assumptions and trying to come to a sensible default
I.
How much digging should we do before we ask?
This is a question I've been wondering recently as I get reacquainted with the vast constellation of services (and therefore massive amounts of code) that make Shopify work.
Big and successful internet tech companies that are here for the long haul have been built on decades of work by programmers by now. The software that powers their business is therefore complex and, as you've probably heard being said before, cannot fit into a single person's head anymore.
But I'm not trying to internalise the whole system here. I'm offloading my brain's RAM and keeping them for learning how a component of the system, say, Billing, works. Can I understand how the Billing component works by reading the code base and searching our internal docs? That's the first question. Should I? is the follow-up.
II.
Well, let's try and answer that with logic. To start, there were a few operative words I used earlier that I think are worth examining to see if they signify faulty assumptions:
- decades of work - as in, decades-old code
- it "cannot fit into a single person's brain" - also, "internalise the whole system"
So, "decades-old code." This isn't likely an accurate description of any code base that survives the test of time. A more accurate description would be that some parts of this code base are decades-old.
If the code base is still being maintained, then more likely than not, you'll be reading code that has been revised over time and therefore, with each iteration and refactor, some of the obtuse black-boxy stuff would have been deconstructed and better expressed.
Is it possible for an old code base to be decrepit and terrible to understand? Yes.
But is it also possible for an old code base to have been well-maintained, continually renewed, and easy to understand? Yes.
By this logic, the age of a code base is therefore not a factor in determining whether I will be able to understand it or not. Age was an irrelevant thing to bring up in discussing whether it's possible to understand how a complex component works just by reading its code.
What about "cannot fit into a single person's brain" and "internalise the whole system"?
Why is fitting the whole system in my brain important? Well, I'll need to understand at a high-level how Billing works internally and how other services interact with it so I know where is the best place to introduce a change in the code. I have to know all the places before I can choose the best one for housing the changes I want to make, right?
To that, I say yes. I need to know which places are most suitable for inserting what kind of logic, and what consequences they might have on services that depend on that place. Do I need the whole system in my brain to do that?
Is it possible to understand how a system works on a high level without knowing the exact computations that happen at the lower level that make the system work correctly? Yes, that's what abstractions are for.
Medium to large software systems will have multiple layers of abstractions at play, so I can probably follow markers and patterns in the code base (e.g. class names, directory names and hierarchy, etc.) to traverse within the abstraction layers that are relevant to me (I've heard the general recommendation from programmers that one should strive to know the layer you are working on and the two below it). Navigating within layers of abstractions takes practice, for sure, but it seems to promise not to involve uploading the whole code base into my brain.
III.
Okay, so one doesn't need to worry about the age of a code base because it doesn't say much about its quality, and one doesn't need to internalise the whole system to work in that system. Good. Glad we got that out of the way.
So, then, what it comes down to is more a matter of resource availability. Are there people who are free to join a call with me to answer my broad and meandering questions? Well, I won't know until I ask. But ah, there we have a catch-22. By asking if someone is free, I'm already taking up their time, but by not asking if someone is free, I won't know if someone is. Getting the current state of resource availability in a team comes at a cost.
A cost. I can work with a cost. I just need to weigh the cost against the benefit and I should know what's the best approach! So here goes:
From this, it's clear to me that only asking after exhausting all means of understanding the component myself isn't a good approach because the main benefit is just "saving people's time." What about my time? From a business perspective, my time costs money too. If I spend a full day looking into the code base to answer a question that actually could have been answered by someone from the team that owns that part of the code base in 10 minutes (after some context exchange and, if on a video call, some chit chat), then that's a stupid thing to do.
But always asking right away also doesn't seem like a good approach, because in the long run, I will be taking up a lot of people's time. Perhaps a question this time about this component might have taken me a full day to answer myself and is answered by someone in 10 minutes, but it's also quite likely for the reverse to happen, where if I looked for 10 minutes in the code base, I'd find the answer myself without taking up 10 minutes of another person's time (that's half the total time used from the business's perspective).
And so it seems I've arrived at the middle approach: ask after I've done some digging myself.
I swear I wasn't trying to be rhetorical with the other two approaches. But go on, believe what you want...
Anyway, now we have the task of trying to answer this difficult question: how much is some digging?
For me, I don't know yet. Based on my current context at Shopify where I'm still relatively new, I'm leaning more towards digging quite a lot before asking someone. A ballpark estimate might be something like 1-2 hours for a task with a small surface area, half a day for a medium surface area, and 2-3 days for a large surface area.
What's your answer?