Software Canon
-
Understanding the XY Problem | /u/kmisterk
-
-2000 Lines Of Code | Andy Hertzfeld
-
My AI Skeptic Friends Are All Nuts | Thomas Ptacek
Professional software developers are in the business of solving practical problems for people with code. We are not, in our day jobs, artisans. Steve Jobs was wrong: we do not need to carve the unseen feet in the sculpture. Nobody cares if the logic board traces are pleasingly routed. If anything we build endures, it won’t be because the codebase was beautiful.
Besides, that’s not really what happens. If you’re taking time carefully golfing functions down into graceful, fluent, minimal functional expressions, alarm bells should ring. You’re yak-shaving. The real work has depleted your focus. You’re not building: you’re self-soothing.
Which, wait for it, is something LLMs are good for. They devour schlep, and clear a path to the important stuff, where your judgement and values really matter.
-
The Reality of Working in Tech: We're Not Hired to Write Code
I later realized that in the fast-paced tech industry, companies prioritize delivering products and features above all else. Managers are responsible for delivering results to higher-ups. As such, it is crucial for developers to work on building and maintaining the company's products and features, regardless of their coding specializations.
...But the reality is we are not hired to write code. That's only incidental.
-
Choosing Languages | Steve Klabnik
-
"We ran out of columns" - The best, worst codebase | Jimmy Miller
-
The Absolute Minimum Every Software Developer Must Know About Unicode in 2023 (Still No Excuses!) | Nikita Tonsky
-
Questionable Advice: The Trap of The Premature Senior – charity.wtf
What you are experiencing now is the alluring comfort of premature seniority. You’re the smartest kid in the room, you know every corner of the system inside and out, you win every argument and anticipate every objection and you are part of every decision and you feel so deeply, pleasingly needed by the people around you.
There is a world of distance between being expert in this system and being an actual expert in your chosen craft. The second is seniority; the first is merely .. familiarity
-
Plans are nothing, planning is everything | Thorsten Ball
What’s important is that you have a plan so that when someone asks you whether you know what you do, you do.
-
My Approach to Building Large Technical Projects | Mitchell Hashimoto
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.
-
Full product engineer | Charity Majors
Or, if you prefer, "I am a full product engineer."
And this ^^^ is what we should all be trending towards. The days when you could put up your hands and protest, "I'm just a backend engineer. Get someone else to write those five lines of javascript" -- are ending.
-
Building for the 99% Developers | Jean Yang
It matters to talk about the 99% Developers because these are the developers building the software that powers our lives — insurance, health care, retail, and banking, just to name a few. It’s not only small companies that can’t easily adopt the processes of modern, tech-first companies; it’s most companies that were not built around technology and that have decades of legacy software practices firmly in place. Many of these companies move around quite a bit of money. Many of these companies handle quite a bit of our personal data. If technology innovations are not benefiting these software teams, we’re losing out on a lot of meaningful improvements to everyone’s quality of life.
-
Ada, Past Present and Future | Robert Dewar
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.
-
GPT4 should be part of your toolkit | Hillel Wayne
I’ve never seen a tool more flexible than GPT4. Just the sheer variety of things you can do with it makes it worth using. No matter who you are, if your job sits you at a computer all day then there’s gonna be something GPT4 can do for you.
At the same time, you have to know its limits. The AI is often wrong and you need to verify everything you get back. So focus on the problems that are hard to do, but easy to check.
-
Two types of software engineers - by Thorsten Ball
One assumes it's easy because it's a non-technical problem, the other assumes that's why it's hard.
Painting in really broad strokes, though, I'd say that type 1 doesn't take people into account and type 2 knows that at the heart of all of their engineering work (and problems) are people.
...
Because, see, when it gets messy, that's where it gets real; that’s where the actual work begins, when you go from drawing board to actually shipping something of value and with impact to someone.
-
How software companies die | Orson Scott Card
Here's the secret that every successful software company is based on: You can domesticate programmers the way beekeepers tame bees. You can't exactly communicate with them, but you can get them to swarm in one place and when they're not looking, you can carry off the honey.
---
The shock is greater for the coder, though. He suddenly finds that alien creatures control his life. Meetings, Schedules, Reports. And now someone demands that he PLAN all his programming and then stick to the plan, never improving, never tweaking, and never, never touching some other team's code. The lousy young programmer who once worshiped him is now his tyrannical boss, a position he got because he played golf with some sphincter in a suit.
The hive has been ruined. The best coders leave. And the marketers, comfortable now because they're surrounded by power neckties and they have things under control, are baffled that each new iteration of their software loses market share as the code bloats and the bugs proliferate.
-
Is High Quality Software Worth the Cost?
Neglecting internal quality leads to rapid build up of cruft. This cruft slows down feature development. Even a great team produces cruft, but by keeping internal quality high, is able to keep it under control. High internal quality keeps cruft to a minimum, allowing a team to add features with less effort, time, and cost.
-
You Can Probably Stand To Charge More | @patio11
Are you worried that your customers are going to implement your product in a week themselves? That is, perhaps, a realistic worry if your customers are primarily developers. If you have a 200 line shell script and want to sell it to a bunch of Linux mavens for $15, well, God be with you. Sometimes developers spend time on things which they really should just buy off the shelves, too — I’m as guilty as that as anybody. But the rest of the world doesn’t want to program your program. If they had the skills or desire to reinvent your wheel, they’d be programmers, but they’re not. They’re teachers or real-estate brokers or heart surgeons. Everything that happens inside of the computer is black magic to them and you are the shaman they rely on for magical amulets to keep the evil spirits at bay. So long as your amulets work, you can pretty much charge what you like for them.
-
I'm Going To Scale My Foot Up Your Ass | Ted Dziuba
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.
-
Use the Wrong Tool for the Job • Buttondown
This is going in a lot of different places. Let’s bring it back together:
Impedance is when you have to take on complexity to solve a problem, due to your choice of tools.
The more impedance, the more “wrong” your tool is for the job.
The complexity from impedance usually (usually) is counteracted by the higher complexity ceilings you get with familiar tools, and possibly by the additional simplifications you get from tool mastery.
Impedance isn’t a one-and-done deal: as a system grows, you need to do more things, which adds more impedance (and more places for worse impedance).
The ecosystem growing also reduces the impedance of the “wrong tool”, so it’s more viable in place of the “right tool”.
I think impedance is an interesting source of complexity because it’s avoidable, but not one you always should avoid. You’re often better off writing more complex software if you can stick with a familiar tool.
-
PAGNIs: Probably Are Gonna Need Its | Simon Willison
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.
---
One trick with all of these things is that while they may seem quite expensive to implement, they get dramatically cheaper as you gain experience and gather more tools for helping put them into practice.
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.
-
What engineering can teach (and learn from) us | Hillel Wayne
I’d like to see a lot more thought and planning go into stuff. I’m sure the Agile people are gonna freak out and be like, “You’re doing waterfall!” No, we’re not. We’re just thinking about what we want to build and why. -Matt (chemical)
-
Are We Really Engineers? | Hillel Wayne
Is software engineering “really” engineering? A lot of us call ourselves software engineers. Do we deserve that title? Are we mere pretenders to the idea of engineering? This is an important question, and like all important questions, it regularly sparks arguments online. On one hand you have the people who say we are not engineers because we do not live up to “engineering standards”. These people point to things like The Coming Software Apocalypse as evidence that we don’t have it together. They say that we need things like certification, licensing, and rigorous design if we want to earn the title engineer.
On the other end of the horseshoe, we have people like Pete McBreen and Paul Graham who say that we are not engineers because engineering cannot apply to our domain. Engineers work on predictable projects with a lot of upfront planning and rigorous requirements. Software is dynamic, constantly changing, unpredictable. If we try to apply engineering practice to software then software would be 10 times as expensive and stuck in 1970.
-
What I've Learned in 45 Years in the Software Industry | Joel Goldberg
Technology constantly changes, but some fundamental approaches to software development transcend these trends. Here are six fundamentals that will continue to be relevant for a long time.
- Teamwork: Great teams build great software. Don’t take teamwork for granted.
- Trust: Teams move at the speed of trust. Be the kind of dependable person you would want to work with.
Communication: Communicate honestly and proactively. Avoid the curse of knowledge.
- Seek Consensus: Take the time to bring your whole team along. Let discussion and disagreement bring you to the best solution.
- Automated Testing: Well-tested code allows your team to move fast with confidence.
- Clean, understandable, and navigable code and design: Think of the next engineer that will take over your code as your customer. Build code that your successor won’t have any trouble reading, maintaining, and updating.
---
Fighting complexity is a never-ending cause. Solutions should be as simple as possible. Assume the next person to maintain your code won’t be as smart as you. When you can use fewer technologies, do so.
---
If you don’t guard against the curse of knowledge it has the potential to obfuscate all forms of communication, including code. The more specialized your work, the greater the risk that you will communicate in ways that are incomprehensible to the uninitiated. Fight the curse of knowledge. Work to understand your audience. Try to imagine what it would be like to learn what you are communicating for the first time.
-
The C4 model for visualising software architecture
As an industry, we do have the Unified Modeling Language (UML), ArchiMate and SysML, but asking whether these provide an effective way to communicate software architecture is often irrelevant because many teams have already thrown them out in favour of much simpler "boxes and lines" diagrams. Abandoning these modelling languages is one thing but, perhaps in the race for agility, many software development teams have lost the ability to communicate visually.
-
Modules, monoliths, and microservices | Avery Pennarun
You can find various definitions on the Internet. Here's mine: microservices are the most extreme possible backlash against monoliths.
--
An interface is the connection between modules. A module is a collection of related code. In systems design, we talk about "boxes and arrows" engineering: modules are the boxes, and interfaces are the arrows.
The deeper question then is: how big are the boxes? How much goes in each box? How do we decide when to split one big box into two smaller ones? What's the best way to connect the boxes? There are many approaches to all this. Nobody quite knows what's best. It's one of the hardest problems in software architecture.
Over the decades, we've evolved through many kinds of "boxes." Goto statements were "considered harmful" largely because they prevented any hierarchy at all. Then we added functions or procedures; those are very simple boxes, with interfaces (parameters and return codes) between them.
Depending which branch of programming you go down, you then discover recursive functions, combinators, static function prototypes, libraries (statically or runtime-linked), objects (OOP), coroutines, protected virtual memory, processes, threads, JITs, namespaces, sandboxes, chroots, jails, containers, virtual machines, supervisors, hypervisors, microkernels, and unikernels.
And that's just the boxes! Once you have boxes isolated from each other, then you need to connect them with arrows. For that, we have ABIs, APIs, syscalls, sockets, RPCs, filesystems, databases, message passing systems, and "virtualized hardware."
-
Taco Bell Programming | Ted Dziuba
-
How To Ask Questions The Smart Way | Eric Steven Raymond
We've found by experience that people who are careless and sloppy writers are usually also careless and sloppy at thinking and coding (often enough to bet on, anyway). Answering questions for careless and sloppy thinkers is not rewarding; we'd rather spend our time elsewhere.
-
The Grug Brained Developer | Grug
one day code base understandable and grug can get work done, everything good!
next day impossible: complexity demon spirit has entered code and very dangerous situation!
grug no able see complexity demon, but grug sense its presence in code base
demon complexity spirit mocking him make change here break unrelated thing there what!?! mock mock mock ha ha so funny grug love programming and not becoming shiney rock speculator like grug senior advise
club not work on demon spirit complexity and bad idea actually hit developer who let spirit in with club: sometimes grug himself!
sadly, often grug himself
so grug say again and say often: complexity very, very bad
---
in-between tests, grug hear shaman call "integration tests" sometime often with sour look on face. but grug say integration test sweet spot according to grug: high level enough test correctness of system, low level enough, with good debugger, easy to see what break
---
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
---
grug wonder why big brain take hardest problem, factoring system correctly, and introduce network call too
seem very confusing to grug
-
Professional Programming: The First 10 Years | Thorsten Ball
Fearlessness is undervalued
Most of the programmers I look up to and learned from share one trait that is rarely talked about: fearlessness.
They dive into an unknown codebase without fear. They open up the code of a dependency that they suspect is misbehaving without fear. They start working on something without knowing how they’ll finish.
It’s inspiring seeing someone being fearless, but becoming fearless yourself is one of the best learning accelerators I’ve found.
---
Nothing really matters, except bringing value to the customer
Type safety, 100% test coverage, the ability to fluently express business logic in code, perfect development tooling, an efficient system that wastes no resources, using the best programming language for the job, an elegant API design, a fast feedback loop, writing great code – these are not the goal.
Here’s the goal: providing value to your customers, by shipping software that solves their problem, repeatedly.
The things above help you do that – faster, cheaper, more efficiently, safer, with greater joy – but they’re not the goal. The goal is to provide value to your customers.
The trap: it’s often easier to write software than to deliver it. But delivering is what it’s all about.
---
Perfection is unachievable
I’m not sure I ever thought it is, but now I’m certain it is not. Everything is the result of trade-offs.
You will never reach 100% on every axis that you care about. Something has to give. And when you think you did make it perfect, you’ll soon realise that you forgot something.
My aesthetics have changed too. Instead of looking for the beauty that lies in perfection I now think the program that succeeds despite its flaws is beautiful. Look at that little program go, holding the internet together, despite the 17 TODOs in it.
-
Code Reviews | Matt Van Itallie
-
Gold Plating | Jeff Atwood
On one end you have the individual who solves problems. When they have a task or goal, and run into obstacles, they will solve them, overcome them, bypass them, work around, above or right through them, even if it means redefining the problem to do something just as good or better than the original task or goal. These people would, I think, be Joel's "rosh gadol."
On the other end of the spectrum, you have the person who stops at the first excuse. In other words, as soon as the individual as a justifiable reason to stop looking for a solution, they are finished. While this can be intentional (Joel's example of a "work to rule" situation applies), it is more often just part of their nature. These would be the "rosh katan."
There are, sad to day, a lot more of the latter than the former.
-
Things You Should Never Do, Part I | Joel Spolsky
When you throw away code and start from scratch, you are throwing away all that knowledge. All those collected bug fixes. Years of programming work.
You are throwing away your market leadership. You are giving a gift of two or three years to your competitors, and believe me, that is a long time in software years.
-
I test in prod | Charity Majors
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.
-
Building for the 99% Developers | Future
Software development is not all clean code and automated processes -- and it never will be. Buyers and vendors both need to realize this.
-
Embrace Constraints | REWORK
I don’t actually trust us either to have built great software if we had unlimited people, unlimited time and whatnot, because you end up gold platening things in ways that make them heavy and cumbersome and brittle and easily scratched. When you are forced to make something simpler with simpler materials in less time, I think that you end up with something better.
-
Parse, don’t validate
Use a data structure that makes illegal states unrepresentable. Model your data using the most precise data structure you reasonably can. If ruling out a particular possibility is too hard using the encoding you are currently using, consider alternate encodings that can express the property you care about more easily. Don’t be afraid to refactor.
Push the burden of proof upward as far as possible, but no further. Get your data into the most precise representation you need as quickly as you can. Ideally, this should happen at the boundary of your system, before any of the data is acted upon.
-
The Path of Madness — brandur.org
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 importan...
-
Big Ball of Mud
While much attention has been focused on high-level software architectural patterns, what is, in effect, the de-facto standard software architecture is seldom discussed. This paper examines this most frequently deployed of software architectures: the BIG BALL OF MUD. A BIG BALL OF MUD is a casually, even haphazardly, structured system. Its organization, if one can call it that, is dictated more by expediency than design. Yet, its enduring popularity cannot merely be indicative of a general disregard for architecture.
-
Escaping From Gilligan's Island | Jeff Atwood
As that old software proverb goes, the first ninety percent of the task takes ninety percent of the time, and the last ten percent takes the other ninety percent.
Actually succeeding in a software project depends a whole lot less on not doing a few things wrong but on doing almost everything right.
-
The Joel Test: 12 Steps to Better Code | Joel Spolsky
-
Dad and The Ten Commandments of Egoless Programming | Stephen Wyatt Bush
Understand and accept that you will make mistakes. The point is to find them early, before they make it into production. Fortunately, except for the few of us developing rocket guidance software at JPL, mistakes are rarely fatal in our industry. We can, and should, learn, laugh, and move on.
-
A letter to myself as a fresh software engineer | Luca Florio
Please don’t be affected by the NIH syndrome. There is no point in reinventing the wheel. Avoid wasting time in something that is already out there. If you can achieve your goal simply glueing together some tools, just do it. What you should deliver as a software engineer is value to your business, not lines of code.
-
Railway Oriented Programming | F# for fun and profit
-
Write code that is easy to delete, not easy to... | programming is terrible
-
AHA Programming 💡
I think the key is that we don't know what the future of code will be. We could spend weeks optimizing code for performance, or coming up with the best API for our new abstraction, only to find out the next day that we made incorrect assumptions and the API needs a complete rework or the feature the code was written for is no longer needed. We don't know for sure. All we can really be sure of is that things will probably change, and if they never do then we wont touch the code anyway so who cares what it looks like?
-
What to look for in a code review | Google eng-practices
-
The Boy Scout Rule
If we all checked-in our code a little cleaner than when we checked it out, the code simply could not rot. The cleanup doesn't have to be something big. Change one variable name for the better, break up one function that's a little too large, eliminate one small bit of duplication, clean up one composite if statement.
Can you imagine working on a project where the code simply got better as time passed? Do you believe that any other option is professional? Indeed, isn't continuous improvement an intrinsic part of professionalism?
-
Design with Types | F# for fun and profit
-
The Twelve-Factor App
In the modern era, software is commonly delivered as a service: called web apps, or software-as-a-service. The twelve-factor app is a methodology for building software-as-a-service apps that:
Use declarative formats for setup automation, to minimize time and cost for new developers joining the project;
Have a clean contract with the underlying operating system, offering maximum portability between execution environments;
Are suitable for deployment on modern cloud platforms, obviating the need for servers and systems administration;
Minimize divergence between development and production, enabling continuous deployment for maximum agility;
And can scale up without significant changes to tooling, architecture, or development practices.
The twelve-factor methodology can be applied to apps written in any programming language, and which use any combination of backing services (database, queue, memory cache, etc).
-
How to Report Bugs Effectively | Simon Tatham
-
Magpie Driven Development (MDD) | Bevan Arps
Magpie Driven Development is when you have developers who want to use something new for no better reason than it’s shiny and fun.
Examples include someone using an unexpected programming language to complete some feature work, as illustrated here; someone picking up a research paper from MIT and using the associated demonstration code as the basis for their design; or someone choosing to use a different library for a given task than the one the team has standardized on.
It’s key to recognize that MDD occurs when developers indulge purely because they want to try something new. There’s little or no benefit to the product group or the wider team, and the change is often shoehorned into place regardless of the appropriateness of the solution.
-
20 Things I've Learned in my 20 Years as a Software Engineer | Justin Etheredge
The reason many of us love software is because we are lifelong learners, and in software no matter which direction you look, there are wide vistas of knowledge going off in every direction and expanding by the day. This means that you can spend decades in your career, and still have a huge knowledge gap compared to someone who has also spent decades in a seemingly similar role. The sooner you realize this, the sooner you can start to shed your imposter syndrome and instead delight in learning from and teaching others.
--
Software is a means to an end: The primary job of any software engineer is delivering value. Very few software developers understand this, even fewer internalize it. Truly internalizing this leads to a different way of solving problems, and a different way of viewing your tools. If you really believe that software is subservient to the outcome, you’ll be ready to really find “the right tool for the job” which might not be software at all.
--
The 10x programmer is a silly myth. The idea that someone can produce in 1 day what another competent, hard working, similarly experienced programmer can produce in 2 weeks is silly. I’ve seen programmers that sling 10x the amount of code, and then you have to fix it 10x the amount of times. The only way someone can be a 10x programmer is if you compare them to 0.1x programmers. Someone who wastes time, doesn’t ask for feedback, doesn’t test their code, doesn’t consider edge cases, etc… We should be far more concerned with keeping 0.1x programmers off our teams than finding the mythical 10x programmer.
--
The best software engineers think like designers: Great software engineers think deeply about the user experience of their code. They might not think about it in those terms, but whether it is an external API, programmatic API, user interface, protocol, or any other interface; great engineers consider who will be using it, why it will be used, how it will be used, and what is important to those users. Keeping the user’s needs in mind is really the heart of good user experience.
--
Software engineers, like all humans, need to feel ownership: If you divorce someone from the output of their work, they will care less about their work. I see this almost as a tautology. This is the primary reason why cross-functional teams work so well, and why DevOps has become so popular. It isn’t all about handoffs and inefficiencies, it is about owning the whole process from start to finish, and being directly responsible for delivering value. Give a group of passionate people complete ownership over designing, building, and delivering a piece of software (or anything really) and amazing things will happen.
--
Keep your processes as lean as possible: Everyone wants to be agile these days, but being “agile” is about building things in small chunks, learning, and then iterating. If someone is trying to shoehorn much more into it than that, then they’re probably selling something. It isn’t to say that people don’t need accountability or help to work this way, but how many times have you heard someone from your favorite tech company or large open source project brag about how great their Scrum process is? Stay lean on process until you know you need more. Trust your team and they will deliver.
-
The Product-Minded Software Engineer - The Pragmatic Engineer
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?
-
Software development topics I've changed my mind on after 6 years in the industry | Chris Kiehl
- Despite being called "engineers," most decision are pure cargo-cult with no backing analysis, data, or numbers
- Software architecture probably matters more than anything else. A shitty implementation of a good abstraction causes no net harm to the code base. A bad abstraction or missing layer causes everything to rot.
- So called "best practices" are contextual and not broadly applicable. Blindly following them makes you an idiot
- Designing scalable systems when you don't need to makes you a bad engineer.
- Talking directly to the customer always reveals more about the problem, in less time, and with higher accuracy
- The word "scalable" has a mystical and stupefying power over the mind of the software engineer. Its mere utterance can whip them into a depraved frenzy. Grim actions have been justified using this word
- Typed languages are better when you're working on a team of people with various experience levels
-
Why every software engineering interview should include ops question | Charity Majors
All engineers should embrace the ethos of owning their code in production, and nobody should be promoted or hired into a senior role if they don’t.
And yes, that means all engineers! Even your iOS/Android engineers and website developers should be interested in what happens to their code after they hit deploy. They should care about things like instrumentation, and what kind of data they may need later to debug their problems, and how their features may impact other infrastructure components.
-
Observing containers with the three pillars of observability | Frederic Branczyk
Metrics allow you to evaluate, at a high level, whether a system is behaving as expected. As such, they’re typically used for alerting. There are hundreds of metrics to describe each container, from memory to over-network activity to CPU, so to keep your alerts targeted and useful, focus on ones that describe the end user experience: server error rates, latency, saturation, and so on. Metrics that describe causes, rather than symptoms, of a service failure, like a specific error, CPU, or increased memory, are less helpful: Knowing CPU usage is at 90 percent, for example, doesn’t tell you anything about how users experience the service; knowing 99.9 percent of requests were successfully processed within 100 milliseconds, on the other hand, tells you your service is reliable and fast enough to provide the desired user experience.
-
Design Docs at Google
As software engineers our job is not to produce code per se, but rather to solve problems. Unstructured text, like in the form of a design doc, may be the better tool for solving problems early in a project lifecycle, as it may be more concise and easier to comprehend, and communicates the problems and solutions at a higher level than code.
-
Hyrum's Law
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.
-
The Twelve-Factor App
-
The Architecture Behind A One-Person Tech Startup | Anthony Najjar Simon
-
Career Ladders | Sarah Drasner
-
My Engineering Axioms | Martin True
Your product solves your customer's problem(s), and therefore is your asset. The code itself is the cost of creating the asset. The more code you have, the more it needs to be read, tested, changed, and understood. This is especially relevant when you consider axiom 1. Accept new code (and dependency on external code) conservatively. The best code is code you don't have to write.
---
Until you have a high degree of confidence that your abstraction is going to pay for itself because it solves a real, abstract problem you really do have, don't do it. Wait and learn more. Until then, repeating code can help avoid dependency, which itself makes the code easier to change independently or delete. A premature abstraction creates complexity through dependency and indirection, and can become a bottleneck to your ability to respond to change.
-
Why unit tests and how to make them work for you | Chris James (@quii)
The strength of software is that we can change it. Most software will require change over time in unpredictable ways; but don't try and over-engineer because it's too hard to predict the future
Instead we need to make it so we can keep our software malleable. In order to change software we have to refactor it as it evolves or it will turn into a mess
A good test suite can help you refactor quicker and in a less stressful manner
Writing good unit tests is a design problem so think about structuring your code so you have meaningful units that you can integrate together like Lego bricks
-
Five Rules of Programming | Rob Pike
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.
-
Write code that is easy to delete, not easy to extend | @tef, programming is terrible
Becoming a professional software developer is accumulating a back-catalogue of regrets and mistakes. You learn nothing from success. It is not that you know what good code looks like, but the scars of bad code are fresh in your mind.
Becoming a professional software developer is accumulating a back-catalogue of regrets and mistakes. You learn nothing from success. It is not that you know what good code looks like, but the scars of bad code are fresh in your mind.
-
How to reevaluate your frontend architecture – Increment: Frontend
For me, following this process was a great reminder that idealistic technology choices don’t always match the reality of creating and maintaining consistent software in an organization. Our job as engineers is not just to build websites, it’s to support a business model, contribute to a culture, grow careers, and, above all, create value.
-
How Developers Stop Learning: Rise of the Expert Beginner | Erik Dietrich
The Expert Beginner has nowhere to go because progression requires an understanding that he has a lot of work to do, and that is not a readily available conclusion. If you’ve ever heard the aphorism about “ten years of experience or the same year of experience ten times,” the Expert Beginner is the epitome of the latter.
-
How To Keep Your Best Programmers | Erik Dietrich
(This whole piece, holy shit.)
Don’t get me wrong. There are always organizational gripes or annoyances anywhere you go (or depart from), and it’s always possible that someone will come along and say, “How would you like to make twice as much money doing the coolest work imaginable while working from home in your pajamas?” or that your current employer will say, “We’re going to halve your pay, force you to do horrible grunt work, and send you to Antarctica to do it.” It is certainly possible that I could have a specific reason for leaving, but that seems more the exception than the rule.
As a general practice, I like to examine my own motivations for things that I do. I think this is a good check to make sure that I’m being rational rather than impulsive or childish... I’m not intending to say, “I’m the best and here’s how someone can keep me.” I consider my own programming talent level irrelevant to the post and prefer to think of myself as a competent and productive developer, distinguished by enthusiasm for learning and pride in my work. I don’t view myself as a “rock star,” and I generally view such prima donna self-evaluation to be counterproductive and silly.
…what happens is that the more talented and effective IT engineers are the ones most likely to leave — to evaporate, if you will. They are the ones least likely to put up with the frequent stupidities and workplace problems that plague large organizations; they are also the ones most likely to have other opportunities that they can readily move to.
What tends to remain behind is the ‘residue’ — the least talented and effective IT engineers. They tend to be grateful they have a job and make fewer demands on management; even if they find the workplace unpleasant, they are the least likely to be able to find a job elsewhere. They tend to entrench themselves, becoming maintenance experts on critical systems, assuming responsibilities that no one else wants so that the organization can’t afford to let them go.
-
Going faster with continuous delivery | Mark Mansour @AWS
The project validated the concept of a pipeline as a way for our teams to define all the steps needed to release software to customers. The first step in a pipeline is to build an artifact. The pipeline then runs that build artifact through a series of steps until the artifact is released to all customers. We use pipelines to reduce the risk that a new code change could have a negative impact on our customers. Each step in the pipeline should increase our confidence that the build artifact doesn’t contain defects. If a defect does reach production, we want to get production back to a healthy state as quickly as possible.
===
The answer to the question, “how much testing is enough?” is a judgement call. It requires a team to understand the context in which they operate. To deal with this situation we used another leadership principle, Ownership. This principle is about thinking long term and not sacrificing long-term value for short-term results. Software teams at Amazon have a high bar for testing, and spend a lot of effort on it, because owning a product means also owning the consequences of any defects in that product. If a problem were to have an impact on customers, it is members of the small, single-threaded software team who handle that issue and fix it in real time. The tension between increasing execution speed and responding to issues in production means that teams are motivated to test adequately. However, if we over invest in testing, then we might not succeed because others have moved faster than us. We’re always looking to improve our software release processes without becoming a blocker to the business.
-
Choose Boring Technology or, How to be old, for young people | Dan McKinley
-
Choose Boring Technology | Dan McKinley
Mindful choice of technology gives engineering minds real freedom: the freedom to contemplate bigger questions. Technology for its own sake is snake oil.
-
The Python Paradox | Paul Graham
So far, anyway. Both languages are of course moving targets. But they share, along with Ruby (and Icon, and Joy, and J, and Lisp, and Smalltalk) the fact that they're created by, and used by, people who really care about programming. And those tend to be the ones who do it well.
-
Designing very large (JavaScript) applications | Malte Ubl
You want to get to a state where whatever the engineers on your team do, the most straightforward way is also the right way–so that they don’t get off the path, so that they naturally do the right thing.
This might not always be possible. In that case just add a test. But this is not something that many people feel empowered to do. But please feel empowered to add tests to your application that ensure the major invariants of your infrastructure. Tests are not only for testing that your math functions do the right thing. They are also for infrastructure and for the major design features of your application.
---
What I think being senior means is that I’d be able to solve almost every problem that somebody might throw at me. I know my tools, I know my domain. And the other important part of that job is that I make the junior engineers eventually be senior engineers.
Beyond senior engineer: I can anticipate how the API choices that I’m making, or the abstractions that I’m introducing into a project, how they impact how other people would solve a problem.
---
Now I’m going to talk about how Google actually does this and what is one way to get a good programming model, while also achieving good performance. What we do is we take our components and we split them by rendering logic, and by application logic.
So, now we have two separate things, and we only ever load the application logic for a component when we previously rendered it. This turns out to be a very simple model, because you can simply server side render a page, and then whatever was actually rendered, triggers downloading the associated application bundles. This puts the human out of the system, as loading is triggered automatically by rendering.
-
Fire And Motion | Joel Spolsky
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.
-
Time is the only real currency we have | The Boring Tech Co
My whole point is this - yes, what we do is generally complex and we live in a world where our tools are constantly evolving. We need to continuously up skill ourselves and learn more to stay relevant.
It is important to have the knowledge of a number of tools in our mental tool set - so we can employ any of them for the job at hand.
It is more important, however, to get an understanding of using the right tool for the job. Our work as engineers is to help the company make money by keeping customers happy. Not to show off the latest-thing-I-just-learnt-about to our peers.
---
My whole point is this - yes, what we do is generally complex and we live in a world where our tools are constantly evolving. We need to continuously up skill ourselves and learn more to stay relevant.
It is important to have the knowledge of a number of tools in our mental tool set - so we can employ any of them for the job at hand.
It is more important, however, to get an understanding of using the right tool for the job. Our work as engineers is to help the company make money by keeping customers happy. Not to show off the latest-thing-I-just-learnt-about to our peers.
-
Why users care about how you write code | Kent C. Dodds
So did the way the app code was written impact the end user? You betcha. Did the user care that they had to wait weeks rather than days for the new feature? Yeah, they totally cared.
-
A primer on functional architecture – Increment | Scott Wlaschin
From an architectural perspective, the most obvious consequence of composing bigger functions from smaller ones is that functional systems tend to look like pipelines with inputs and outputs, rather than a message-oriented request/response model.
-
Many good practices of software architecture—cohesion, decoupling, isolation of I/O, etc.—arise naturally from applying functional-programming principles. For example, we’ve seen that in a typical functional design each workflow is constructed independently, comprising only the functionality it needs (which maximizes cohesion), and that autonomy is emphasized at all levels, from individual functions up to bounded contexts (decoupling). Furthermore, a surefire way to enhance testability and maintainability is to keep the business logic in pure, deterministic functions, and to use immutable data models to force data changes to become explicit and unambiguous.
-
Levels of Seniority | Kamran Ahmed
Being content with your role is a bad thing and you should always strive to improve yourself for the next step.
Lots of companies care more for the years of experience to decide the seniority which is a crappy metric -- you don't gain experience just by spending years. You gain it by continuously solving different sorts of problems, irrespective of the number of years you spend in the industry. I have seen fresh graduates having no industry experience get up to speed quickly and producing work of a Senior Engineer and I have seen Senior developers labeled "senior" merely because of their age and "years of experience".
The most important traits that you need to have in order to step up in your career are: not settling with mediocrity, having an open mindset, being humble, learning from your mistakes, working on the challenging problems and having an opportunity mindset rather than a complaining one.
-
An app can be a home-cooked meal | Robin Sloan
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?
-
Teach Yourself Programming in Ten Years | Peter Norvig
So go ahead and buy that Java/Ruby/Javascript/PHP book; you'll probably get some use out of it. But you won't change your life, or your real overall expertise as a programmer in 24 hours or 21 days. How about working hard to continually improve over 24 months? Well, now you're starting to get somewhere...
-
(A few) Ops Lessons We All Learn The Hard Way | Jan Schaumann
- UTC or GTFO
- An API without a reference implementation and command-line client is called a gray box
- Very few operations are truly idempotent
- It's ok to use shell for complex stuff; it often times is easier, faster, and still less of a mess than juggling libraries and dependencies
- A README.md in git is no substitute for a manual page that's shipped with your tool
- That completely automated solution you set up requires at least three manual steps you didn't document
- Doubling your time estimate in the hopes of beating expectations won't work because your manager takes your estimate, has a hardy laugh, and then resets it back to what they already promised upchain
- Recursively applying the Pareto Principle is a surprisingly accurate way to gauge your low hanging fruit, determine your high impact objectives, and ballpark your required effort
- Mandatory code reviews do not automatically improve code quality nor reduce the frequency of incidents
-
Software disenchantment | tonsky
Engineering is understanding performance, structure, limits of what you build, deeply. Combining poorly written stuff with more poorly written stuff goes strictly against that. To progress, we need to understand what and why are we doing.
-
So it’s our mission as engineers to show the world what’s possible with today’s computers in terms of performance, reliability, quality, usability. If we care, people will learn. And there’s nobody but us to show them that it’s very much possible. If only we care.
-
You don’t have to be a genius to write fast programs. There’s no magic trick. The only thing required is not building on top of a huge pile of crap that modern toolchain is.
-
So I want to call it out: where we are today is bullshit. As engineers, we can, and should, and will do better. We can have better tools, we can build better apps, faster, more predictable, more reliable, using fewer resources (orders of magnitude fewer!). We need to understand deeply what we are doing and why. We need to deliver: reliably, predictably, with topmost quality. We can—and should–take pride in our work. Not just “given what we had…”—no buts!
-
The boring technology behind a one-person Internet company | Wenbin Fang
Most of time, the biggest obstacle of building & shipping things is over thinking. What if this, what if that. Boy, you are not important at all. Everyone is busy in their own life. No one cares about you and the things you build, until you prove that you are worth other people’s attention. Even you screw up the initial product launch, few people will notice. Think big, start small, act fast. It’s absolutely okay to use the boring technology and start something simple (even ugly), as long as you actually solve problems.
-
The Standard of Code Review | Google's Engineering Practices
Aspects of software design are almost never a pure style issue or just a personal preference. They are based on underlying principles and should be weighed on those principles, not simply by personal opinion. Sometimes there are a few valid options. If the author can demonstrate (either through data or based on solid engineering principles) that several approaches are equally valid, then the reviewer should accept the preference of the author. Otherwise the choice is dictated by standard principles of software design.
-
Developing In Stockfighter With No Trading Experience | @patio11
In my experience, the modal web developer probably does not believe they can do algorithmic trading or reverse engineering of assembly code. We strongly disagree: every great developer you know got there by solving problems they were unqualified to solve until they actually did it
-
How to Build Good Software | Li Hongyi
Building good software involves alternating cycles of expanding and reducing complexity. As new features are developed, disorder naturally accumulates in the system. When this messiness starts to cause problems, progress is suspended to spend time cleaning up. This two-step process is necessary because there is no such thing as platonically good engineering: it depends on your needs and the practical problems you encounter. Even a simple user interface such as Google’s search bar contains a massive amount of complexity under the surface that cannot be perfected in a single iteration. The challenge is managing this cycle, letting it get messy enough to make meaningful progress, but not letting it get so complicated that it becomes overwhelming.
…the best engineers are at least 10 times more productive than an average engineer. This is not because good engineers write code 10 times faster. It is because they make better decisions that save 10 times the work.
Building software is not about avoiding failure; it is about strategically failing as fast as possible to get the information you need to build something good.
-
Micro Frontends | Cam Jackson
As frontend codebases continue to get more complex over the years, we see a growing need for more scalable architectures. We need to be able to draw clear boundaries that establish the right levels of coupling and cohesion between technical and domain entities. We should be able to scale software delivery across independent, autonomous teams.
-
Stripe Atlas: Guide to Software as a Service, as a business | @patio11
If you are a software entrepreneur, and you do not sell mobile applications (which have a separate billing model, imposed by the platforms’ app stores), you should thoroughly understand the business of SaaS. This will let you make better decisions for your product (and company), allow you to see business-threatening problems months or years in advance of them being obvious, and help you in communicating with investors.
-
How not to hire a software engineer | @tonsky
I mean, I have fourteen years of experience. I’d be happy to talk about functional programming, distributed systems, consensus, replication, collaborative text editing, CRDTs, parallel architectures, UI frameworks, team processes, product design, user experience. I have practical and research experience in all those areas. All of them are in direct interest for more or less any internet giants I’ve been interviewed at.
Was I ever asked about any of those? No.
What I get is “imagine you have a function that takes a list…” five times in a row. Five school-level problems are supposed to give you an adequate impression of what? How thorough was I reading Cormen et al?
-
Fast Software, the Best Software | Craig Mod
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.
-
Software Eats Itself | Can Duruk
But here’s my contrarian bet on technology: While there’s seemingly an unassailable dearth of technology workers, especially in the Bay Area, the tech industry will also be automating itself, faster than most people are ready to appreciate. The lower end will is already experiencing this pain, but the bar will slowly move up
And that’s the other side of my argument. I believe as more and more of the bottom rung of the technology work is either automated or abstracted away, there’ll be more and more demand for the upper end. In other words, more specialization which will require deeper, more intensive training.
-
Pure UI
The fundamental idea I want to discuss is the definition of an application’s UI as a pure function of application state.
-
I don't want to be a full-fullstack developer | Artur Martsinkovskyi
Fullstack is interesting because is seems to be almost unique to the software engineering field. Other fields mostly have more division of labour, you don’t expect the dentist to cure your heart and neurosurgeon to fix your haemorrhoids.
We get mediocre solutions created by people who don’t have enough expertise in the particular field to see the better way, with a sketchy knowledge filled with Stackoverflow answers and copy-paste. We get people who stay stale in their improvements, having to keep up with too many topics. We get the professionals that don’t create amazing things because they don’t have time to dig in enough time to actually create some value to the field. We get substandard products by lower development price that fades off after the bugs and lost customers come in because of issues the projects inevitably face when developed in such the fashion. Fullstack may be worth it from the short-term economical perspective, but it is harmful for the industry overall and for the projects we build.
-
Salary Negotiation: Make More Money, Be More Valued | @patio11
Your salary negotiation — which routinely takes less than 5 minutes to conclude — has an outsized influence on what your compensation is. Compensation can include money or things which are more-or-less fungible replacements for money, but it can also include interesting things which you value from “more time with your family” to “opportunities to do tasks which you find fulfilling” to “perks which make a meaningful difference in your day-to-day quality of life.” That makes your negotiation five very important minutes. You generally can’t do a totally bang up job on any five minutes of work this year and have your boss give you an extra $5,000. You can trivially pick up $5,000 in salary negotiations just by sucking less.
-
What Working At Stripe Has Been Like | @patio11
Stripe is a celebration of the written word which happens to be incorporated in the state of Delaware.
We produce prodigious amounts of it internally, most of it widely visible within the company. My favorite job perk might be that library; it includes everything from a crackling memo about current state of book publishing (relevant to our interests) to experiment writeups about using machine learning to counter credit card fraud (relevant to our interests) to market analyses of SaaS adoption in Japanese businesses (relevant to our interests).
-
Pinboard — Pay to Play to Keep a System Small
Have a mantra. Pinboard has the goals of: being fast, reliable, and terse. They think these are the qualities that will earn and keep customers. When a problem comes up, like massive growth, they always prioritize so that these system qualities are maintained. For example, their first priority is preventing data loss, which dictated changing their server architecture. So the site seems conceptually confusing during a period of growth that's OK...if the site is quickly and reliably saving links.
-
Why I’m Done Making Desktop Applications | @patio11
It has exceeded all my expectations: in ease of writing, in features, in sales, in support burden, in marketability, etc. In game theory terms, it strictly dominates the desktop version, when seen from the eyes of the developer at any rate.
If I were starting out today, I would, without a shadow of a doubt, write a web app instead of a desktop app.
-
Don't Call Yourself A Programmer, And Other Career Advice | Patrick McKenzie
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.
-
Latency Numbers Every Programmer Should Know | jboner
Latency Comparison Numbers (~2012)
----------------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 3,000 ns 3 us
Send 1K bytes over 1 Gbps network 10,000 ns 10 us
Read 4K randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
Disk seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB
-
Functional Core, Imperative Shell | Gary Bernhardt
Purely functional code makes some things easier to understand: because values don't change, you can call functions and know that only their return value matters—they don't change anything outside themselves. But this makes many real-world applications difficult: how do you write to a database, or to the screen?
In this screencast we look at one method for crossing this divide. We review a Twitter client whose core is functional: managing tweets, syncing timelines to incoming Twitter API data, remembering cursor positions within the tweet list, and rendering tweets to text for display. This functional core is surrounded by a shell of imperative code: it manipulates stdin, stdout, the database, and the network, all based on values produced by the functional core.
This design has many nice side effects. For example, testing the functional pieces is very easy, and it often naturally allows isolated testing with no test doubles. It also leads to an imperative shell with few conditionals, making reasoning about the program's state over time much easier.
-
Boundaries | Gary Bernhardt
-
Programming Sucks | Still Drinking
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
---
So no, I’m not required to be able to lift objects weighing up to fifty pounds. I traded that for the opportunity to trim Satan’s pubic hair while he dines out of my open skull so a few bits of the internet will continue to work for a few more days.