Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
226 views

Clean Code Basic Principles

Clean Code Basic Principles

Uploaded by

Marko
Copyright
© © All Rights Reserved
Available Formats
Download as RTF, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
226 views

Clean Code Basic Principles

Clean Code Basic Principles

Uploaded by

Marko
Copyright
© © All Rights Reserved
Available Formats
Download as RTF, PDF, TXT or read online on Scribd
You are on page 1/ 29

1) Why we need Clean Code (Because of software mainteance)

· Bad Code (example of some app that is discontiunied because of non-clean code)

· LeBlanc's rule (says 'Later equals never')

· Total Cost of Owning a mess

· Graph of Productivity vs Time

'As productivity decreases, management does the only thing they can, they add more staff to the
project in hopes of increasing productivity. But that new staff is not versed in the design of the system.'

Redesign of project (New tiger team for creating new software design, and old team for mainteniance
old design while new design reaches the abilities of old one)

'You will not make the deadline by making the mess.' -> 'The only way to make the deadline and zhe only
way is to go fast is to keep the code as clean as possible at all times'

Code-sense

What is clean code (elegant, efficient, clean code does one thing well, readability, crisp abstraction,
literate, care, meaningful names, expressiveness)

Boy Scout Rule (says 'Leave the campground cleaner than you found it.')

