Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan Lead...

29
Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan http://www.nicholasvaidyanathan.info Lead Visionary, Visionary Software Solutions http://www.visionarysoftwaresolutions.com

Transcript of Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan Lead...

Page 1: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Software Engineering Reading Group: Clean CodeChapter 3

Led by Nicholas Vaidyanathanhttp://www.nicholasvaidyanathan.infoLead Visionary, Visionary Software Solutionshttp://www.visionarysoftwaresolutions.com

Page 2: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Functions matterCan you understand in 3

minutes?

Page 3: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

How about this?

Page 4: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Small!“The first rule of functions is that they should

be small.”“The second rule of functions is that they

should be smaller than that.”“Functions should not be 100 lines long.

Functions should hardly ever be 20 lines long.”Beck’s Sparkle

◦ “I was used to functions in Swing programs that took up miles of vertical space. Every function in this program was just two, or three, or four lines long. Each was transparently obvious. Each told a story. And each led you to the next in a compelling order. That’s how short your functions should be!3”

Page 5: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Blocks and IndentingThis implies that the blocks within if

statements, else statements, while statements, and so on should be one line long. Probably that line should be a function call.

This also implies that functions should not be large enough to hold nested structures.

Therefore, the indent level of a function should not be greater than one or two.

Page 6: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Do One ThingFUNCTIONS SHOULD DO ONE THING. THEY

SHOULD DO IT WELL. THEY SHOULD DO IT ONLY.

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.

Another way to know that a function is doing more than “one thing” is if you can extract another function from it with a name that is not merely a restatement of its implementation [G34].

Functions that do one thing cannot be reasonably divided into sections.

Page 7: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

One Level of Abstraction per FunctionIn 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.

Mixing levels of abstraction within a function is always confusing. ◦Readers may not be able to tell whether a

particular expression is an essential concept or a detail.

◦ like broken windows, once details are mixed with essential concepts, more and more details tend to accrete within the function.

Page 8: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

The Stepdown RuleWe want the code to read like a top-down narrativewe 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.◦ To include the setups and teardowns, we include setups,

then we include the test page content, and then we include the teardowns.

◦ To include the setups, we include the suite setup if this is a suite, then we include the regular setup.

◦ To include the suite setup, we search the parent hierarchy for the “SuiteSetUp” page and add an include statement with the path of that page.

◦ To search the parent. . .

Page 9: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Switch StatementsCan be hard to readDo N things by nature

Page 10: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Poor Payroll

Large, multiple reasons for change Does more than 1 thing Violates Single Responsibility Principle Violates Open-Closed Principle Opens door for even worse!

◦ isPayday(Employee e, Date date)◦ deliverPay(Employee e, Money pay)

Page 11: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Bury Switch with OOPUse Abstract Factory that delegates

to Employee instances through polymorphism

My general rule for switch statements is that they can be tolerated if they appear only once, are used to create polymorphic objects, and are hidden behind an inheritance relationship so that the rest of the system can’t see them [G23].

Page 12: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Better Payroll

Page 13: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Use Descriptive NamesRemember Ward’s principle: “You know you

are working on clean code when each routine turns out to be pretty much what you expected.”

Don’t be afraid to make a name long. A long descriptive name is better than a short enigmatic name.◦A long descriptive name is better than a long

descriptive comment.Choosing descriptive names will clarify the

design of the module in your mind and help you to improve it.

Be consistent in your names.

Page 14: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Function Arguments Ideal Number of arguments for a function is 0

(niladic)Next comes monadic (1), followed closely by

dyadic (2)Triadic (3) should be avoided whenever possiblePolyadic (3+) requires justification…and really

shouldn’t be doneArguments take a lot of conceptual power

◦ They may mix abstractionsArguments are hard to test

◦ Combinatorial explosion of values for inputsOutput arguments are harder to understand than

input arguments.

Page 15: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Common monadic formsCommon reasons to pass an argument

◦Ask a question about it boolean fileExists(“MyFile”)

◦Transformation and return InputStream fileOpen(“MyFile”)

transforms a file name String into an InputStream return value.

◦Event void passwordAttemptFailedNtimes(int attempts) Use with care. It should be very clear to the reader this is an

event

◦Try to avoid any monadic functions that don’t follow these forms, for example

Page 16: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Monadic mistakesvoid includeSetupPageInto(StringBuffer pageText)

StringBuffer transform(StringBuffer in) > void transform(StringBuffer out)

Page 17: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Flag Arguments Flag arguments are ugly.

◦ Passing a boolean into a function is a truly terrible practice.

Complicates the signature of a method, and loudly proclaims the function does more than 1 thing!

Page 18: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Dyadic FunctionswriteField(name) > writeField(output-Stream,

name)◦ First is easily parsed, second takes a moment

until we figure out to ignore the first parameterBut we shouldn’t have code that we ignore!Two arguments make better sense in

makePoint(int x, int Y)◦ Ordered components of a single value!

Even obvious dyadic functions like assertEquals(expected, actual) are problematic.◦ Must memorize the parameter order, since there

is no natural ordering

Page 19: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

TriadsWorse than dyadsIt’s likely that you should use an

Argument Object◦When groups of variables are passed

together, the way x and y are in the example above, they are likely part of a concept that deserves a name of its own.

Page 20: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Verbs and KeywordsChoosing good names for a

function can help mitigate parameter ordering issues

In the case of a monad, the function and argument should form a very nice verb/noun pair.◦write(name) writeField(name)

writeField() is a keyword form of a function name, it encodes the name of arguments into the function name

Page 21: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Have no Side EffectsSide effects are LIES

◦Your function promises to do one thing, but also does other hidden things

Side effects create temporal couplings which are confusing and often the source of bugs

Page 22: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

What’s Wrong here?

Page 23: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Output ArgumentsappendFooter(s);

◦Does this function append s as the footer to something?

◦Or does it append some footer to s? Is s an input or an output?

Anything that forces you to check the function signature is equivalent to a double-take. It’s a cognitive break and should be avoided.

much of the need for output arguments disappears in OO languages because this is intended to act as an output argument.

Page 24: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Command Query SeparationFunctions should either do

something or answer something, but not both.◦Either your function should change

the state of an object, or it should return some information about that object.

◦Doing both often leads to confusion.

Page 25: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Separate!public boolean set(String attribute, String value);

if (set("username", "unclebob"))...◦Is it asking whether the “username”

attribute was previously set to “unclebob”?

◦is it asking whether the “username” attribute was successfully set to “unclebob”?

Page 26: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Prefer Exceptions to returning Error CodesReturning error codes is a subtle

violation of Command Query Separation◦Promotes commands being used as

predicates in if statements, leading to deep nesting

Extract try/catch blocks

Error Handling is One Thing

Page 27: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Don’t Repeat YourselfDuplication is a problem

◦Requires modification in multiple places on changes..lots of opportunity for error

Duplication may be the root of all evil in software. ◦Many principles and practices have

been created for the purpose of controlling or eliminating it.

Page 28: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

Structured ProgrammingEdsger Djikstra Rules

◦Every function and every block within a function should have one entry and one exit

◦Only 1 return statement◦No break or continue in loops◦Never any gotos

Page 29: Software Engineering Reading Group: Clean Code Chapter 3 Led by Nicholas Vaidyanathan  Lead Visionary, Visionary Software.

How Do You Write Functions Like This?Writing software is like any other

kind of writing◦When you write a paper or an

article,you get your thoughts down first, then you massage it until it reads well.

◦Refactor, Refactor, Refactor!◦But write Unit Tests that stress the

original first, and keep them passing!