The Robert C. Martin Clean Code Collection (Collection) (Robert C. Martin Series)
Rate it:
Open Preview
10%
Flag icon
If a function does only those steps that are one level below the stated name of the function, then the function is doing one thing.
10%
Flag icon
In order to make sure our functions are doing “one thing,” we need to make sure that the statements within our function are all at the same level of abstraction.
10%
Flag icon
we want to be able to read the program as though it were a set of TO paragraphs, each of which is describing the current level of abstraction and referencing subsequent TO paragraphs at the next level down.
11%
Flag icon
There are two very common reasons to pass a single argument into a function. You may be asking a question about that argument, as in boolean fileExists(“MyFile”). Or you may be operating on that argument, transforming it into something else and returning it. For example, InputStream fileOpen(“MyFile”) transforms a file name String into an InputStream return value. These two uses are what readers expect when they see a function. You should choose names that make the distinction clear, and always use the two forms in a consistent context. (See Command Query Separation below.) A somewhat less ...more
11%
Flag icon
Flag arguments are ugly. Passing a boolean into a function is a truly terrible practice. It immediately complicates the signature of the method, loudly proclaiming that this function does more than one thing. It does one thing if the flag is true and another if the flag is false!
12%
Flag icon
When a function seems to need more than two or three arguments, it is likely that some of those arguments ought to be wrapped into a class of their own.
12%
Flag icon
Side effects are lies.
12%
Flag icon
Functions should either do something or answer something, but not both.
12%
Flag icon
Prefer Exceptions to Returning Error Codes Returning error codes from command functions is a subtle violation of command query separation.
12%
Flag icon
Functions should do one thing. Error handing is one thing. Thus, a function that handles errors should do nothing else. This implies (as in the example above) that if the keyword try exists in a function, it should be the very first word in the function and that there should be nothing after the catch/finally blocks.
12%
Flag icon
When you use exceptions rather than error codes, then new exceptions are derivatives of the exception class. They can be added without forcing any recompilation or redeployment.12
13%
Flag icon
Structured programming, Aspect Oriented Programming, Component Oriented Programming, are all, in part, strategies for eliminating duplication.
13%
Flag icon
The proper use of comments is to compensate for our failure to express ourself in code.
13%
Flag icon
Why am I so down on comments? Because they lie. Not always, and not intentionally, but too often. The older a comment is, and the farther away it is from the code it describes, the more likely it is to be just plain wrong. The reason is simple. Programmers can’t realistically maintain them.
18%
Flag icon
If one function calls another, they should be vertically close, and the caller should be above the callee, if at all possible. This gives the program a natural flow.
20%
Flag icon
Objects hide their data behind abstractions and expose functions that operate on that data. Data structure expose their data and have no meaningful functions.
20%
Flag icon
Procedural code (code using data structures) makes it easy to add new functions without changing the existing data structures. OO code, on the other hand, makes it easy to add new classes without changing existing functions.
20%
Flag icon
Procedural code makes it hard to add new data structures because all the functions must change. OO code makes it hard to add new functions because all the classes must change.
20%
Flag icon
There is a well-known heuristic called the Law of Demeter2 that says a module should not know about the innards of the objects it manipulates.
20%
Flag icon
More precisely, the Law of Demeter says that a method f of a class C should only call the methods of these: • C • An object created by f • An object passed as an argument to f • An object held in an instance variable of C The method should not invoke methods on objects that are returned by any of the allowed functions. In other words, talk to friends, not to strangers.
20%
Flag icon
This confusion sometimes leads to unfortunate hybrid structures that are half object and half data structure. They have functions that do significant things, and they also have either public variables or public accessors and mutators that, for all intents and purposes, make the private variables public, tempting other external functions to use those variables the way a procedural program would use a data structure.4 Such hybrids make it hard to add new functions but also make it hard to add new data structures. They are the worst of both worlds. Avoid creating them.
21%
Flag icon
Objects expose behavior and hide data. This makes it easy to add new kinds of objects without changing existing behaviors. It also makes it hard to add new behaviors to existing objects. Data structures expose data and have no significant behavior. This makes it easy to add new behaviors to existing data structures but makes it hard to add new data structures to existing functions. In any given system we will sometimes want the flexibility to add new data types, and so we prefer objects for that part of the system. Other times we will want the flexibility to add new behaviors, and so in that ...more
21%
Flag icon
Use Exceptions Rather Than Return Codes
21%
Flag icon
In a way, try blocks are like transactions. Your catch has to leave your program in a consistent state, no matter what happens in the try. For this reason it is good practice to start with a try-catch-finally statement when you are writing code that could throw exceptions.
22%
Flag icon
Each exception that you throw should provide enough context to determine the source and location of an error. In Java, you can get a stack trace from any exception; however, a stack trace can’t tell you the intent of the operation that failed. Create informative error messages and pass them along with your exceptions. Mention the operation that failed and the type of failure. If you are logging in your application, pass along enough information to be able to log the error in your catch.
22%
Flag icon
We can classify them by their source: Did they come from one component or another? Or their type: Are they device failures, network failures, or programming errors? However, when we define exception classes in an application, our most important concern should be how they are caught.
22%
Flag icon
Returning null from methods is bad, but passing null into methods is worse.
24%
Flag icon
First Law You may not write production code until you have written a failing unit test. Second Law You may not write more of a unit test than is sufficient to fail, and not compiling is failing. Third Law You may not write more production code than is sufficient to pass the currently failing test.
24%
Flag icon
These three laws lock you into a cycle that is perhaps thirty seconds long.
24%
Flag icon
Test code is just as important as production code. It is not a second-class citizen.
26%
Flag icon
F.I.R.S.T.8
26%
Flag icon
Fast Tests should be fast. They should run quickly. When tests run slow, you won’t want to run them frequently.
26%
Flag icon
Independent Tests should not depend on each other. One test should not set up the conditions for the next test. You should be able to run each test independently and run the tests in any order you like. When tests depend on each other, then the first one to fail causes a cascade of downstream failures, making diagnosis difficult and hiding downstream defects.
26%
Flag icon
Repeatable Tests should be repeatable in any environment. You should be able to run the tests in the production environment, in the QA environment, and on your laptop while riding home on the train without a network.
26%
Flag icon
Self-Validating The tests should have a boolean output. Either they pass or fail. You should not have to read through a log file to tell whether the tests pass.
26%
Flag icon
Timely The tests need to be written in a timely fashion. Unit tests should be written just before the production code that makes them pass. If you write tests after the production code, then you may find the production code to be hard to test. You may decide that some production code is too hard to test. You may not design the production code to be testable.
26%
Flag icon
class should begin with a list of variables. Public static constants, if any, should come first. Then private static variables, followed by private instance variables. There is seldom a good reason to have a public variable.
26%
Flag icon
Encapsulation We like to keep our variables and utility functions private, but we’re not fanatic about it. Sometimes we need to make a variable or utility function protected so that it can be accessed by a test. For us, tests rule. If a test in the same package needs to call a function or access a variable, we’ll make it protected or package scope. However, we’ll first look for a way to maintain privacy. Loosening encapsulation is always a last resort.
26%
Flag icon
The first rule of classes is that they should be small. The second rule of classes is that they should be smaller than that.
26%
Flag icon
If we cannot derive a concise name for a class, then it’s likely too large. The more ambiguous the class name, the more likely it has too many responsibilities. For example, class names including weasel words like Processor or Manager or Super often hint at unfortunate aggregation of responsibilities.
26%
Flag icon
We should also be able to write a brief description of the class in about 25 words, without using the words “if,” “and,” “or,” or “but.”
27%
Flag icon
The Single Responsibility Principle (SRP)2 states that a class or module should have one, and only one, reason to change.
27%
Flag icon
Trying to identify responsibilities (reasons to change) often helps us recognize and create better abstractions in our code.
27%
Flag icon
system with many small classes has no more moving parts than a system with a few large classes. There is just as much to learn in the system with a few large classes.
27%
Flag icon
Classes should have a small number of instance variables. Each of the methods of a class should manipulate one or more of those variables. In general the more variables a method manipulates the more cohesive that method is to its class. A class in which each variable is used by each method is maximally cohesive. In general it is neither advisable nor possible to create such maximally cohesive classes; on the other hand, we would like cohesion to be high. When cohesion is high, it means that the methods and variables of the class are co-dependent and hang together as a logical whole.
27%
Flag icon
The strategy of keeping functions small and keeping parameter lists short can sometimes lead to a proliferation of instance variables that are used by a subset of methods. When this happens, it almost always means that there is at least one other class trying to get out of the larger class. You should try to separate the variables and methods into two or more classes such that the new classes are more cohesive.
27%
Flag icon
When classes lose cohesion, split them!
28%
Flag icon
Private method behavior that applies only to a small subset of a class can be a useful heuristic for spotting potential areas for improvement. However, the primary spur for taking action should be system change itself.
29%
Flag icon
Inversion of Control moves secondary responsibilities from an object to other objects that are dedicated to the purpose, thereby supporting the Single Responsibility Principle.
30%
Flag icon
It is a myth that we can get systems “right the first time.” Instead, we should implement only today’s stories, then refactor and expand the system to implement new stories tomorrow. This is the essence of iterative and incremental agility. Test-driven development, refactoring, and the clean code they produce make this work at the code level.
« Prev 1 3