2) Good names (Use Intention-Revealing Names, Avoid Disinformation, Make Meaningful Distinctions,
Use Pronounceable Names, Use Searchable Names, Avoid Encodings, Avoid Mental Mapping, Use
Solution and Problem Domain Names, Don't Add Gratuitous Context)

Use Intention-Revealing Names:

· The problem isn’t the simplicity of the code but the implicity of the code. We want to know
more information from source code (we want explicite code)...

Avoid disinformation:

· We need to avoid names such as (hp, six , sco etc.) beacuse they are the names of Unix platforms
or variants.

· Even if you are coding a hypotenuse and 'hp' looks like a good abbreviation, it could be
disinformative because it can have two meanings.

· Do not refer to a grouping of accounts as an accountList unless it’s actually a List.

· Beware of using names which vary in small ways


· Spelling similar concepts similarly is information. Using inconsistent spellings is dis-information.

· A truly awful example of disinformative names would be the use of lower-case L or uppercase O
as variable names, especially in combination. The problem, of course, is thatthey look almost
entirely like the constants one and zero, respectively

Make Meaningful Distinctions (Učinite značajne razlike) :

· Programmers create problems for themselves when they write code solely to satisfy a compiler
or interpreter (programmer ignores potential warnings)

· Use Pronounceable Names (don't use x1, x2, x3... because these names doesn't have any
information)

· Don't use similar meaning words such as ProductInfo and ProductData, because if we want to
instance an Object, we will not know what we exactly want to instance without looking at the
code in class files. Also this can be applied on methods.

· Noise words are redundant (Ex. we don't name variable nameString, numberInt, ..., instead use
name, number ...)

Use Pronounceable Names:

· Humans are good at words. A significant part of our brains is dedicated to the concept of words.
And words are, by definition, pronounceable. So, you need to use pronounceable words

· Programming is a social activity (not only YOU work on projects!)

Use Searchable Names:

· Single-letter names and numeric constants have a particular problem in that they are noteasy to
locate across a body of text

· Likewise, the name 'e' is a poor choice for any variable for which a programmer might need to
search. It is the most common letter in the English language and likely to show upin every
passage of text in every program. In this regard, longer names trump shorter names, and
any searchable name trumps a constant in code.

· If a variable or constant might be seen or used in multiple places in a body of code,it is


imperative to give it a search-friendly name.

Avoid encodings:

· We have enough encodings to deal with without adding more to our burden.

· Encoding type or scope information into names simply adds an extra burden of deciphering
· It hardly seems reasonable to require each new employee to learn yet another encoding
“language” in addition to learning the (usually considerable) body of code that they’ll be working
in.

· It is an unnecessary mental burden when trying to solve a problem. Encoded namesare seldom
pronounceable and are easy to mistype.

· Java programmers don’t need type encoding. Objects are strongly typed, and editing
environments have advanced such that they detect a type error long before you can run a
compile!

· You also don’t need to prefix member variables with m_ anymore,

· Besides, people quickly learn to ignore the prefix (or suffix) to see the meaningful part of the
name.

· The more we read the code, the less we see the prefixes.

Avoid Mental Mapping:

· Readers shouldn’t have to mentally translate your names into other names they already know.

· This problem generally arises from a choice to use neither problem domain terms nor solution
domain terms.

· This is a problem with single-letter variable names (except i, j and k for loop counters)

· It’s just a placeholder that the reader must mentally map to the actual concept.

· There can be no worse reason for using the name 'c' than because 'a' and 'b' were already taken

· In general programmers are pretty smart people. Smart people sometimes like to show off their
smarts by demonstrating their mental juggling abilities.

· One difference between a smart programmer and a professional programmer is that the
professional understands that clarity is king. Professionals use their powers for good and write
code that others can understand.

Class Names:

· Class names always should be start with capitalised letter and have noun or noun phrase names
like (such as Customer, Vehicle ...)

· Avoid Class names like Manager, Processor, Data, or Info in the name of a class.

· A class name should not be a verb (glagol)


Method Names:

· Methods should have verb or verb phrase names (like postPayment, deletePage, or save)

· Accessors, mutators, and predicates should be named for their value and prefixed with get, set,
and is according to the javabean standard

· Say what you mean. Mean what you say (don't use names such as holyShit(), dumbSpace(), also
this paradigm applies anywhere in clean code)

Pick One Word per Concept:

· For instance, it’s confusing to have fetch, retrieve, and get as equivalent methods of different
classes.

· A consistent lexicon is a great boon to the programmers who must use your code.

Don't pun:

· Avoid using the same word for two purposes

· Using the same term for two different ideasis essentially a pun.

· If you follow the “one word per concept” rule, you could end up with many classes that have, for
example, an add method. As long as the parameter lists and return values of the various add
methods are semantically equivalent, all is well.

· Our goal, as authors, is to make our code as easy as possible to understand.

· We want our code to be a quick skim, not an intense study.

· We want to use the popular paperback model where by the author is responsible for making
himself clear and not the academic model where it is the scholar’s job to dig the meaning out of
the paper

Use Solution and Problem Domain Names:

· Remember that the people who read your code will be programmers.

· So go ahead and use computer science (CS) terms, algorithm names, pattern names, math
terms, and so forth.

· Choosing technical names forthose things is usually the most appropriate course

· Separating solution and problem domain concepts is part of the job of a good pro-grammer and
designer.
· The code that has more to do with problem domain concepts should have names drawn from
the problem domain.

Add Meaningful Context:

· There are a few names which are meaningful in and of themselves—most are not.

· Instead, you need to place names in context for your reader by enclosing them in well-named
classes, functions, or namespaces.

· Example of this is if we have variables named lastName, we can rename it with addLastName if
we have add or remove class

· Unfortunately, the context must be inferred.

· The improvement of context also allowsthe algorithm to be made much cleaner by breaking it
into many smaller functions

Don't Add Gratuitous Context:

· In an imaginary application called “Gas Station Deluxe,” it is a bad idea to prefix every class
with GSD.

· Shorter names are generally better than longer ones, so long as they are clear. Add no more
context to a name than is necessary.

· The names accountAddress and customerAddress are fine names for instances of the
classAddress, but could be poor names for classes

· Address is a fine name for a class

Final words:

· The hardest thing about choosing good names is that it requires good descriptive skills and a
shared cultural background.

· This is a teaching issue rather than a technical, business, or management issue.

· As a result many people in this field don’t learn to do it very well

· If you are maintaining someone else’s code, use refactoring tools to help resolve these problems.
It will pay off in the short term and continue to pay in the long run

3) Functions (Needs to be small, Do One Thing, Sections within Functions, One Level of Abstraction per
Function, Reading Code from Top to Bottom, Use Descriptive Names, Avoid using Function Arguments,
Avoid using Flag Arguments, Use good Verbs and Keywords, Have No Side Effects, We need to prefer
using Exceptions than Error codes, Don't Repeat Yourself - DRY, Structured Programming)

· Functions arethe first line of organization in any program. Writing them well is the topic of this
chapter.

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.

· In the eighties we used to say that a function should be no bigger than a screen-full.

Blocks and Indenting:

· This 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.

· The indent level of a function should not be greater than one or two.

· This, of course, makes the functions easier to read and understand

Do One Thing:

· Functions should do one thing and they should do it well and they should do it only

· One level of abstraction per Function

· After all, the reason we write functions is to decompose a larger concept (in other words, the
name of the function) into a set of steps at the next level of abstraction

· So, 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

Sections within Functions:

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

One Level of Abstraction per Function:

· 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.

· 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

Reading Code from Top to Bottom (also known as 'The Stepdown Rule'):

· We want the code to read like a top-down narrative.

· We want every function to be followed by those at the next level of abstraction, so that we can
read the program, descend ingone level of abstraction at a time as we read down the list of
functions.

· To say this differently, 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.

· It turns out to be very difficult for programmers to learn to follow this rule and write functions
that stay at a single level of abstraction.

· But learning this trick is also very important.

· It is the key to keeping functions short and making sure they do “one thing.”

· Making the code read like a top-down set of TO paragraphs is an effective technique for keeping
the abstraction level consistent.

Switch Statements:

· It’s hard to make a small switch statement.

· Even a switch statement with only two cases is larger than I’d like a single block or function to be

· It’s also hard to make a switch statement that does one thing

· By their nature, switch statements always do N things.

· Unfortunately we can’t always avoid switch statements, but we can make sure that each switch
statement is buried in a low-level class and is never repeated.

· We do this, of course, with polymorphism.

· To avoid using Switch, we can use Abstraction and interface

· 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
· Of course every circumstance is unique, and there are times when I violate one or more parts of
that rule

Use Descriptive Names:

· We need to describe what function and variables does

· It is hard to overestimate the valueof good names.

· Ward's principle says 'You know you are working on clean code when each routine turns out to
be pretty much what you expected'

· Half the battle to achieving that principle is choosing good names for small functions that do one
thing (the smaller and more focused a function is, the easier it is to choose a descriptive name)

· Don’t be afraid to make a name long (long descriptive name is better than a shortenigmatic
name)

· A long descriptive name is better than a long descriptive comment(s)

· Usea naming convention that allows multiple words to be easily read in the function names, and
then make use of those multiple words to give the function a name that says what it does

· Don’t be afraid to spend time choosing a name. Indeed, you should try several different names
and read the code with each in place.

· Choosing descriptive names will clarify the design of the module in your mind and help you to
improve it.

· Be consistent in your names (Use the same phrases, nouns, and verbs in the function names you
choose for your modules)

Function Arguments (Function Parameters):

· The ideal number of arguments for a function is zero (niladic)

· Next comes one (monadic), followed closely by two (dyadic).

· Three arguments (triadic) should be avoided where possible.

· More than three (polyadic) requires very special justification and then shouldn’t be used anyway

· Arguments are even harder from a testing point of view

· Output arguments are harder to understand than input arguments (because the output
arguments often cause us to do a double-take)
Common Monadic Forms:

· 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
beoperating on that argument, transforming it into something else and returning it

· A somewhat less common, but still very useful form for a single argument function, is an event

· Try to avoid any monadic functions that don’t follow these forms, for example, void
includeSetupPageInto(StringBuffer pageText).

· Using an output argument instead of a return value for a transformation is very confusing

· Flag arguments (passing boolean as parameter) 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!

· We need to split the function into two: ifTrue() and ifFalse()

Dyadic Functions:

· A function with two arguments is harder to understand than a monadic function.

· The two arguments have no natural ordering. The expected, actual ordering is a convention that
requires practice to learn

· Dyads aren’t evil, and you will certainly have to write them. However, you should be aware that
they come at a cost and should take advantage of what mechanims may be available to you to
convert them into monads.

Triads Functions:

· Functions that take three arguments are significantly harder to understand than dyads.

· The issues of ordering, pausing, and ignoring are more than doubled.

Argument Objects:

· When a function seems to need more than two or three arguments, it is likely that some of
those arguments needs to be wrapped into a class of their own

· Reducing the number of arguments by creating objects out of them may seem like cheating, but
it’s not.

· 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.

Argument Lists

· String.format(regex, Object)

· If the variable arguments are all treated identically, as they are in the example above, then they
are equivalent to a single argument of type List.

Verbs and Keywords:

· Choosing good names for a function can go a long way toward explaining the intent of the
function and the order and intent of the arguments.

Have No Side Effects:

· Side effects are lies. Your function promises to do one thing, but it also does other hidden things
(ex. calling of initializeForm after login validation in same function)

· This can be resulted in data loss

Output Arguments:

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

· If your function must change the stateof something, have it change the state of its owning
object.

Command Query Separation:

· Functions should either do something or answer something, but not both.

· Example of this problem is if(set("name", "pasword")). What is 'set' means there?

· The real solution is to separate the command from the query so that the ambiguity cannot occur.

Prefer Exceptions to Returning Error Codes:

· Returning error codes from command functions is a subtle violation of command query
separation.

· This does not suffer from verb/adjective confusion, but does lead to deeply nested structures.
· When you return an error code, you create the problem that the caller must deal with the error
immediately.

· On the other hand, if you use exceptions instead of returned error codes, then the error
processing code can be separated from the happy path code

Extract Try/Catch Blocks:

· Try/Catch blocks are ugly in their own right.

· They confuse the structure of the code and mix error processing with normal processing, so it is
better to extract the bodies of the Try/Catch blocks out into functions of their own.

· In the above, the delete function is all about error processing (it is easy to understand and then
ignore)

· Error handling can be ignored. This provides a nice separation that makes the code easier to
understand and modify

Error Handling Is One Thing:

· Error handing is one thing. This, 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.

The Error.java Dependency Magnet:

· Returning error codes usually implies that there is some class or enum in which all the error
codes are defined.

· Classes like this are a dependency magnet (many other classes must import and use them).

· This, when the Errorn enum changes, all those other classes need to be recompiled and
redeployed.

· Programmers don't want to add new errors because then they have to rebuild and redeploy
everything, so they reuseold error codes instead of adding new ones

· 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.

Don't Repeat Yourself:

· It’s not easy to spot duplication with other code and aren’t uniformly duplicated.
· Still, the duplication is a problem because it bloats the code.

· 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
(such as Object Oriented Programming).

Structured Programming:

· Some programmers follow Edsger Dijkstra’s rules of structured programming.

· Dijkstra said that every function, and every block within a function, should have one entry and
one exit.

· Following these rules means that there should only be one return statement in a function, no
break or continue statements in a loop, and never, ever, any goto statements.

· It is only in larger functions that such rules provide significant benefit.

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).

