A Philosophy of Software Design
Rate it:
Open Preview
Read between November 13 - November 17, 2024
8%
Flag icon
Complexity is anything related to the structure of a software system that makes it hard to understand and modify the system.
9%
Flag icon
Complexity can take many forms. For example, it might be hard to understand how a piece of code works; it might take a lot of effort to implement a small improvement, or it might not be clear which parts of the system must be modified to make the improvement; it might be difficult to fix one bug without introducing another. If a software system is hard to understand and modify, then it is complicated; if it is easy to understand and modify, then it is simple.
9%
Flag icon
The overall complexity of a system (C) is determined by the complexity of each part p (cp) weighted by the fraction of time developers spend working on that part (tp). Isolating complexity in a place where it will never be seen is almost as good as eliminating the complexity entirely.
9%
Flag icon
Change amplification: The first symptom of complexity is that a seemingly simple change requires code modifications in many different places.
9%
Flag icon
Cognitive load: The second symptom of complexity is cognitive load, which refers to how much a developer needs to know in order to complete a task.
10%
Flag icon
Sometimes an approach that requires more lines of code is actually simpler, because it reduces cognitive load.
10%
Flag icon
Unknown unknowns: The third symptom of complexity is that it is not obvious which pieces of code must be modified to complete a task, or what information a developer must have to carry out the task successfully.
10%
Flag icon
One of the most important goals of good design is for a system to be obvious.
11%
Flag icon
The need for extensive documentation is often a red flag that the design isn’t quite right.
12%
Flag icon
working code isn’t enough. It’s not acceptable to introduce unnecessary complexities in order to finish your current task faster.
22%
Flag icon
information hiding can often be improved by making a class slightly larger.
24%
Flag icon
The best features are the ones you get without even knowing they exist.
24%
Flag icon
When decomposing a system into modules, try not to be influenced by the order in which operations will occur at runtime; that will lead you down the path of temporal decomposition, which will result in information leakage and shallow modules. Instead, think about the different pieces of knowledge that are needed to carry out the tasks of your application, and design each module to encapsulate one or a few of those pieces of knowledge.
24%
Flag icon
over-specialization may be the single greatest cause of complexity in software.
25%
Flag icon
the sweet spot is to implement new modules in a somewhat general-purpose fashion. The phrase “somewhat general-purpose” means that the module’s functionality should reflect your current needs, but its interface should not.
27%
Flag icon
One of the most important elements of software design is determining who needs to know what, and when. When the details are important, it is better to make them explicit and as obvious as possible,
36%
Flag icon
it is more important for a module to have a simple interface than a simple implementation.
39%
Flag icon
If the same piece of code (or code that is almost the same) appears over and over again, that’s a red flag that you haven’t found the right abstractions.
43%
Flag icon
The decision to split or join modules should be based on complexity. Pick the structure that results in the best information hiding, the fewest dependencies, and the deepest interfaces.
51%
Flag icon
Designing software is hard, so it’s unlikely that your first thoughts about how to structure a module or system will produce the best design. You’ll end up with a much better result if you consider multiple options for each major design decision: design it twice.
55%
Flag icon
Well-written comments are not failures. They increase the value of code and serve a fundamental role in defining abstractions and managing system complexity.
60%
Flag icon
Higher-level comments are more difficult to write than lower-level comments because you must think about the code in a different way. Ask yourself: What is this code trying to do? What is the simplest thing you can say that explains everything in the code? What is the most important thing about this code?
78%
Flag icon
If you want to maintain a clean design for a system, you must take a strategic approach when modifying existing code. Ideally, when you have finished with each change, the system will have the structure it would have had if you had designed it from the start with that change in mind.
85%
Flag icon
better not to use generic containers. If you need a container, define a new class or structure that is specialized for the particular use. You can then use meaningful names for the elements, and you can provide additional documentation in the declaration, which is not possible with the generic container.
85%
Flag icon
software should be designed for ease of reading, not ease of writing.
87%
Flag icon
One of the risks of agile development is that it can lead to tactical programming. Agile development tends to focus developers on features, not abstractions, and it encourages developers to put off design decisions in order to produce working software as soon as possible.
94%
Flag icon
look for leverage, where the solution to one problem also allows many other problems to be solved, or where knowing one piece of information makes it easy to understand many other things.
95%
Flag icon
Focusing on what is important is also a great life philosophy: identify a few things that matter most to you, and try to spend as much of your energy as possible on those things. Don’t fritter away all of your time on things that you don’t consider important or rewarding.