More on this book
Community
Kindle Notes & Highlights
Avoid duplicate code. Undoubtedly
Simplify complicated boolean tests. Understanding
Putting such a test into a function makes the code more readable because (1) the details of the test are out of the way and (2) a descriptive function name summarizes the purpose of the test.
One of the strongest mental blocks to creating effective routines is a reluctance to create a simple routine for a simple purpose. Constructing a whole routine to contain two or three lines of code might seem like overkill, but experience shows how helpful a good small routine can be.
A function like Cosine() is perfectly cohesive because the whole routine is dedicated to performing one function. A function like CosineAndTan() has lower cohesion because it tries to do more than one thing. The goal is to have each routine do one thing well and not do anything else.
payoff is higher reliability.
Make names of routines as long as necessary. Research shows that the optimum average length for a variable name is 9 to 15 characters.
Routines tend to be more complicated than variables, and good names for them tend to be longer.
To name a function, use a description of the return value. A function returns a value, and the function should be named for the value it returns. For example, cos(), customerId.Next(), printer.IsReady(), and pen.CurrentColor() are all good function names that indicate precisely what the functions return.
To name a procedure, use a strong verb followed by an object. A procedure with functional cohesion usually performs an operation on an object. The name should reflect what the procedure does, and an operation on an object implies a verb-plus-object name. PrintDocument(), CalcMonthlyRevenues(), CheckOrderlnfo(), and RepaginateDocument() are samples of good procedure names.
A large percentage of routines in object-oriented programs will be accessor routines, which will be very short. From time to time, a complex algorithm will lead to a longer routine, and in those circumstances, the routine should be allowed to grow organically up to 100–200 lines. (A line is a noncomment, nonblank line of source code.) Decades of evidence say that routines of such length are no more error prone than shorter routines. Let issues such as the routine's cohesion, depth of nesting, number of variables, number of decision points, number of comments needed to explain the routine, and
...more
In short, use a function if the primary purpose of the routine is to return the value indicated by the function name. Otherwise, use a procedure.
Assertions are especially useful in large, complicated programs and in high-reliability programs. They enable programmers to more quickly flush out mismatched interface assumptions, errors that creep in when code is modified, and so on.
Use error-handling code for conditions you expect to occur; use assertions for conditions that should. never occur Assertions
Error handling typically checks for bad input data; assertions check for bugs in the code.
error-handling code is used to address an anomalous condition, the error handling will enable the program to respond to the error gracefully. If an assertion is fired for an anomalous condition, the corrective action is not merely to handle an error gracefully—the corrective action is to change the program's source code, recompile, and release a new version of the software.
Developers tend to use these terms informally, but, strictly speaking, these terms are at opposite ends of the scale from each other. Correctness means never returning an inaccurate result; returning no result is better than returning an inaccurate result. Robustness means always trying to do something that will allow the software to keep operating, even if that leads to results that are inaccurate sometimes.
With so many options, you need to be careful to handle invalid parameters in consistent ways throughout the program. The way in which errors are handled affects the software's ability to meet requirements related to correctness, robustness, and other nonfunctional attributes. Deciding on a general approach to bad parameters is an architectural or high-level design decision and should be addressed at one of those levels.
you use the test only once, you might not think it's worthwhile to put it into a routine. But putting the test into a well-named function improves readability and makes it easier for you to see what your code is doing, and that's a sufficient reason to do it.
Table 19-2. Techniques for Counting the Decision Points in a Routine Start with 1 for the straight path through the routine. 2. Add 1 for each of the following keywords, or their equivalents: if while repeat for and or 3. Add 1 for each case in a case statement.
After you have counted the decision points, you can use the number to analyze your routine's complexity: 0–5 The routine is probably fine. 6–10 Start to think about ways to simplify the routine. 10+ Break part of the routine into a second routine and call it from the first routine.
Moving part of a routine into another routine doesn't reduce the overall complexity of the program; it just moves the decision points around. But it reduces the amount of complexity you have to deal with at any one time. Since the important goal is to minimize the number of items you have to juggle mentally, reducing the complexity of a given routine is worthwhile.
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
Put one class in one file. A
Comments should say things about the code that the code can't say about itself—at the summary level or the intent level.