· The first draft might be clumsy and disorganized, so you wordsmith it and restructure it and
refine it until it reads the way you want it to read.

· In the end, I wind up with functions that follow the rules I’ve laid down in this chapter.I don’t
write them that way to start. I don’t think anyone could.

Conclusion:

· Functions are the verbs of that language, and classes are the nouns.

· This is not some throwback to the hideous old notion that the nouns and verbs in a
requirements document are the first guess of the classes and functions of a system. Rather, this
is a much older truth.

· The art of programming is, and has always been, the art of language design.

· This chapter has been about the mechanics of writing functions well.

· If you follow the rules here in, your functions will be short, well named, and nicely organized.
But never forget that your real goal is to tell the story of the system, and that the functions you
write need to fit cleanly together into a clear and precise language to help you with that telling.

4) Comments (Comments Do Not Make Up for Bad Code):


· Nothing can be quite so helpful as a well-placed comment

· Comments are not like Schindler’s List. They are not “pure good.” Indeed, comments are, at best,
a necessary evil

· The proper use of comments is to compensate for our failure to express ourself in code.

· Comments are always failures. We must have them because we cannot always figure out how to
express ourselves without them, but their use is not a cause for celebration

· Unfortunately the comments don’t always follow them— can’t always follow them, because of
code changing and envolving.

