One of the most important properties about any software system is the ability to understand what it is going to do without having to run it. This concept is usually referred to as the ability to “reason about the system.” Basically, you want to make statements about the structures, actions, and results of the system without having to see them in action first.
To understand why this is important, imagine a system with a hundred different pieces. To keep this simple, let’s pretend it’s an actual physical system, and not a computer. Let’s say that we have an automated plant that produces cars, with 100 steps from raw materials to finished car. Each of these parts makes some change to the input materials to produce an output product. There are various ways we could configure this system and each of its pieces: Continue reading
Many years ago, I wrote a blog post explaining what was wrong with computers, and essentially saying the problem was complexity. Several years after that, I published Code Simplicity, which was essentially a thesis describing how and why simplicity was the most important quality of software.
Many years after that, I was sitting in a room of some of the world’s most experienced software engineers, coming up with guidelines and principles around which we wanted to structure software development, and after questioning the room, I came to a terrible realization: nobody had ever defined what “simplicity” was for software.
I thought, perhaps naively, that this was simply a known fact—that when I said “simplicity,” everybody just knew what I meant. To some degree, honestly, this was true. When you say the word “simplicity,” people at least get some idea. But I noticed that people would apply it in many different ways, some of them very much not what I intended. I would see people point at a function or file and say, “Look, it has fewer lines of code now, thus it is simpler!” Or say, “Look, this system uses such-and-such design pattern, thus it is now simpler!” Or worse, “This system is now completely generic and follows all of the things that ‘everybody knows’ you’re supposed to do with software, so that’s simple, right?”
So, I went on a search to try to find some sort of valid definition for simplicity. Eventually, I had to come up with it. I actually came up with this several years ago now, and I’ve been meaning to write a blog post about it, but simply haven’t done so. So what is the answer to this great mystery? For software, what is simplicity? Continue reading
There’s a point that I’ve been making to engineers recently that I realized would be valuable if shared more widely.
When you do engineering work, there are different types of tasks that get given to you. Some tasks are emergencies or short-term work. We sometimes call this “putting out fires,” especially when the work relates to handling something that is urgently broken or immediately needed without delay.
Other tasks are strategic in nature. You have collected information about what is needed and/or wanted from your users, you’ve designed a solution, and you’re working toward it methodically and intelligently.
It is important to understand when you are doing which type of work, and to think about them differently. Continue reading
One question that people ask me all the time is, “How do I become a programmer?” Or, “How do I learn to program?” Continue reading
There are three key factors to being or becoming a great programmer: awareness, understanding, and responsibility.
I’ve talked a lot about the subject of understanding. Heck, I even named my most recent book Understanding Software. In particular, I’ve pointed out many times that the better you understand something, the better you will do it.
However, there are two other factors that go along with understanding to make somebody into an excellent software developer. In brief, if you aren’t aware of a problem, there’s no understanding to be had. And if you don’t take action to solve the problem (which starts with taking responsibility for it) then you can’t do anything about it.
There’s a lot to know about each of these points, though, and they are key points when one looks at how to become a better software developer. So I want to go into each one in more depth with you, here. Continue reading
Hey everybody. I’ve published a new book! It’s called Understanding Software.
The book contains all of the content that I’ve written on software development and working in teams since the publication of Code Simplicity, plus some entirely new content that’s never been published anywhere. In fact, it contains one of my favorite essays that I ever wrote from back in 2008 but never published before. So there’s that for you. All the content has been put into a beautiful layout, then curated and organized for maximum readability.
It’s something I’m actually really happy with, and I’m looking forward to hearing what you have to say about it, too.
From the Publisher
Understanding Software covers many areas of programming, from how to write simple code to profound insights into programming, and then how to suck less at what you do! You’ll discover the problems with software complexity, the root of its causes, and how to use simplicity to create great software. You’ll examine debugging like you’ve never done before, and how to get a handle on being happy while working in teams.
Max brings a selection of carefully crafted essays, thoughts, and advice about working and succeeding in the software industry, from his legendary blog Code Simplicity. Max has crafted forty-three essays which have the power to help you avoid complexity and embrace simplicity, so you can be a happier and more successful developer.
Max’s technical knowledge, insight, and kindness, has earned him a status as a code guru, and his ideas will inspire you and help refresh your approach to the challenges of being a developer.
What you will learn
- See how to bring simplicity and success to your programming world
- Clues to complexity – and how to build excellent software
- Simplicity and software design
- Principles for programmers
- The secrets of rockstar programmers
- Max’s views and interpretation of the Software industry
- Why Programmers suck and how to suck less as a programmer
- Software design in two sentences
- What is a bug? Go deep into debugging
You can get it on Amazon, direct from the publisher, or in any other place where programming books are sold.
It is very easy to think of software development as being an entirely technical activity, where humans don’t really matter and everything is about the computer. However, the opposite is actually true.
Software engineering is fundamentally a human discipline.
Many of the mistakes made over the years in trying to fix software development have been made by focusing purely on the technical aspects of the system without thinking about the fact that it is human beings who write the code. When you see somebody who cares about optimization more than readability of code, when you see somebody who won’t write a comment but will spend all day tweaking their shell scripts to be fewer lines, when you have somebody who can’t communicate but worships small binaries, you’re seeing various symptoms of this problem.
In reality, software systems are written by people. They are read by people, modified by people, understood or not by people. They represent the mind of the developers that wrote them. They are the closest thing to a raw representation of thought that we have on Earth. They are not themselves human, alive, intelligent, emotional, evil, or good. It’s people that have those qualities. Software is used entirely and only to serve people. They are the product of people, and they are usually the product of a group of those people who had to work together, communicate, understand each other, and collaborate effectively. As such, there’s an important point to be made about working with a group of software engineers:
There is no value to being cruel to other people in the development community.
It doesn’t help to be rude to the people that you work with. It doesn’t help to angrily tell them that they are wrong and that they shouldn’t be doing what they are doing. It does help to make sure that the laws of software design are applied, and that people follow a good path in terms of making systems that can be easily read, understood, and maintained. It doesn’t require that you be cruel to do this, though. Sometimes you do have to tell people that they haven’t done the right thing. But you can just be matter of fact about it—you don’t have to get up in their face or attack them personally for it.
For example, let’s say somebody has written a bad piece of code. You have two ways you could comment on this: Continue reading
Sometimes people have a very hard time debugging. Mostly, these are people who believe that in order to debug a system, you have to think about it instead of looking at it.
Let me give you an example of what I mean. Let’s say you have a web server that is silently failing to serve pages to users 5% of the time. What is your reaction to this question: “Why?”
Do you immediately try to come up with some answer? Do you start guessing? If so, you are doing the wrong thing.
The right answer to that question is: “I don’t know.”
So this gives us the first step to successful debugging: Continue reading
There’s a point that I made in the book but which I have had to point out to people a few times since then, and so I wanted to emphasize it a bit more.
When you clean up code, you are always doing it in the service of the product. Refactoring is essentially an organizational process (not the definition of “organizational” meaning “having to do with a business” but the definition meaning “having to do with putting things in order”). That is, you’re putting in order so that you can do something.
When you start refactoring for the sake of refactoring alone, refactoring gets a bad name. People start to think that you’re wasting your time, you lose your credibility, and your manager or peers will stop you from continuing your work.
When I say “refactoring for the sake of refactoring alone,” what I mean is looking at a piece of code that has nothing to do with what you’re actually working on, saying, “I don’t like the way that this is designed,” and moving parts of the design around without affecting the functionality of the system. This is like watering the lawn when your house is on fire. If your codebase is like most of the codebases I’ve seen, “your house is on fire” is probably even an appropriate analogy. Even so, if things aren’t that bad, the point is that you’re focusing on something that doesn’t need to be focused on. You might feel like you’re doing a great job of reorganizing the code, and probably you are, but the point of watering your lawn is to have a nice lawn in front of your house. If your refactoring has nothing to do with the current product or feature goals of your system, you’re not actually accomplishing anything other than re-ordering something that nobody is using, involved with, or cares about.
So what is it that you want to do? Continue reading
Often, people who work on engineering productivity either come into conflict with the developers they are attempting to help, or spend a long time working on some project that ends up not mattering because nobody actually cares about it.
This comes about because the problem that you see that a development team has is not necessarily the problem that they know exists. For example, you could come into the team and see that they have hopelessly complex code and so they can’t write good tests or maintain the system easily. However, the developers aren’t really that aware that they have complex code or that this complexity is causing the trouble that they are having. What they are aware of is something like, “we can only release once a month and the whole team has to stay at work until 10:00 PM to get the release out on the day that we release.”
When engineering productivity workers encounter this situation, some of them just try to ignore the developers’ complaints and just go start refactoring code. This doesn’t really work, for several reasons. The first is that both management and some other developers will resist you, making it more difficult than it needs to be to get the job done. But if just simple resistance was the problem, you could overcome it. The real problem is that you will become unreal and irrelevant to the company, even if you’re doing the best job that anybody’s ever seen. Your management will try to dissuade you from doing your job, or even try to get rid of you. When you’re already tackling technical complexity, you don’t need to also be tackling a whole company that’s opposed to you.
In time, many engineering productivity workers develop an adversarial attitude toward the developers that they are working with. They feel that if the engineers would “just use the tool that I wrote” then surely all would be well. But the developers aren’t using the tool that you wrote, so why does your tool even matter? The problem here is that when you start off ignoring developer complaints (or don’t even find out what problems developers think they have) that’s already inherently adversarial. That is, it’s not that everything started off great and then somehow became this big conflict. It actually started off with a conflict by you thinking that there was one problem and the developers thinking there was a different problem.
And it’s not just that the company will be resistive—this situation is also highly demoralizing to the individual engineering productivity worker. In general, people like to get things done. They like for their work to have some result, to have some effect. If you do a bunch of refactoring but nobody maintains the code’s simplicity, or you write some tool/framework that nobody uses, then ultimately you’re not really doing anything, and that’s disheartening.
So what should you do? Continue reading