<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://zahra.dev/</id>
  <title>Zahra Traboulsi</title>
  <updated>2025-09-01T00:00:00.000Z</updated>
  <link rel="self" href="https://zahra.dev/atom.xml"/>
  <link href="https://zahra.dev"/>
  <author>
    <name>Zahra Traboulsi</name>
    <uri>https://zahra.dev</uri>
  </author>
  <entry>
    <title>Be the engineer you'd love to work with</title>
    <link href="https://zahra.dev/blog/be-the-engineer-youd-love-to-work-with"/>
    <id>https://zahra.dev/blog/be-the-engineer-youd-love-to-work-with</id>
    <updated>2025-08-30T00:00:00.000Z</updated>
    <content type="html"><![CDATA[<p>I've worked with a lot of people over the years and in a lot of different teams. Some engineers are gruff, some are gregarious. Beyond a bare minimum level of civility, though, what I've found marks them out as somebody that people love to work with is how much their consideration for others shows up in their work.</p>
<p>When I started thinking about this, I fell for the trap of semantic drift and was under the incorrect impression that "conscientiousness" was the right word for this. It turned out, though, that the dictionary definition of that is actually "wishing to do one's work or duty well and thoroughly". I don't think that's a coincidence – when you're working with other people, as most of us do, enabling your team is an important part of your job.</p>
<p>So what does this considerateness look like in practice? Here are some examples:</p>
<ul>
<li>Being mindful of the work you take on.
<ul>
<li>Taking a share of the work nobody really enjoys doing.</li>
<li>Leaving tasks available that are par for the course for you, but a growth opportunity for someone else.</li>
<li>Taking on what you can handle, rather than committing yourself to too much.</li>
</ul>
</li>
<li>Unblocking others at natural pause points in your day.
<ul>
<li>Reviewing pull requests as soon as you can if you're not focussed on something else.</li>
<li>Answering questions that are blocking as soon as possible, or being upfront when you don't have the time or the knowledge to do so.</li>
</ul>
</li>
<li>Treating pull requests as part of the work product.
<ul>
<li>Splitting up your work-in-progress well enough that the resulting pull requests are manageable to review.</li>
<li>Reading through your own pull requests and ensuring they're sufficiently documented before asking for review from others.</li>
</ul>
</li>
<li>Filing the kinds of bug reports that you would like to recieve.
<ul>
<li>Providing as much detail and evidence as possible.</li>
<li>Fixing the bug yourself if it's trivially solvable.</li>
</ul>
</li>
<li>Making a decent effort to figure out something by yourself before resorting to asking for help.</li>
</ul>
<p>In doing these sorts of things, you exchange some of your own time, effort and scope for direct short-term impact for the sake of a smoother-running team. There's definitely a balance to be struck here – you should not be tanking progress on your own work given that that's what you're being relied upon to do. However, as part of the process of doing your own work, there are many small choices and efforts you can make every day to prevent that from causing unnecessary isssues for your colleagues while they try to do the same.</p>
<p>Giving yourself some slack time to deal with unplanned work instead of constantly keeping your work queue at 100% capacity is also an important strategy to learn to maintain your performance for the long term, and that's when you can practice some of these behaviours that are less directly-related to your own tasks. Combined, these efforts help to train your muscles in a plethora of areas: communication, debugging, prioritization, business thinking and self-reliance.</p>
<p>While practicing considerateness in your work does make you a better engineer to work with, I cannot promise you that this will definitely translate into immediate tangible benefits for your career progression, if that is something you care about. While companies often espouse prioritising the needs of the organisation and the team over your own personal to-do list as a cultural value, I've rarely seen it rewarded organisationally.</p>
<p>Hiring and promotion rubrics might nominally include this behaviour but greater weight is often given to experience single-handedly architecting some sort of important service at an impressive scale. After all, quantitative measures are a lot easier to grade than qualitative. Sadly, as a result, the lack of incentives can lead a lot of people not to bother making the effort who would have done if they were in a team with a different culture.</p>
<p>If the incentives aren't there, it can be <em>really hard</em> to show up and be deliberately considerate day-in, day-out. Honestly, sometimes it's hard even if they are; which one of us hasn't had an off-day? But showing a tendency to stick with it regardless of your immediate circumstances will round out your own skills and garner the respect of many of your peers throughout your career. It will enable you to build a great reputation and stronger relationships with other people detail-oriented enough to notice the difference in working with you, and help to cultivate the same perspective in other engineers who are looking to improve.</p>
<p>So, next time you're tempted to chuck a pull request over the wall, or are about to pick up a new task while your review pile languishes, take a minute and ask yourself: am I being the sort of engineer I'd love to work with?</p>
]]></content>
  </entry>
  <entry>
    <title>A taxonomy of technical interviews</title>
    <link href="https://zahra.dev/blog/technical-interview-taxonomy"/>
    <id>https://zahra.dev/blog/technical-interview-taxonomy</id>
    <updated>2024-07-29T00:00:00.000Z</updated>
    <content type="html"><![CDATA[<p>Software engineering interviews don’t exactly have the best reputation, often with good reason. But, sometimes they can actually be… <em>fun</em>? What is it that determines whether they’re going to leave you energised rather than withdrawing from the job market completely? To draw my own conclusions on this, I’ve trawled through my past experiences. As well as having interviewed candidates, I've undergone technical interviews as a candidate at roughly two dozen companies so far, some pretty well known.</p>
<p>In 2024, FAANG-style interviews continue to dominate discourse, which might give the impression that most interview processes are carbon copies of each other. However, it's been heartening to see more diverse technical interview formats emerge in recent years, even among widely renowned companies. Personally, I've found formats are usually the greatest determinant of how enjoyable an interview process is, so here’s an opinionated overview of the ones I’ve been through as a frontend-leaning full stack engineer.</p>
<p>If you're an experienced interviewer who’s seen it all, you might want to <a href="#closing-thoughts">jump to my closing thoughts</a>, otherwise: buckle in!</p>
<p>Technical interview formats largely split into three groups:</p>
<ol>
<li><a href="#coding-interviews">Coding</a></li>
<li><a href="#system-design">System design</a></li>
<li><a href="#miscellaneous">Miscellaneous</a></li>
</ol>
<h2>Coding interviews</h2>
<p>The bread and butter of the software engineering interview process. As many software engineers progress to senior levels, they spend less time overall writing code, and this is often reflected in interview processes at that level. However, even then, some form of hands-on coding continues to feature at least once or twice.</p>
<h3>Algorithmic interviews</h3>
<p>These questions largely focus on data structures, line-level optimisation and the like. They might be plainly presented with no particular context that would tie the problem to a real-life scenario with the interviewer asking you to transcribe on a whiteboard, or you might be asked to write a script that can recursively traverse directories and list or gather stats about them for example.</p>
<p>It's easy to bemoan the irrelevance of these, especially when they aren't disguised at least in part to look like something you might come across at work, but there is a reason why they are so enduring.</p>
<p><a href="https://giuseppegurgone.com/">Giuseppe Gurgone</a> shared his take on these types of interviews on <a href="https://giuseppegurgone.com/leetcode-interviews">his blog</a>:</p>
<p>“Their aim isn't to throw unusual and complex algorithms at candidates just for the sake of it; instead, it's to evaluate problem-solving skills using a focused and sufficiently generic problem.”</p>
<p>Similarly, both while undergoing interviewer training and as a candidate myself, I have often heard interviewers stress the focus is not on whether the candidate finds the answer or how long they take to do it, <em>it’s on their approach</em>. In my experience, this often gets lost because these interviews are easy to deliver and assess on some level, it’s not actually that easy to do these things well. The "objective" success or failure to solve the problem in time is very distracting, especially when these interviews run at scale and they’re being delivered by people with numerous other competing priorities, so this is a trap to be wary of.</p>
<h3>Practical interviews</h3>
<p>There's a huge amount of variety in this category but what all these interviews share is that they involve writing code and <em>building something</em> beyond an isolated class or function. These interviews also tend to be open book, meaning you have access to the internet, API references and Stack Overflow. This access might even extend to ChatGPT or Claude depending on the company.</p>
<p>There's a number of different dimensions these can cut across:</p>
<h4>Live vs take home</h4>
<p>Often both kinds will feature in a single interview process, with the take home happening prior to the live (or "in-person") interview.</p>
<p>In my experience, the amount of time provided as an estimate for a take-home task is almost always underestimated by the hiring team, sometimes wildly. In reality, the upper bound of time available for these is a function of how busy the candidate is outside of work, which puts some demographics at a significant disadvantage. While live interviews can give a lot of people performance anxiety, they can be preferable for people who are pressed for time or more senior candidates who simply aren’t particularly enthused by the idea of building yet another CRUD app.</p>
<p>There are tradeoffs and it's hard to come up with a single interview that is going to work for every candidate's strengths and circumstances. The combination of a take home task followed by an in-person follow-up is something I’m seeing more and more frequently, and it avoids a lot of pitfalls. That said, as an interviewing team, it’s important to ensure that the time set for the take home task is both reasonable (read: not 8-10 unpaid hours) and realistic by validating it in-house before giving it to candidates.</p>
<h4>Length of time</h4>
<p>On one end of the spectrum, shorter 30-60 minute interviews have focussed on adding a feature or two to an existing codebase, often that produced in the take-home task. On the other hand, I've spent a whole day onsite with a company, building out a web application. A number of companies, <a href="https://linear.app/blog/why-and-how-we-do-work-trials-at-linear">like Linear</a>, also conduct work trials, where a candidate works with the company for several days. There are tradeoffs with most durations: on the shorter end, a candidate doesn’t have much time to gain momentum, and with the days-long interview processes, these are pretty much logistically impossible for a lot of people.</p>
<h4>Starting from scratch vs bootstrapped</h4>
<p>Take-home tasks in particular often give you a bit of leeway in terms of your tech stack. On the other hand, in-person, or supervised interviews will often provide a starter project you are expected to work with.</p>
<p>One potential gotcha is that working in a codebase that features technologies you’re familiar with is very different to picking up a new set of technologies for the first time, <em>especially</em> if there is not a sufficient corpus of existing code to work with as there would be in a real production codebase. This is easier to deal with in a take-home project due to there being less pressure to get everything working within a certain amount of time, but doing this live on top of being watched by strangers can be incredibly stressful.</p>
<p>Interviewers might genuinely believe that when it comes down to it they will not penalise candidates who are not familiar with the tools at hand if they struggle to be as productive while gaining familiarity, but again, it's an easy trap to fall into and it’s frustrating to be on the receiving end of that. One way to level the playing field here, then, is to bootstrap starter projects with standard technology choices. While when they get into the role, engineers will have access to more specialised (or opinionated) tooling and libraries carefully selected to enhance productivity, having a good grasp of the underpinnings is still important and it reduces the chance that one candidate is going to be significantly hampered by a lack of experience with your tech choices compared to another.</p>
<h4>Pair programming vs solo</h4>
<p>When it comes to live interviews, there is a spectrum here. The most socially acceptable minimum when it comes to communication is for the interviewer to be responsive to questions and perhaps give you a well-timed hint if you are struggling or heading down the wrong path. (Sadly, that minimum is often not met: interviewers loudly having unrelated conversations or yawning doesn’t exactly make for a stellar candidate experience.)</p>
<p>On the other end, you could be repeatedly swapping pair programming roles (driver and passenger) with the interviewer, so your engineering is mostly done through discussion. While pair programming draws a range of opinions as a mandated practice, in an interview context, being able to get input from another person, especially in an unfamiliar codebase or tech stack will be more reflective of the reality of a lot of engineering teams and less pressurised.</p>
<p>In a more extreme version of a pair programming interview (this particular one being algorithmic), I was presented with a task and the role of driver rotated between me and two interviewers every five minutes. While I question the amount of valuable signal the interviewers could get out of this compared to me simply coding the solution myself, it was actually more fun than it sounds. I ended up pair-programming maybe twice in two years in that job.</p>
<h2>System design</h2>
<p>While there is an infamous format that probably comes to mind, as an industry we are now running several very different types of interviews and calling them all "systems design", at least for frontend/fullstack engineers. This can sometimes make it difficult to know what to expect.</p>
<h3>Backend system design</h3>
<p>This is the archetypal FAANG-style interview: the one that you probably think of when you hear "system design interview". You, as a lone engineer with no access to the internet or other resources, will be tasked with designing Facebook/Youtube/TikTok or the like.</p>
<p>While I do think having a decent foundation of systems design knowledge is a great bonus for engineers working on product, it's not <em>the absolute necessity</em> it's made out to be in many interview processes. <a href="https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/">Designing Data Intensive Applications</a> becomes a much more interesting read once you have at least a passing familiarity with the sorts of systems it talks about, and you are not necessarily guaranteed to be exposed to them given some number of years working on software.</p>
<h3>Frontend system design</h3>
<p>These interviews are similar in nature to backend interviews, in terms of taking a higher-level look at building a system. Instead of focussing on handling traffic at scale, they focus on holistic knowledge of the frontend, covering topics such as:</p>
<ul>
<li>Data fetching</li>
<li>Optimisation and performance</li>
<li>Security</li>
<li>Accessibility</li>
</ul>
<p>An example would be to design a dashboard page that can display any number (potentially hundreds) of charts, that is configured by the user.</p>
<p>These interviews are gaining traction but are still quite rare relative to backend system design interviews. If you do happen to have one coming up, I would suggest taking a look at <a href="https://medhat.dev/blog/cracking-frontend-system-design-interview/">Medhat Dawoud’s</a> guide.</p>
<h3>Data modelling</h3>
<p>This can take different forms: component modelling on the frontend, API design or database design. It's basically a smaller slice of a frontend or backend system interview thrown into sharper focus. These sorts of interviews tend to be strongly related to skills you'll often exercise as part of technical design processes when leading projects.</p>
<p><a href="https://andrewingram.net/">Andy Ingram</a> has written <a href="https://andrewingram.net/posts/deriving-a-data-model-from-a-design-with-graphql">an in-depth post</a> on conducting an interview like this focussing on designing a GraphQL API over on his blog.</p>
<h2>Miscellaneous</h2>
<p>Despite the unduly non-descript label, I think these kinds of interviews are underrated and underutilised. Professional software engineering is usually a team sport and you're often tasked with extending and maintaining existing code in collaboration with other people and interview formats that focus less on individual code authoring explore those skills more effectively.</p>
<h3>Reading code</h3>
<p>In one interview of this type, I was given snippets of code in various languages I wasn't necessarily familiar with and asked to explain what I thought they did and why. This format gives a sense of how somebody reacts to unfamiliar code and languages while eliminating the added pressure of having to work through the technical difficulties that often come along with getting started with a new technology on a given machine for the first time.</p>
<h3>Pull request reviews</h3>
<p>In this interview variant, you will be given a decently-sized chunk of code, perhaps about 250 lines or so, and will have a limited amount of time to provide feedback. These interviews test your ability not only to read and understand code, but also your communication skills, attention to detail and perhaps, your level of pedantry. In many teams, especially in larger companies, you will be doing a lot of code reviews and even if you work with a world class team, there’s still a lot of strategic advantages to doing it well. Sarah Vessels recently <a href="https://github.blog/developer-skills/github/how-to-review-code-effectively-a-github-staff-engineers-philosophy/#how-to-get-the-most-out-of-code-reviews">wrote in detail about this</a> on the GitHub engineering blog.</p>
<h3>Presentation</h3>
<p>My first graduate interview (which was for developer relations, rather than engineering) involved giving a presentation on a technical topic of my choosing: ThreeJS. Independently of that, I promptly realised developer relations is not for me and that was the last presentation I gave as part of an interview. However, I recently sat in as an interviewer on one of these being conducted with a staff-level candidate for frontend infrastructure engineering.</p>
<p>These interviews are fairly uncommon for software engineers, but they can definitely be useful for those operating above senior-level for certain roles. A big part of engineering at higher levels at many companies can involve influencing, advising and strategising, even as an individual contributor, so testing for this skill makes sense.</p>
<h3>Language and ecosystem discussion</h3>
<p>These types of interviews vary based on a candidate’s experience level but tend to dive into familiarity with concepts in the specific language(s) and tech stack used on the job.For more junior candidates, this be a “what is a closure in JavaScript?”, or a more general exploration of your approach to higher-order concepts like testing implementation and state management.</p>
<p>For earlier career engineers I think these questions work better embedded as part of a practical exercise where code is being written or read. Many people implicitly internalise concepts and features without learning their names or committing them to memory. However, if you’re hiring for an engineering enablement team or looking for someone to lay robust foundations in a particular area of your stack, getting a sense of their expertise and how they stay up to date with recent developments in the area can be valuable.</p>
<h2>Closing thoughts</h2>
<p>The interview processes in which I have performed the strongest and enjoyed the most tend to be the ones where I felt the skills they showcase match the sort of work I am used to doing, and more specifically, with constraints relatively similar to the norm. I was convinced that those sorts of interviews betrayed a lower technical bar, precisely <em>because they felt so natural</em>. The fallacy finally came into sharp focus when talking to an external recruiter about a process I underwent this year that was way more engaging than struggle-inducing: I was only the third person to have made it through to the offer stage (the company had multiple positions open) and it turned out every single interviewer was highly experienced and pedigreed.</p>
<p>On the other hand, the most frustrating interview processes I have been through have consistently been the ones that seemed completely detached from reality. If you are hiring someone to be your startup’s second frontend engineer and you are planning to task them with single-handedly scaling your backend to a billion users when you already have twenty backend engineers, you might want to reconsider.</p>
<p>Interviews are never going to be perfect, but we can do so much better! An integral part of that is designing processes on the basis of identifying skills that are useful and important in the context of the role, team and company. But for now, interviews are what they are, so I won’t completely discount the idea that I’ll be back to memorising how to implement a highly fault-tolerant globally-distributed rate-limiting service from scratch some time in the future just yet.</p>
<p><em>Shoutout to <a href="https://giuseppegurgone.com/">Giuseppe Gurgone</a> and <a href="https://alberto.weblog.lol/">Alberto Morabito</a> for reviewing the draft. I started it after a conversation on this topic with Alberto, who wrote his own too! You can read it <a href="https://alberto.weblog.lol/2024/07/types-of-software-engineer-interviews">here</a>.</em></p>
<h3>Interesting reads on this topic</h3>
<ul>
<li><a href="https://sockpuppet.org/blog/2015/03/06/the-hiring-post">"The Hiring Post"</a> - Thomas Ptacek (2015)</li>
<li><a href="https://danluu.com/algorithms-interviews/">“Algorithms interviews: theory vs practice”</a> - Dan Luu (2020)</li>
<li><a href="https://news.ncsu.edu/2020/07/tech-job-interviews-anxiety/">"Tech Sector Job Interviews Assess Anxiety, Not Software Skills"</a> - NC State University (2020)</li>
</ul>
]]></content>
  </entry>
  <entry>
    <title>Shipping incrementally</title>
    <link href="https://zahra.dev/blog/shipping-incrementally"/>
    <id>https://zahra.dev/blog/shipping-incrementally</id>
    <updated>2024-06-15T00:00:00.000Z</updated>
    <content type="html"><![CDATA[<p>In a post-ZIRP (zero interest-rate policy) tech industry where many engineers are being pressed to build and ship things faster, <em>faster</em>, <strong><em>fasteeeer</em></strong>, it's increasingly easy to end up careering towards a project's end with your sights set solely on the grand finale (or "the deadline"), when all your efforts will go out to your users. This is a trap: the allure of setting to work ASAP and making early progress on development covers up the eventualities of the frantic rush, extended deadlines and a risky release.</p>
<p>If you're used to this way of working, it requires conscious practice and effort to break out of. The alternative is to ship incrementally. Fortunately, building the ability to do this is like training your core muscles – it takes work, but once you do, day-to-day tasks mysteriously get easier and a lot of those nagging pains that sometimes come with age disappear.</p>
<h2>Breaking down larger projects</h2>
<p>Shipping a single small-scale feature is straightforward: those can often fit in a single commit or pull request, depending on the size. But what about when you take on larger challenges that take weeks, months or even years? That all starts with a plan.</p>
<p>Setting a project up for being delivered incrementally often occurs before a single line of code intended for production gets written, by analysing your project's goals and splitting them up into independently deliverable <strong>milestones</strong>. Making thoughtful decisions before your technical design is set in stone can transform a project that might otherwise have ended with three engineers merging a 100,000 line pull request on a Saturday into one that can be enabled with the simple flick of a switch given the right approach.</p>
<p>Note that this doesn't mean you can't write any code for prototyping or discovery; on the contrary, building something quick and scrappy to validate your assumptions and throw light onto your unknown unknowns can be a powerful tool, as long as you don't commit yourself, or get committed to shipping your first pass. You can read more about one way to go about this in <a href="https://jmduke.com/posts/microblog/zero-draft/" target="_blank">this post on zero drafts</a> by <a href="https://x.com/jmduke" target="_blank">Justin Duke</a>.</p>
<h3>Identifying milestones</h3>
<p>So what should a milestone look like? There is no One True Way to split up a project, how you do it will depend heavily on what you're trying to achieve. Milestones for net-new feature work will likely look very different to those for replacing or extending a product-wide primitive and even more so that those that involve a migration to change data models fundamental to your application. Over time as you work on more projects and gain more experience, you'll find patterns and reusable strategies start to emerge, such as:</p>
<ul>
<li>
<p>If you are building a user-facing project, a fairly obvious strategy is to slice your project vertically and delivering an end-to-end feature that can be used standalone, so you can start getting feedback from some users as soon as possible. This is especially useful if you're using a tech stack or tools you may be unfamiliar with.</p>
</li>
<li>
<p>If you are introducing a change to multiple product surfaces, like different websites or an application and a companion CLI, for example, focussing on building for one at a time might be more appropriate, but be careful not to get tunnel vision. Go into the details while considering the technical design to make sure you're not over-optimising it for one platform versus another.</p>
</li>
<li>
<p>If you are migrating to a new data model or making database schema changes, splitting that process up into several steps that allow the old and new shapes of the data to co-exist while the project is underway can remove the need for a hard cut-over while supporting changes further up the stack that rely on them.</p>
</li>
</ul>
<p>Here are some suggestions for what a useful milestone might look like in your team:</p>
<ul>
<li>It should be well demarcated with a clear definition of when it is complete. Dependencies between one milestone and a previous one are fine, but if the project needs to be unavoidably paused for a month or two between one milestone finishing and the next starting, it shouldn't leave your system in an unmanageable state.</li>
<li>You should feel comfortable giving a rough estimate of how much effort or time it will take to tackle it. If not, you probably need to do a time-boxed exploration into it first.</li>
<li>It should not be too fine-grained, these are not supposed to be JIRA ticket-level tasks. There should be some sort of meaningful functionality or situation change involved.</li>
</ul>
<p>A lot of companies have processes around writing design documentation and tech specs. If yours doesn't, consider writing out your milestones and sharing them with your team for feedback.</p>
<h3>Engineering techniques</h3>
<p>While planning milestones, it's also important to consider the different tools and techniques at your disposal that you can use during the execution phase, as this will unlock new ways of working.</p>
<p>Getting code into production as early as possible is one of the most reliable ways to de-risk deployment. <strong>Feature flags</strong> are a popular tool since they allow you to do this without disrupting your users before your changes are ready for prime-time. Some feature flagging solutions will allow you to target different environments, so your teammates can try things out on staging. You may even be able to target individual users, meaning you can ship to alpha testers from your user base and get feedback as you build and ship.</p>
<p>Decoupling deployment from release with feature flags also means you can ship smaller units of code at a time which makes for easier and more effective code reviews (that will probably be completed quicker too), as well as making it easier to rollback and debug changes that aren't behaving as expected once rolled out.</p>
<p>While feature flagging works well for frontend-heavy projects and new features, sometimes it won't be enough. What if you need to continue to support an existing feature or service while making major changes to critical pieces of code or dependencies that affect a large area of your application?</p>
<p>One potential solution is to use a <strong>facade</strong>. It can provide indirect access to your existing system and you can also use it to point to your new code using a feature flag. This is a pattern often found in the world of OOP (object-oriented programming) and might sound dated, but the concept is generalisable. Perhaps in your case a facade could be as simple as a file or function that routes the flow of code or data to the old or new solution, depending on a feature flag or other logic.</p>
<p>When it comes to significantly reshaping your data models, there's a fair chance that you're going to want to make some changes to your database at some stage. Here's a handy tip that <a href="https://x.com/JackEllis" target="_blank">Jack Ellis</a> got from <a href="https://carlsverre.com/" target="_blank">Carl Sverre</a> that can be used to support incremental development in these cases:</p>
<blockquote><p>Well, TIL.<br /><br />Me: "Everyone tells me to use feature flags in production but you can't exactly use them when you need to restructure a 30+ billion row table to make the feature work"<br /><br />Carl: "Use database views for now and deal with the migration once the feature is ready to launch"</p>— Jack Ellis (@JackEllis) <a href="https://twitter.com/JackEllis/status/1796666966322909292?ref_src=twsrc%5Etfw">May 31, 2024</a></blockquote> 
<p>If you're not familiar with database views, they are queries that act like virtual tables. You write an initial query to create the view based on your static, existing tables, and then your database stores that query and you can query the resulting view as if it's a real table. You can use this to provide indirection that acts like, yes, a facade! They also have other uses - you can more easily test out a potential change you'd like to make to your existing tables for a new feature without making a big commitment of migrating the tables the rest of your application.</p>
<h2>The tradeoff (or is it?)</h2>
<p>On paper (or Google doc), you will likely find that the overall estimate for final project delivery gets longer when taking the approach I've outlined here, as opposed to the one you might have given without taking this approach. While this headline of needing more time will be a hard sell in some organisations, especially ones that aren't engineering-driven, the reality is that you may end up completing the project faster. That may seem counter-intuitive given the overheads: the additional planning and extra engineering effort required to support this working. In practice, though, continually integrating the code into production increases momentum and getting feedback earlier pulls forward a lot of the fixes that otherwise would've been left until the end of the project or after it shipped, as well as avoiding a need for any project-level reverts.</p>
<p>Additionally, given the average level of ~in~accuracy when it comes to engineering estimates is <a href="https://xkcd.com/1658/" target="_blank">an industry wide meme</a>, placing so much weight on the absolutes doesn't really make sense. That doesn't mean we should abandon hope of ever doing a passable job of estimating software projects! In fact, splitting up the work actually makes giving an accurate initial estimate easier, and it is also easier to recalibrate if need be as the project progresses as <a href="https://jacobian.org/">Jacob Kaplan-Moss</a> notes in <a href="https://jacobian.org/2021/may/20/estimation/" target="_blank">this post</a> from his series on software estimation.</p>
<h2>Rounding up</h2>
<p>So, splitting work into shorter-term discretely shippable units brings:</p>
<ul>
<li>More accuracy and less uncertainty regarding timelines while the project progresses.</li>
<li>Tangible progress that can deliver value to your users sooner.</li>
<li>More manageable review, ship and debug cycles, which produce a flywheel effect on productivity.</li>
<li>Less of a scramble to fix bugs and address important feedback at the "end" of the project, holding up the release.</li>
</ul>
<p>If by now I haven't managed to convince you, maybe <a href="https://twitter.com/LisaKC_" target="_blank">Lisa Karlin Curtis</a> can. While writing this post, I discovered <a href="https://incident.io/blog/breaking-down-complex-projects" target="_blank">a treatise she penned on the incident.io engineering blog</a> with a more startup and product-focussed lens. If it can work for early-stage teams and public companies, it can probably work for you too.</p>
]]></content>
  </entry>
</feed>