· Inaccurate comments are far worse than no comments at all. They delude and mislead.

· They set expectations that will never be fulfilled (they lay down old rules that need not, orshould
not, be followed any longer)

· Truth can only be found in one place and that place is the code. Only the code can truly tell you
what it does.

Comments Do Not Make Up for Bad Code:

· One of the more common motivations for writing comments is bad code.

· We write a module and we know it is confusing and disorganized and we know it’s a mess, so we
say to ourselves, “Oh, I’d better comment that!”, No, you’d better to clean it!

· Clear and expressive code with few comments is far superior to cluttered and complex code with
lots of comments.

· Rather than spend your time writing the comments that explain the mess you’ve made, spend it
cleaning that mess.

· Don't Use a Comment When You Can Use a Function or a Variable

Explain Yourself in Code:

· In many cases it’s simply a matter of creating a function that says the same thing as the
commentyou want to write

Good Comments (Legal Comments, Informative Comments, Explanation of Intent Comments,


Clarification Comments, Warning of Consequences Comments, TODO Comments, Amplification
Comments, Javadoc API Comments):

· Some comments are necessary or beneficial.


· Keep in mind, however, that the only truly good comment is the comment you found a way not
to write.

Legal Comments:

· Copyright and authorship statements are necessary and reasonable things to put into a
comment at the start of each source file.

· Comments like this should not be contracts or legal tomes (about not to 100 lines or more ...)

· Where possible, refer to a standard license or other external document rather than putting all
the terms and conditions into the comment

Informative Comments:

· It is sometimes useful to provide basic information with a comment, but in most scenarions it is
better to use good names or create a classes or methods

Explanation of Intent Comments (Objašnjava nameru kako je zamišljeno ili zašto to radi):

· Sometimes a comment goes beyond just useful information about the implementation and
provides the intent behind a decision.

Clarification (Razjašnjavajući) Comments:

· Sometimes it is just helpful to translate the meaning of some obscure argument or return value
into something that’s readable (in general it is better to find a way to make that argument or
return value clear in its own right), but when its part of the standard library (or in code that you
cannot alter), then a helpful clarifying comment can be useful

· There is a substantial risk, of course, that a clarifying comment can be incorrect.

· This explains both why the clarification is necessary and why it’s risky.

· So before writing comments like this, take care that there is no better way, and then take even
more care that they are accurate.

Warning of Consequences (Upozorenje na posledice) Comments:

· Sometimes it is useful to warn other programmers about certain consequences.

· Nowadays, of course, we’d turn off the test case by using the @Ignore attribute with
anappropriate explanatory string.

TODO Comments:

· It is sometimes reasonable to leave “To do” notes in the form of //TODOcomments.


· In the following case, the TODO comment explains why and what that function’s future should
be.

· TODOs are jobs that the programmer thinks should be done, but for some reason can’t do at the
moment

· It might be a reminder to delete a deprecated feature or aplea for someone else to look at a
problem.

· Whatever else a TODO might be, it is not an excuse to leave bad code in the system.

· Nowadays, most good IDEs provide special gestures and features to locate all the TODO
comments, so it’s not likely that they will get lost.

Amplification Comments:

