More from Ognjen Regoje • ognjen.io
Many (most?) engineers go from university to a sizable company significantly distancing them from the actual value their code creates. They labour under the delusion that they’re paid to write code. In fact, they’re paid to make money, and writing code is probably the most expensive way that they can do that. They will often say things like “We should scrap this entirely and re-write it, it will only take 8 months” – often about code that generates 8 figures in revenue and employs several dozen people. Code that pays for their smartwatches. But, of course: Engineers are hired to create business value, not to program things – Don’t Call Yourself A Programmer, And Other Career Advice In my estimate it takes about a decade of experience before engineers start to really internalize this. This can be significantly sped up by having a shorter feedback loop between the code written and the value realized by the engineer. There are two ways to do this: Freelancing Founding Freelancing By freelancing, and doing it well, the reward, is very directly tied to the code written. The best way to do freelance, for the sake of learning, would be to work on fixed cost contracts – which isn’t great freelancing advice, but is excellent for the longterm career. Delivering to someone elses specs makes engineers focused on delivery only the necessary and sufficient code to make that happen. All the correct decisions result in an improvement of the engineers earnings per hour and all mistakes in a reduction. That feedback loop very quickly teaches: The importance of quality and automated testing Architecture and keeping options open Communication and requirements gathering, asking the right questions All of these are factors that come into play once an engineer is breaking the barrier from Senior to management or Staff. Founding a company Founding a company, where the code that you produced secures your salary, teaches those lessons, plus a few others: Understanding the importance tradeoffs that companies make betwen velocity and tech debt It is also an opportunity to learn how to make those tradeoffs well, something engineers aren’t always great at Experience creating the most value possible with the least code Very few enginers pre-emtively suggest ways to test product hyptheses using cheaper appoaches Pragmatism and bias towards shipping and avoidingg gold-plating functionality that is immature Plus you very quickly start to understand why “We should re-write it” is almost never the right business decision. All software engineers should freelance or found a business was originally published by Ognjen Regoje at Ognjen Regoje • ognjen.io on April 18, 2025.
In The Innovator’s Dilemma Christensen talks about how when acquiring a company you might either be acquiring its product or its processes. Depending on which it is, you need to handle the integration differently. I’ve realized that hiring a new manager follows a similar pattern: either they’re expected to integrate into the organization, or be independent and create some change. That expectation depends on whether the team, and possibly the wider organization, function well. If the team is high-performing, why would adding or overhauling processes make sense over fine-tuning existing ones? But new managers often join and immediately start suggesting ways to fix things. In many of these cases, they aren’t suggesting some best practices but are simply trying to have the new company function in a similar way to their previous one. But they never have enough context to justify these changes. What they should do is take a step back and understand why they were hired and what already works. Are they there to run the team as it is and perhaps look for marginal gains in efficiency and effectiveness? Or are they there because things are fundamentally broken and they need to overhaul the organization? In 9 out of 10 cases, it’s the first one. They’re there to ensure the continuity of the team. Therefore in 9 out of 10 cases the objective should be to integrate into the processes as quickly as possible and help iterate. Why are you here, manager? was originally published by Ognjen Regoje at Ognjen Regoje • ognjen.io on April 18, 2025.
I love Ben Brode’s Design Lessons from Improv talk. It presents techniques that we could all use more frequently. I particularly took the “Yes, and…“ to heart. It is an excellent technique, or attitude really, that keeps the conversation going. Conversations often start slow but get progressively more interesting the deeper you go. And “Yes, and…” makes it possible to get there. One of my favorite uses of “Yes, and…” is when someone sends you an article that you’ve already read or a video you’ve already watched. The typical response might be 👍 seen it (A whole site is named after the fact that you’ve already read it) If the other person is interested in having a conversation, you’ve just stopped it in its tracks expecting them to put in all the effort to keep it going. A “Yes, and…” response such as “Yes, I’ve read it, and something you found interesting” opens up the conversation. Even if the other person just wanted to share something they thought you might find interesting, you’ve: a) created an opportunity to exchange opinions and b) put in slightly above the bare minimum of effort to acknowledge that what they shared with you was indeed interesting At work At work, specifically, it is useful in all manner of discussions. Conversations about product, or code, or architecture, or team activities, or customer service all get better when you don’t dismiss but build on top of each other. The value of "Yes, and..." was originally published by Ognjen Regoje at Ognjen Regoje • ognjen.io on April 17, 2025.
One of the best pieces of advice I’ve ever gotten is to take a minute, or a week, after you’ve had a difficult conversation. By and large, people are not unreasonable. They’re not out to get you. They’re not trying to make your life miserable. They’re probably trying to do what they think is right. But tough conversations happen and when they do it’s important to take time to process the information and formulate a more nuanced opinion. To take a work example: picture a conversation where you’re being some particularly heavy feedback You’re confused, you’re sad, you’re angry. You disagree. You want to protest, defend yourself, argue, explain. Doing so, however, would accomplish nothing in the immediate, and probably set you back in the long-term. The other person is probably also upset and stressed about having to have the conversation. Getting defensive would get make them to do the same and the conversation would quickly devolve into one run by emotions. Instead, listen and gather as much information as possible. If possible, try to write as much as you can down. Don’t say much except ask questions and then politely ask for a follow-up meeting in a few days. That will give you the time to process all the information and figure out if they were right, if it might not have been a big deal at all, if there is nuance in the situation or if you were indeed right. Or, as is most likely, some combination of all of the above. You’ll be able to formulate a cohesive model of the situation in your head, which will help you make a better decision or counter-argument if needed. It’ll also give you, and the others, time to cool down and prevent anyone from reacting too emotionally. Come to the follow-up meeting with humility and a willingness to compromise. Recap the previous meeting and make sure that everyone is on the same page. Then explain your understanding of the situation and present your opinion. The end result should be a much more amicable outcome without the need for a third meeting. And while my example is in the context of work, the same is true for personal conversations. So, take a minute. Or a week. It’ll help you make better decisions. During a difficult conversation, remember to take a minute was originally published by Ognjen Regoje at Ognjen Regoje • ognjen.io on April 17, 2025.
There is nothing as inevitable as a re-org when a new VP joins. When a new executive joins they’re often overwhelmed by the amount of context they need to absorb to start being effective. The more seasoned ones aren’t pertrubed by this: they understand that gathering this context is their full-time job for the next several weeks or months. There’s even a book about this period. The less savvy ones, on the other hand, often reach for one of the following coping strategies, depending on the type of role they occupy. This organization makes no sense, we must re-organize it immediately Spoken by a newly joined VP who needs to assess the organization and understand why it is set up the way it is. It results in several workshops about boundaries, Conway’s law and team topologies result in a slightly different, but not materially significant organization. And a VP with a much better understanding of their people, the culture, the product and the challenges. We must document/map it Spoken by a product manager getting to grips with the features they’ll be working on before having read the abundant sales, technical and product reference materials. This usually results in several workshops where there is a lot of “discovery” and “mapping”. In reality, the product manager is getting an in-person crash course. It rarely results in any new discoveries or documentation or maps being produced but always results in a much more confident product manager. We must have a process for that Spoken by a new engineering manager who’s not yet familiar with the existing processes and ways of working. This usually results in the engineering manager starting to write a Confluence page on how the process should work, until one of the team members sends them an existing, but finished, Confluence page on exactly that, but with slight differences. The new page gets a link to the existing ones and is promptly forgotten. Does this process really work for anyone? A sub-category of the above then the process in place is different from their previous employer. This code is so bad, we must re-write it entirely Spoken by a senior but not yet quite staff engineer who’s just getting to grips with a new codebase – often about code that generates 7 or 8 digits in revenue. It results in the engineer spending several hours on an alternative architecture and running it by their team several times. Eventually, they understand that what they’re suggesting is quite similar to what is actually in place, that there is some refactoring and improvements to be done, but it’s nowhere near as tragic as they imagined it to be. Why does this happen? A week or two after joining, depending on how generous the company is, the engineer gets a ticket to work on, the PM is asked about the backlog priority and the EM why their bug injection rate is so high and what they’re doing about it. And they naturally feel lost. The problem is that most companies don’t set an expected timeline for having a person become effective in their position. How to do better? The amount of context required to be effective increases with seniority. But everyone needs a couple of weeks outside of the default onboarding programme to read through their team’s wiki space, to look through the backlog, to pair with their colleagues, to get an understanding of the work the team is doing, to be present at the retrospectives to listen and not have to lead and facilitate. Only after they get the lay of the land can they start contributing in a meaningful way. The managerial fear of the unknown was originally published by Ognjen Regoje at Ognjen Regoje • ognjen.io on April 17, 2025.
More in programming
Having spent four decades as a programmer in various industries and situations, I know that modern software development processes are far more stressful than when I started. It's not simply that developing software today is more complex than it was back in 1981. In that early decade, none
In previous articles, we saw how to use “real” UART, and looked into the trick used by Arduino to automatically reset boards when uploading firmware. Today, we’ll look into how Espressif does something similar, using even more tricks. “Real” UART on the Saola As usual, let’s first simply connect the UART adapter. Again, we connect … Continue reading Espressif’s Automatic Reset → The post Espressif’s Automatic Reset appeared first on Quentin Santos.
I started writing this early last week but Real Life Stuff happened and now you're getting the first-draft late this week. Warning, unedited thoughts ahead! New Logic for Programmers release! v0.9 is out! This is a big release, with a new cover design, several rewritten chapters, online code samples and much more. See the full release notes at the changelog page, and get the book here! Write the cleverest code you possibly can There are millions of articles online about how programmers should not write "clever" code, and instead write simple, maintainable code that everybody understands. Sometimes the example of "clever" code looks like this (src): # Python p=n=1 exec("p*=n*n;n+=1;"*~-int(input())) print(p%n) This is code-golfing, the sport of writing the most concise code possible. Obviously you shouldn't run this in production for the same reason you shouldn't eat dinner off a Rembrandt. Other times the example looks like this: def is_prime(x): if x == 1: return True return all([x%n != 0 for n in range(2, x)] This is "clever" because it uses a single list comprehension, as opposed to a "simple" for loop. Yes, "list comprehensions are too clever" is something I've read in one of these articles. I've also talked to people who think that datatypes besides lists and hashmaps are too clever to use, that most optimizations are too clever to bother with, and even that functions and classes are too clever and code should be a linear script.1. Clever code is anything using features or domain concepts we don't understand. Something that seems unbearably clever to me might be utterly mundane for you, and vice versa. How do we make something utterly mundane? By using it and working at the boundaries of our skills. Almost everything I'm "good at" comes from banging my head against it more than is healthy. That suggests a really good reason to write clever code: it's an excellent form of purposeful practice. Writing clever code forces us to code outside of our comfort zone, developing our skills as software engineers. Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you [will get excellent debugging practice at exactly the right level required to push your skills as a software engineer] — Brian Kernighan, probably There are other benefits, too, but first let's kill the elephant in the room:2 Don't commit clever code I am proposing writing clever code as a means of practice. Being at work is a job with coworkers who will not appreciate if your code is too clever. Similarly, don't use too many innovative technologies. Don't put anything in production you are uncomfortable with. We can still responsibly write clever code at work, though: Solve a problem in both a simple and a clever way, and then only commit the simple way. This works well for small scale problems where trying the "clever way" only takes a few minutes. Write our personal tools cleverly. I'm a big believer of the idea that most programmers would benefit from writing more scripts and support code customized to their particular work environment. This is a great place to practice new techniques, languages, etc. If clever code is absolutely the best way to solve a problem, then commit it with extensive documentation explaining how it works and why it's preferable to simpler solutions. Bonus: this potentially helps the whole team upskill. Writing clever code... ...teaches simple solutions Usually, code that's called too clever composes several powerful features together — the "not a single list comprehension or function" people are the exception. Josh Comeau's "don't write clever code" article gives this example of "too clever": const extractDataFromResponse = (response) => { const [Component, props] = response; const resultsEntries = Object.entries({ Component, props }); const assignIfValueTruthy = (o, [k, v]) => (v ? { ...o, [k]: v } : o ); return resultsEntries.reduce(assignIfValueTruthy, {}); } What makes this "clever"? I count eight language features composed together: entries, argument unpacking, implicit objects, splats, ternaries, higher-order functions, and reductions. Would code that used only one or two of these features still be "clever"? I don't think so. These features exist for a reason, and oftentimes they make code simpler than not using them. We can, of course, learn these features one at a time. Writing the clever version (but not committing it) gives us practice with all eight at once and also with how they compose together. That knowledge comes in handy when we want to apply a single one of the ideas. I've recently had to do a bit of pandas for a project. Whenever I have to do a new analysis, I try to write it as a single chain of transformations, and then as a more balanced set of updates. ...helps us master concepts Even if the composite parts of a "clever" solution aren't by themselves useful, it still makes us better at the overall language, and that's inherently valuable. A few years ago I wrote Crimes with Python's Pattern Matching. It involves writing horrible code like this: from abc import ABC class NotIterable(ABC): @classmethod def __subclasshook__(cls, C): return not hasattr(C, "__iter__") def f(x): match x: case NotIterable(): print(f"{x} is not iterable") case _: print(f"{x} is iterable") if __name__ == "__main__": f(10) f("string") f([1, 2, 3]) This composes Python match statements, which are broadly useful, and abstract base classes, which are incredibly niche. But even if I never use ABCs in real production code, it helped me understand Python's match semantics and Method Resolution Order better. ...prepares us for necessity Sometimes the clever way is the only way. Maybe we need something faster than the simplest solution. Maybe we are working with constrained tools or frameworks that demand cleverness. Peter Norvig argued that design patterns compensate for missing language features. I'd argue that cleverness is another means of compensating: if our tools don't have an easy way to do something, we need to find a clever way. You see this a lot in formal methods like TLA+. Need to check a hyperproperty? Cast your state space to a directed graph. Need to compose ten specifications together? Combine refinements with state machines. Most difficult problems have a "clever" solution. The real problem is that clever solutions have a skill floor. If normal use of the tool is at difficult 3 out of 10, then basic clever solutions are at 5 out of 10, and it's hard to jump those two steps in the moment you need the cleverness. But if you've practiced with writing overly clever code, you're used to working at a 7 out of 10 level in short bursts, and then you can "drop down" to 5/10. I don't know if that makes too much sense, but I see it happen a lot in practice. ...builds comradery On a few occasions, after getting a pull request merged, I pulled the reviewer over and said "check out this horrible way of doing the same thing". I find that as long as people know they're not going to be subjected to a clever solution in production, they enjoy seeing it! Next week's newsletter will probably also be late, after that we should be back to a regular schedule for the rest of the summer. Mostly grad students outside of CS who have to write scripts to do research. And in more than one data scientist. I think it's correlated with using Jupyter. ↩ If I don't put this at the beginning, I'll get a bajillion responses like "your team will hate you" ↩
Whether we like it or not, email is widely used to identify a person. Code sent to email is used as authentication and sometimes as authorisation for certain actions. I’m not comfortable with Google having such power over me, especially given the fact that they practically don’t have any support you can appeal to. If your Google account is blocked, that’s it. Maybe you know someone from Google and they can help you, but for most of us mortals that’s not an option.