A Philosophy of Software Design
Rate it:
Open Preview
5%
Flag icon
I have talked with several people I consider to be great programmers, but most of them had difficulty articulating specific techniques that give them their advantage.
Augusto Marinho
O estudo de design system pode ajudar a endereçar este problema
6%
Flag icon
Over time, complexity accumulates, and it becomes harder and harder for programmers to keep all of the relevant factors in their minds as they modify the system.
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
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
Complexity is more apparent to readers than writers. If you write a piece of code and it seems simple to you, but other people think it is complex, then it is complex.
9%
Flag icon
Your job as a developer is not just to create code that you can work with easily, but to create code that others can also work with easily.
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.
10%
Flag icon
Complexity is caused by two things: dependencies and obscurity.
11%
Flag icon
The second cause of complexity is obscurity. Obscurity occurs when important information is not obvious.
11%
Flag icon
Complexity isn’t caused by a single catastrophic error; it accumulates in lots of small chunks.
12%
Flag icon
The tactical tornado is a prolific programmer who pumps out code far faster than others but works in a totally tactical fashion.
12%
Flag icon
However, tactical tornadoes leave behind a wake of destruction. They are rarely considered heroes by the engineers who must work with their code in the future.
13%
Flag icon
Over time, these mistakes will become obvious. When you discover a design problem, don’t just ignore it or patch around it; take a little extra time to fix it.
13%
Flag icon
The term technical debt is often used to describe the problems caused by tactical programming.
14%
Flag icon
The best way to lower development costs is to hire great engineers:
15%
Flag icon
One of the most important techniques for managing software complexity is to design systems so that developers only need to face a small fraction of the overall complexity at any given time.
15%
Flag icon
The best modules are those whose interfaces are much simpler than their implementations.
16%
Flag icon
An abstraction that omits important details is a false abstraction
19%
Flag icon
By separating the interface of a module from its implementation, we can hide the complexity of the implementation from the rest of the system.
19%
Flag icon
The basic idea is that each module should encapsulate a few pieces of knowledge, which represent design decisions.
20%
Flag icon
This creates a dependency between the modules: any change to that design decision will require changes to all of the involved modules.
20%
Flag icon
Information leakage is one of the most important red flags in software design.
21%
Flag icon
When designing modules, focus on the knowledge that’s needed to perform each task, not the order in which tasks occur
24%
Flag icon
The best features are the ones you get without even knowing they exist.
25%
Flag icon
In reviewing student projects I noticed that general-purpose classes were almost always better than special-purpose alternatives.
27%
Flag icon
One of the most important elements of software design is determining who needs to know what, and when.
30%
Flag icon
The best way to do this is by designing the normal case in a way that automatically handles the edge conditions without any extra code.
31%
Flag icon
Specialization can’t be eliminated completely, but with good design you should be able to reduce it significantly and separate specialized code from general-purpose code. This will result in deeper classes, better information hiding, and simpler and more obvious code.
33%
Flag icon
The motivation for decorators is to separate special-purpose extensions of a class from a more generic core.
35%
Flag icon
Contexts may also create thread-safety issues; the best way to avoid problems is for variables in a context to be immutable. Unfortunately, I haven’t found a better solution than contexts.
36%
Flag icon
it is more important for a module to have a simple interface than a simple implementation.
41%
Flag icon
This separation added complexity with no benefit. The logging methods were shallow: most consisted of a single line of code, but they required a considerable amount of documentation.
42%
Flag icon
Methods containing hundreds of lines of code are fine if they have a simple signature and are easy to read. These methods are deep (lots of functionality, simple interface), which is good.
42%
Flag icon
When designing methods, the most important goal is to provide clean abstractions. Each method should do one thing and do it completely.
42%
Flag icon
red flag (“Conjoined Methods”)
42%
Flag icon
It should be possible to understand each method independently. If you can’t understand the implementation of one method without also understanding the implementation of another, that’s a red flag. This red flag can occur in other contexts as well: if two pieces of code are physically separated, but each can only be understood by looking at the other, that is a red flag.
43%
Flag icon
Depth is more important than length: first make functions deep, then try to make them short enough to be easily read. Don’t sacrifice depth for length.
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.
45%
Flag icon
A recent study found that more than 90% of catastrophic failures in distributed data-intensive systems were caused by incorrect error handling1.
48%
Flag icon
Exception masking is an example of pulling complexity downward.
52%
Flag icon
no-one is good enough to get it right with their first try.
52%
Flag icon
I hope these chapters will convince you of three things: good comments can make a big difference in the overall quality of software; it isn’t hard to write good comments; and (this may be hard to believe) writing comments can actually be fun.
52%
Flag icon
When developers don’t write comments, they usually justify their behavior with one or more of the following excuses: “Good code is self-documenting.” “I don’t have time to write comments.” “Comments get out of date and become misleading.” “The comments I have seen are all worthless; why bother?”
54%
Flag icon
Code reviews provide a great mechanism for detecting and fixing stale comments.
54%
Flag icon
The overall idea behind comments is to capture information that was in the mind of the designer but couldn’t be represented in the code.
« Prev 1