· A comment may be used to amplify the importance of something that may otherwise seem
inconsequential.

Javadocs in Public APIs:

· There is nothing quite so helpful and satisfying as a well-described public API.

· If you are writing a public API, then you should certainly write good javadocs for it, but keep in
mind the rest of the advice in this chapter.

Bad Comments (Mumbling, Redundant Comments, Misleading Comments, Mandated Comments,


Journal Comments, Noise Comments, Position Markers in Comments, Closing Brace Comments,
Attributions and Bylines Comments, Commented-Out Code, Nonlocal Information Comments, Too Much
Information Comments, Inobvious Connection Comments):

· Most comments fall into this category. Usually they are crutches or excuses for poor code or
justifications for insufficient decisions, amounting to little more than the programmer talking to
himself.

Mumbling:

· Plopping in a comment just because you feel you should or because the process requires it,is a
hack. If you decide to write a comment, then spend the time necessary to make sure itis the best
comment you can write.

· Any comment that forces you to look in another module for the meaning of that comment has
failed to communicate to you and is not worth the bits it consumes.

Redundant (Suvišni) Comments:


· Indeed, it is less precise than the code and entices the reader to accept that lack of precision in
lie you of true understanding

Misleading (Obmanjujući) Comments:

· Sometimes, with all the best intentions, a programmer makes a statement in his comments that
isn’t precise enough to be accurate. And this can make very big problems when other
programmer wants to use this peace of code

Mandated (Zvaničan redosled) Comments:

· It is just plain silly to have a rule that says that every function must have a javadoc, or every
variable must have a comment

· Comments like this just clutter up the code, propagate lies, and lend to general confusion and
disorganization

· This clutter adds nothing and serves only to obfuscate the code and create the potential for lies
and misdirection

Journal Comments:

· Sometimes people add a comment to the start of a module every time they edit it.

· These comments accumulate as a kind of journal, or log, of every change that has ever been
made.

· I have seen some modules with dozens of pages of these run-on journal entries.

· Long ago there was a good reason to create and maintain these log entries at the start of every
module.

· We didn’t have source code control systems that did it for us.

· Nowadays, however, these long journals are just more clutter to obfuscate the module and they
should be completely removed.

Noise Comments:

· Sometimes you see comments that are nothing but noise (such as 'give me a break').

· They restate the obvious and provide no new information.

· These comments are so noisy that we learn to ignore them.

· As we read through code, our eyes simply skip over them, eventually the comments begin to lie
as the code around them changes.
· Rather than venting in a worthless and noisy comment, the programmer should have recognized
that his frustration could be resolved by improving the structure of his code.

· Javadocs can also be noisy. What purpose do the following Javadocs (from a well-known open-
source library) serve? Answer: nothing.

· They are just redundant noisy comments written out of some misplaced desire to provide
documentation.

Position Markers (Ex. '/////////CODE/////////'):

· Sometimes programmers like to mark a particular position in a source file.

· There are rare times when it makes sense to gather certain functions together beneath a banner
like this, but in general they are clutter that should be eliminated — especially the noisy train of
slashes at the end.

· Think of it this way. A banner is startling and obvious if you don’t see banners very often, so use
them very sparingly, and only when the benefit is significant.

· If you over use banners, they’ll fall into the background noise and be ignored.

Closing Brace Comments:

· Sometimes programmers will put special comments on closing braces

· Although this might make sense for long functions with deeply nested structures, it serves only
to clutter the kind of small and encapsulated functions that we prefer

· So if you find yourself wanting to mark your closing braces, try to shorten your functions instead.

Attributions and Bylines Comments:

· Source code control systems are very good at remembering who added what and when.

· There is no need to pollute (zagaditi) the code with little bylines.

· You might think that such comments would be useful in order to help others know who to talk to
about the code, but the reality is that they tend to stay around for years and years, getting less
and less accurateand relevant.

Commented-Out Code:

· Few practices are as odious as commenting-out code. Don’t do this!

· Others who see that commented-out code won’t have the courage to delete it.
· They’ll think it is there for a reason and is too important to delete.

· So commented-out code gathers like dregs (talog) at the bottom of a bad bottle of wine.

· There was a time, back in the sixties, when commenting-out code might have been useful.

· But we’ve had good source code control systems for a very long time now.

· Those systems will remember the code for us. We don’t have to comment it out any more. Just
delete the code. We won’t lose it. Promise.

HTML Comments:

· HTML in source code comments is an abomination, as you can tell by reading the code below.

· It makes the comments hard to read in the one place where they should be easy to read — the
editor/IDE

· Nonlocal Information Comments

Nonlocal Information Comments:

· If you must write a comment, then make sure it describes the code it appears near.

· Don’t offer system-wide information in the context of a local comment.

Too Much Information Comments:

· Don’t put interesting historical discussion or irrelevant descriptions of details into your
comments.

Inobvious Connection Comments:

