Show passage from The Mythical Man-Month
Adding manpower to a late software project makes it later.
Writing about software that influenced my thinking, and that I try to come back to regularly.
Small excerpts from the pieces can be toggled via the bullet points.
Adding manpower to a late software project makes it later.
Complexity is anything related to the structure of a system that makes it hard to understand and modify the system.
Hope is not a strategy.
Software engineering is programming integrated over time.
The ability to work and deliver in small batches is especially important, because it allows you to gather user feedback quickly.
A complex system may be an accurate reflection of our immature understanding of a complex problem.
Programming in this sense primarily must be the programmers’ building up knowledge of a certain kind, knowledge taken to be basically the programmers’ immediate possession.
The complexity of software is an essential property, not an accidental one.
Complexity is the root cause of the vast majority of problems with software today.
The human brain isn’t particularly good at basic logic and now there’s a whole career in doing nothing but really, really complex logic.
Values in your system afford shifting boundaries between anything.
This functional core is surrounded by a shell of imperative code... all based on values produced by the functional core.
Producing beautiful software is not a goal. Solving complex technical problems is not a goal. Writing bug-free code is not a goal. Using sexy programming languages is not a goal. Add revenue. Reduce costs. Those are your only goals.
Don’t call yourself a programmer: “Programmer” sounds like “anomalously high-cost peon who types some mumbo-jumbo into some other mumbo-jumbo.” If you call yourself a programmer, someone is already working on a way to get you fired.
Instead, describe yourself by what you have accomplished for previously employers vis-a-vis increasing revenues or reducing costs. If you have not had the opportunity to do this yet, describe things which suggest you have the ability to increase revenue or reduce costs, or ideas to do so.
Speed and reliability are often intuited hand-in-hand. Speed can be a good proxy for general engineering quality. If an application slows down on simple tasks, then it can mean the engineers aren’t obsessive detail sticklers. Not always, but it can mean disastrous other issues lurk. I want all my craftspeople to stickle.
It feels — intuitively — that software (beyond core functionality) should aim for speed. Speed as a proxy for efficiency. If a piece of software is becoming taurine-esque, unwieldy, then perhaps it shouldn’t be a single piece of software. Ultimately, to be fast is to be light. And to be light is to lessen the burden on someone or some task. This is the ultimate goal: For our pocket supercomputers to lesson burdens, not increase them. For our mega-powered laptops to enable a kind of fluency — not battle, or struggle — of creation.
The key is deliberative practice: not just doing it again and again, but challenging yourself with a task that is just beyond your current ability.
This messaging app I built for, and with, my family, it won’t change unless we want it to change. There will be no sudden redesign, no flood of ads, no pivot to chase a userbase inscrutable to us. It might go away at some point, but that will be our decision, too. What is this feeling? Independence? Security? Sovereignty?
Is it simply… the feeling of being home?
It took me another fifteen years to realize that the principle of Fire and Motion is how you get things done in life. You have to move forward a little bit, every day. It doesn’t matter if your code is lame and buggy and nobody wants it. If you are moving forward, writing code and fixing bugs constantly, time is on your side.
Fire and Motion, for small companies like mine, means two things. You have to have time on your side, and you have to move forward every day. Sooner or later you will win. All I managed to do yesterday is improve the color scheme in FogBUGZ just a little bit. That’s OK. It’s getting better all the time. Every day our software is better and better and we have more and more customers and that’s all that matters. Until we’re a company the size of Oracle, we don’t have to think about grand strategies. We just have to come in every morning and somehow, launch the editor.
Mindful choice of technology gives engineering minds real freedom: the freedom to contemplate bigger questions. Technology for its own sake is snake oil.
Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.
With a sufficient number of users of an API,
it does not matter what you promise in the contract:
all observable behaviors of your system
will be depended on by somebody.
Most experienced engineers own their work end-to-end: from getting the specification, through implementing it, all the way to rolling it out and validating that it works correctly. Product-minded engineers often go a step beyond this.
They consider their work done only after getting results on user behavior and business metrics. After rollout, they still actively engage with product managers, data scientists, and customer support channels, to learn how the feature is being used in the real world. It can take weeks to get enough reliable data to draw conclusions. Even though they might be working on a new project, they make checking on the results one of their top priorities. It's not a time-consuming activity, but it needs that additional persistence from someone wanting to know: how is my work really doing?
Edit-compile-run is a software engineer’s work loop in which they (1) edit code, (2) compile the code (or start the interpreter), and (3) run the program or test suite. It’s the all-important standard workflow an engineer will run hundreds of times a day, and the speed at which it’s possible is one of the single most important factors for productivity in a codebase. Whether new code is being written or existing code modified, being able to run it and get feedback quickly is of paramount importance.
The ideal edit-compile-run loop for small programs is < 1s, or measured in a couple seconds. For larger programs, 10s of seconds is more likely and still acceptable, but go any higher than that and you’re entering the danger zone.
The fact is, distributed systems exist in a continual state of partial degradation. Failure is the only constant. Failure is happening on your systems right now in a hundred ways you aren’t aware of and may never learn about. Obsessing over individual errors will, at best, drive you to the bottom of the nearest whiskey bottle and keep you up all night. Peace of mind (and a good night’s sleep) can only be regained by embracing error budgets via service-level objectives (SLOs) and service-level indicators (SLIs), thinking critically about how much failure users can tolerate, and hooking up feedback loops to empower software engineers to own their systems from end to end.
so grug say again and say often: complexity very, very bad
grug understand all programmer platonists at some level wish music of spheres perfection in code. but danger is here, world is ugly and gronky many times and so also must code be
When should you over-ride YAGNI? When the cost of adding something later is so dramatically expensive compared with the cost of adding it early on that it’s worth taking the risk. On when you know from experience that an initial investment will pay off many times over.
Any of the ideas I’ve shown here could take an engineering team weeks (if not months) to add to an existing project—but with the right tooling they can represent just an hour (or less) work at the start of a project. And they’ll pay themselves off many, many times over in the future.
You don't need to worry about scalability on your Rails-over-Mysql application because nobody is going to use it. Really. Believe me. You're going to get, at most, 1,000 people on your app, and maybe 1% of them will be 7-day active. Scalability is not your problem, getting people to give a shit is.
Unless you know what you need to scale to, you can't even begin to talk about scalability. How many users do you want your system to handle? A thousand? Hundred thousand? Ten million? Here's a hint: the system you design to handle a quarter million users is going to be different from the system you design to handle ten million users.
Stupid, clear, easy to read code is what we’re looking for… Mostly, unclever code, that’s clear to read, that’s clear to understand is what we’re aiming at.
Programming is enormously expensive.. So even if we get a little advantage in programming, that’s worth a lot. If you were able to convince someone that this technology will save you 10% of your programming costs, that quickly translates into millions of dollars. If I can show you that a particular programming technology reduced risk of schedule variations, that quickly translates into millions of dollars.
Whether it's building a new project from scratch, implementing a big feature, or beginning a large refactor, it can be difficult to stay motivated and complete large technical projects. A method that works really well for me is to continuously see real results and to order my work based on that.
I've learned that when I break down my large tasks in chunks that result in seeing tangible forward progress, I tend to finish my work and retain my excitement throughout the project. People are all motivated and driven in different ways, so this may not work for you, but as a broad generalization I've not found an engineer who doesn't get excited by a good demo. And the goal is to always give yourself a good demo.
A rewrite made QuickDraw simpler, nearly six times faster, and 2,000 lines smaller.
The XY problem is a communication issue where an individual asks for help with their attempted solution (Y) rather than asking for help with their actual problem (X). This can lead to inefficient solutions and unnecessary complexity.