· The connection between a comment and the code it describes should be obvious.

· If you are going to the trouble to write a comment, then at least you’d like the reader to be able
to look at the comment and the code and understand what the comment is talking about.

· The purpose of a comment is to explain code that does not explain itself. It is a pity when a
comment needs its own explanation.

Function Headers:

· Short functions don’t need much description.

· A well-chosen name for a small function that does one thing is usually better than a comment
header.
Function Headers:

· As useful as javadocs are for public APIs, they are anathema to code that is not intended for
public consumption.

· Generating javadoc pages for the classes and functions inside a system is not generally useful,
and the extra formality of the javadoc comments amountsto little more than cruft and
distraction.

5) Formatting:

· When people look under the hood, we want them to be impressed with the neatness,
consistency, and attention to detail that they perceive.

· We want them to be struck by the orderlines.

· We want their eyebrows to rise as they scroll through the modules.

· We want them to perceive that professionals have been at work.

· If instead they see a scrambled mass of code that looks like it was written by a bevy of drunken
sailors, then they are likely to conclude that the same in attention to detail pervades every other
aspect of the project

· You should take care that your code is nicely formatted.

· You should choose a set of simple rules that govern the format of your code, and then you
should consistently apply those rules.

· If you are working on a team, then the team should agree to a single set of formatting rules and
all members should comply (it helps to have an automated tool that can apply those formatting
rules for you).

The Purpose of Formatting:

· Code formatting is important. It is too important to ignore and it is too important to treat
religiously.

· Code formatting is about communication, and communication is the professional developer’s


first order of business.

· The functionality that you create today has a good chance of changing in the next release, but
the readability of your code will have a profound effect on all the change sthat will ever be
made.

· The coding style and readability set precedents that continue to affect maintainability and
extensibility long after the original code has been changed beyond recognition.

· Your style and discipline survives, even though your code does not

Vertical Formatting:

· It appears to be possible to build significant systems (FitNesse project is close to 50,000 lines)
out of files that are typically 200 lines long, with an upper limit of 500.

· Although this should not be a hard and fast rule, it should be consideredvery desirable.

· Small files are usually easier to understand than large files are.

The Newspaper Metaphor:

· Think of a well-written newspaper article. You read it vertically. At the top you expect a headline
that will tell you what the story is about and allows you to decide whether it is something you
want to read.

· The first paragraph gives you a synopsis of the whole story, hiding all the details while giving you
the broad-brush concepts. As you continue down-ward, the details increase until you have all
the dates, names, quotes, claims and others

· We would like a source file to be like a newspaper article. The name should be simple, but
explanatory.

· The name, by itself, should be sufficient to tell us whether we are in the right module or not.

· The topmost parts of the source file should provide the high-level concepts and algorithms.
Detail should increase as we move downward, until at the end we find the lowest level functions
and details in the source file.

Vertical Openness Between Concepts (Empty line between two methods and classes):

· Nearly all code is read left to right and top to bottom. Each line represents an expression ora
clause, and each group of lines represents a complete thought.

· Those thoughts should be separated from each other with blank lines

· This extremely simple rule has a profound effect on the visual layout of the code.

· Each blank line is a visual cue that identifies a new and separate concept

Vertical Density:

· If openness separates concepts, then vertical density implies close association. So lines of code
that are tightly related should appear vertically dense (zbijen) and we need more head and eye
focus to achieve code.

Vertical Distance:

· Concepts that are closely related should be kept vertically close to each other

· Clearly this rule doesn’t work for concepts that belong in separate files, but then closely related
concepts should not be separated into different files unless you have a very good reason.

· Indeed, this is one of the reasons that protected variables should be avoided.

Variable Declarations:

· Variables should be declared as close to their usage as possible.

· Control variables for loops should usually be declared within the loop statement

· In rare cases a variable might be declared at the top of a block or just before a loop in a long-ish
function.

Instance Variables:

· Should be declared at the top of the class.

· This should not increase the vertical distance of these variables, because in a well-designed
class, they are used by many, if not all, of the methods of the class

· The important thing is for the instance variables to be declared in one well-known place and
everybody will should know where to go to see the declarations.

Dependent Functions:

· If one function calls another, they should be vertically close, and the caller should be above the
called, if at all possible.

· This gives the program a natural flow. If the convention is followed reliably, readers will be able
to trust that function definitions will follow shortly after their use.

· It was better to pass that constant down from the place where it makes sense to know it to the
place that actually uses it

Conceptual Affinity:

· The stronger that affinity (veza), the less vertical distance there should be between them

· As we hav seen, this affinity might be based on a direct dependence, such as one function
calling another, or a function using a variable, but there are other possible causes of affinity.
· Affinity might be caused because a group of functions perform a similar operation.

Vertical Ordering:

· In general we want function call dependencies to point in the downward direction.

· That is, a function that is called should be below a function that does the calling.

· This creates a nice flow down the source code module from high level to low level.

· As in newspaper articles, we expect the most important concepts to come first, and we expect
them to be expressed with the least amount of polluting detail and we expect the low-level
details to come last.

Horizontal Formatting:

· How wide should a line be? - It should not be longer than 80-120 characters per line

· Programmers clearly prefer short lines and this suggests that we should strive to keep our lines
short.

· I used to follow the rule that you should never have to scroll to the right, but monitors are too
wide for that nowadays, and younger programmers can shrink the font so small that they can
get 200 characters across the screen. Don’t do that.

Horizontal Openness and Density:

· We use horizontal white space to associate things that are strongly related and disassociate
things that are more weakly related.

· I surrounded the assignment operators with white space to accentuate them.

· Assignment statements have two distinct and major elements: the left side and the right side.
The spaces make that separation obvious (jasnom).

· On the other hand, I didn’t put spaces between the function names and the opening
parenthesis.

· This is because the function and its arguments are closely related. Separating them makes them
appear disjoined instead of conjoined.

· I separate arguments within the function call parenthesis to accentuate the comma and show
that the arguments are separate.

Horizontal Alignment:

· The code should be aligned on left side without unnecessary white spaces
Indentation:

· A source file is a hierarchy rather like an outline.

· There is information that pertains to the file as a whole, to the individual classes within the file,
to the methods within the classes, to the blocks within the methods, and recursively to the
blocks within the blocks.

· Each level of this hierarchy is a scope into which names can be declared and in which
declarations and executable statements are interpreted.

· To make this hierarchy of scopes visible, we indent the lines of source code in pro-portion to
their position in the hiearchy.

· Statements at the level of the file, such as mostclass declarations, are not indented at all.

· Methods within a class are indented one levelto the right of the class.

· Implementations of those methods are implemented one level tothe right of the method
declaration.

· Block implementations are implemented one level to the right of their containing block, and so
on

· Programmers rely heavily on this indentation scheme. They visually line up lines on the left to
see what scope they appear in.

· This allows them to quickly hop over scopes, such as implementations of if or while statements,
that are not relevant to their current situation.

· Your eye can rapidly discern the structure of the indented file.

· You can almost instantly spot the variables, constructors, accessors, and methods.

· It takes just a few seconds to realize that this is some kind of simple front end to a socket, with a
time-out. The unindented version, however, is virtually impenetrable without intense study.

Breaking Indentation:

· It is sometimes tempting to break the indentation rule for short if statements, short while loops,
or short functions. Whenever I have succumbed to this temptation, I have almost always gone
back and put the indentation back in. So I avoid collapsing scopes.

Dummy Scopes:

· Sometimes the body of a while or for statement is a dummy, as shown below. I don’t like these
kinds of structures and try to avoid them.

· When I can’t avoid them, I make sure that the dummy body is properly indented and surrounded
by braces.

Team Rules:

· Every programmer has his own favorite formatting rules, but if he works in a team, then the
'team rules'.

· A team of developers should agree upon a single formatting style, and then every member of
that team should use that style.

· We want the software to have a consistent style. We don’t want it to appear to have been
written by a bunch of disagreeing individuals.

· A good software system is composed of a set of documents that read nicely.

· The reader needs to be able to trust that the formatting gestures he or she has seen in one
source file will mean the same thing in others.

6) Objects and Data Structures (OOP Principles):

· There is a reason that we keep our variables private. We don’t want anyone else to depend on
them.

· Why, then, do so many programmers automatically add getters and setters to their objects,
exposing their private variables as if they were public?

Data Abstraction:

· Hiding implementation (unnecessary details) is about abstractions!

· A class does not simply push its variables out throug getters and setters.

· Rather it exposes abstract interfaces that allow its users to manipulate the essence of the data,
without having to know its implementation.

· We do not want to expose the details of our data.

· Rather we want to express our data in abstract terms.

· This is not merely accomplished by using interfaces and/or getters and setters.

· Serious thought needs to be put into the best way to represent the data that an object contains.

· The worst option is to blithely (improperly) add getters and setters


Inheritance:

· Inheritance is one of the core concepts of object-oriented programming (OOP) languages. It is a


mechanism where you can to derive a class from another class for a hierarchy of classes that
share a set of attributes and methods.

Encapsulation:

· In object oriented computer programming languages, the notion of encapsulation (or OOP
Encapsulation) refers to the bundling of data, along with the methods that operate on that data,
into a single unit.

· Many programming languages use encapsulation frequently in the form of classes

· Encapsulation may also refer to a mechanism of restricting the direct access to some
components of an object, such that users cannot access state values for all of the variables of a
particular object.

· Encapsulation can be used to hide both data members and data functions or methods associated
with an instantiated class or object.

Polymorphism:

· In computer science, it describes the concept that objects of different types can be accessed
through the same interface. Each type can provide its own, independent implementation of this
interface.

· If you’re wondering if an object is polymorphic, you can perform a simple test. If the object
successfully passes multiple is-a or instanceof tests, it’s polymorphic.

· In Java, we have static (compile-time) and dynamic (runtime)

· Static polymorphism - Method overloading (Two same function names with different set of
parameters)

· Dynamic polymorphism - Runtime determing of fuctions, because we have two indentical


functions names with same parameters, and we need to instance that to compiler knows what
we exactly want

Data/Object Anti-Symmetry:

· Objects hide theirdata behindabstractions and expose functions that operate on that data.

· Data structure expose their data and have no meaningful functions

· They are virtual opposites. This difference may seem trivial, but it has far-reaching implications
· Object-oriented programmers might wrinkle (zadići) their noses at this and complain that it is
procedural — and they’d be right, but the sneer may not be warranted.

· Procedural code (code using data structures) makes it easy to add new functions without
changing the existing data structures.

· Object Oriented code, on the other hand, makes it easy to add new classes without changing
existing functions

· Procedural code makes it hard to add new data structures because all the functions must
change.

· Object Oriented code makes it hard to add new functions because all the classes must change

· So, the things that are hard for OOP are easy for procedures, and the things that are hard for
procedures are easy for OOP!

· In any complex system there are going to be times when we want to add new data types rather
than new functions (for these OOP are most appropriate)

· On the other hand, there will also be times when we’ll want to add new functions as opposed to
data types. In that case procedural coding will be more appropriate.

· Mature (zreli) programmers know that the idea that everything is an object is a myth.

· Sometimes you really do want simple data structures with procedures operating on them

The Law of Demeter:

· There is a well-known heuristic called the Law of Demeter that says 'a module should not know
about the innards(unutrašnjost) of the objects it manipulates'

· 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.

Hybrids:

· 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.

· 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, so avoid creating them.

Hiding Structure:

· That seems like a reasonable thing for an object to do!

· This allows variables to hide its internals and prevents the current function from having to
violate the Law of Demeter by navigating through objects it shouldn’t know about

Data Transfer Objects (DTO):

· The quintessential form of a data structure is a class with public variables and no functions.

· This is sometimes called a data transfer object

· Data Transfer Objects are very useful structures, especially when communicating with databases
or parsing messages from sockets, and so on

· They often become the first in a series of translation stages that convert raw data in a database
into objects in the application code.

Active Record:

· Active Records are special forms of Data Transfer Objects,

· They are data structures with public (or bean-accessed) variables, but they typically have
navigational methods like 'save' and 'find'.

· Unfortunately we often find that developers try to treat these data structures as though they
were objects by putting business rule methods in them.

· This is awkward because it creates a hybrid between a data structure and an object.

· The solution, of course, is to treat the Active Record as a data structure and to create separate
objects that contain the business rules and that hide their internal data (which are probably just
instances of the Active Record).

Conclusion:

· 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

7) SOLID Principles:

· In software engineering, SOLID is a mnemonic acronym for five design principles intended to
make software designs more understandable, flexible, and maintainable.

· The principles are a subset of many principles promoted by American software engineer and
instructor Robert C. Martin

· Although the SOLID principles apply to any object-oriented design, they can also form a core
philosophy for methodologies such as agile (agilnom) development or adaptive software
development.

· First principle of SOLID is 'Single Responsibility Principle (SRP)' and that is a computer-
programming principle that states that every module, class or function in a computer program
should have responsibility over only a single part of that program's functionality (do only one
exact thing), and it should encapsulate that part.

· Second principle of SOLID is 'Open Closed Principle (OCP)' and in object-oriented programming,
the open–closed principle states software entities (classes, modules, functions, etc.) should be
open for extension, but closed for modification. That is, such an entity can allow its behaviour to
be extended without modifying its source code

· Third principle of SOLID is 'Liskov Substituon Principle (LSP)' and we should be able to replace
the parent class and the inheriting class and there should be not a problem (in essence, it should
be possible for successor (child class) class lenses to behave like superclass (parent class)
objects)

· Fourth principle of SOLID is 'Interface Segregation Principle (ISP)' and in the field of software
engineering, the interface-segregation principle (ISP) states that no client should be forced to
depend on methods it does not use. ISP splits interfaces that are very large into smaller and
more specific ones so that clients will only have to know about the methods that are of interest
to them. Such shrunken interfaces are also called role interfaces. ISP is intended to keep a
system decoupled and thus easier to refactor, change, and redeploy.

· Fifth principle of SOLID is 'Dependency Inversion Principle (DIP)' and that means the abstraction
should be used instead of concrete implementation because abstraction does not depend on
details, but details depend on abstraction, relieves the application (High-level modules should
not depend on low-level modules. Both should depend on abstractions (e.g., interfaces) and
abstractions should not depend on details. Details (concrete implementations) should depend
on abstractions).
References:

· Robert C. Martin Series - Clean Code (2010)

You might also like