Clean code
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 1
24/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir)
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 3
• Make if hard for bugs to hide
• Clean code does one thing well
• Reads like well-written prose
• obscure the designer’s intent
• Provides one way rather than many ways for doing one thing
• Each routine you read turn out to be pretty much what you expect
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 4
• Clean Programming is some thing like martial art
• Combination of technique and art.
• The Art of Computer Programming by Knuth
• Have different school of thoughts
• Clean Programming is skill
• Good learning results in good use forever
• Changing bad learning is hard
• Like Driving!
Clean code does one thing well
Make it hard for bugs to hide
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 5
Reads like well-written prose
Never obscure the designer’s intent
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 6
Provides one way rather than many
ways for doing one thing
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 7
Each routine you read turn out to be
pretty much what you expect
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 8
4/20/2020
If an object is doing more than one thing, I
break it down into two or more objects.
S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 9
In recent years I begin, and nearly end, with Beck’s rules of
simple code. In priority order, simple code:
• Runs all the tests;
• Contains no duplication;
• Expresses all the design ideas that are in the system;
• Minimizes the number of entities such as classes, methods,
functions, and the like.
Of these, I focus mostly on duplication. When the same thing is
done over and over, it’s a sign that there is an idea in our mind
that is not well represented in the code. I try to figure out what
it is. Then I try to express that idea more clearly.
 Code is clean if it can be understood easily – by everyone on the team.
 With understandability comes readability, changeability, extensibility
and maintainability.
 Clean code can be read and enhanced by a developer other than its
original author.
4/20/2020 10
• Follow standard conventions.
• Keep it simple stupid. Simpler is always better. Reduce complexity as
much as possible.
• Boy scout rule. Leave the campground cleaner than you found it.
• Always find root cause. Always look for the root cause of a problem.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 11
• Keep configurable data at high levels.
• Prefer polymorphism to if/else or switch/case.
• Separate multi-threading code.
• Prevent over-configurability.
• Use dependency injection.
• Follow Law of Demeter. A class should know only its direct
dependencies.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 12
჻ Be consistent. If you do something a certain way, do all similar things in
the same way.
჻ Use explanatory variables.
჻ Encapsulate boundary conditions. Boundary conditions are hard to
keep track of. Put the processing for them in one place.
჻ Prefer dedicated value objects to primitive type.
჻ Avoid logical dependency. Don't write methods which works correctly
depending on something else in the same class.
჻ Avoid negative conditionals.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 13
Use descriptive names
• Choose descriptive and unambiguous
names.
• Make meaningful distinction.
• Use pronounceable names.
• Use searchable names.
• Replace magic numbers with named
constants.
• Avoid encodings. Don't append prefixes
or type information.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 14
Use informative names
• Number-series naming (a1, a2, .. aN) is the
opposite of intentional naming.
• Such names provide no clue to the reader.
• They are noninformative. Consider intent.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 15
public static void copyChars(char a1[], char a2[])
{ for (int i = 0; i < a1.length; i++)
{
a2[i] = a1[i];
}
}
 This function reads much better when source and
destination are used for the argument names.
• If a name is used in multiple places give it a
search-friendly name.
• They are noninformative. Consider intent.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 16
Use searchable names
for (int j=0; j<34; j++) 
{ s += (t[j]*4)/5; }
int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int j=0; j < NUMBER_OF_TASKS; j++)
{
int realTaskDays = taskEstimate[j] *
realDaysPerIdealDay;
int realTaskWeeks = (realdays /
WORK_DAYS_PER_WEEK);
sum += realTaskWeeks;
}
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 17
int d; // elapsed time in days
3. We should choose a name that specifies what is being measured and the
unit of that measurement:
int elapsedTimeInDays;
Int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;
1. The name of a variable, function, or class, should answer all the big
questions. It should tell you why it exists, what it does, and how it is
used.
2. If a name requires a comment, then the name does not reveal its
intent
Use meaningful names
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 18
4. Choosing names that reveal intent can
make it much easier to understand and
change code. What is the purpose of this
code?
public List<int[]> getThem()
{ List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4) list1.add(x);
return list1; }
Use meaningful names -2
• Small.
• Do one thing.
• Use descriptive names.
• Prefer fewer arguments.
• Have no side effects.
• Don't use flag arguments. Split method into
several independent methods that can be
called from the client without the flag.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 19
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 20
 How
‫؞‬ What is it that makes a function easy to read and understand?
‫؞‬ How can we make a function communicate its intent?
‫؞‬ What attributes can we give our functions that will allow a casual
reader to intuit the kind of program they live inside?
1. Small!
჻ The first rule of functions is that they should be small. How short should
your functions be?
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 21
public static String renderPageWithSetupsAndTeardowns
(PageData pageData, boolean isSuite) throws Exception
{
if (isTestPage(pageData))
includeSetupAndTeardownPages(pageData, isSuite);
return pageData.getHtml();
}
- 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.
- Functions that do one thing cannot be reasonably divided into
sections.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 22
 If satatements
‫؞‬ blocks within if, else, while and so on should be one line long.
‫؞‬ Probably that line should be a call.
‫؞‬ Function called within the block should have a nicely descriptive name
 Switch statements
- It’s hard to make a switch statement that does one thing.
- By their nature, switch statements always do N things.
- Make sure that each switch statement is buried in a low-level class and is
never repeated.
- We do this, of course, with polymorphism.
- The following listing shows just one of the operations that might depend
on the type of employee.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 23
- Payroll.java
public Money calculatePay(Employee e)
throws InvalidEmployeeType {
switch (e.type) {
case COMMISSIONED:
return calculateCommissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
}
}
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 24
• It very clearly does more than one thing.
• It violates the Single Responsibility Principle (SRP) because there is
more than one reason for it to change.
• it violates the Open Closed Principle8 (OCP) because it must change
whenever new types are added.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 25
 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.
 Using an output argument instead of a return value
for a transformation is confusing.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 26
 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!.
 A function with two arguments is harder to understand than a monadic
function.
 For example,
writeField(name)
is easier to understand than
writeField(output-Stream, name)
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 27
 Argument Objects
 Wrap into a class of their own, more than two or three arguments.
following declarations:
- Circle makeCircle(double x, double y, double radius);
- Circle makeCircle(Point center, double radius);
 Argument Lists
Functions that take variable arguments can be monads, dyads, or even
triads. But it would be a mistake to give them more arguments than that.
void monad(Integer... args);
void dyad(String name, Integer... args);
void triad(String name, int count, Integer... args);
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 28
 Verbs and Keywords
 The function and argument should form a very
nice verb/noun pair.
 For example,
write(name) is very evocative.
Have No Side Effects
 Side effects are lies. Your function promises to
do one thing, but it also does other hidden
things.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 29
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 30
Side effects are:
1. Call to Session.initialize(), of course.
2. Call to checkPassword function, to checks the password.
- This side effect creates a temporal coupling. That is, checkPassword can only be called
at certain times (in other words, when it is safe to initialize the session). If it is called
out of order, session data may be inadvertently lost.
- Temporal couplings are confusing, especially when hidden as a side effect.
- If you must have a temporal coupling, you should make it clear in the name of the
function. In this case we might rename the function
checkPasswordAndInitializeSession, though that certainly violates “Do one thing.”
6. Comments rules
• Always try to explain yourself in
code.
• Don't be redundant.
• Don't add obvious noise.
• Don't use closing brace comments.
• Don't comment out code. Just
remove.
• Use as explanation of intent.
• Use as clarification of code.
• Use as warning of consequences.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 31
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 32
• Legit comments:
• legal: //copyright and authorship
• informative: //returns...
• explanation of intent: //we rank
these higher because...
• clarification
• consequence warning
• TODOs
Some comments are necessary or beneficial. We’ll look at a few that I
consider worthy of the bits they consume.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 33
 Eg.
// Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the GNU General Public License version 2 or later.
 Informative Comments
 Sometimes it is useful to provide basic
information with a comment.
 For example, this comment explains the
return value:
// Returns an instance of the Responder being tested.
protected abstract Responder responderInstance();
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 34
 “Don’t Comment Bad Code – Rewrite It”.
 Comments are, at best, a necessary evil.
 Comments compensate for failure to express in code
• Bad comments:
• Mumbling
• Redundant comments, Misleading comments
• Mandated comments
• Journal Comments (History of Changes)
• Noise Comments
• Position Markers & Closing Brace Comments
• Commented Out Code
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 35
 Clarification
 Sometimes it is just
helpful to translate
the meaning of some
obscure argument or
return value into
something that’s
readable.
ppublic void testCompareTo() throws Exception
{
WikiPagePath a = PathParser.parse("PageA");
WikiPagePath ab = PathParser.parse("PageA.PageB");
WikiPagePath b = PathParser.parse("PageB");
WikiPagePath aa = PathParser.parse("PageA.PageA");
WikiPagePath bb = PathParser.parse("PageB.PageB");
WikiPagePath ba = PathParser.parse("PageB.PageA");
assertTrue(a.compareTo(a) == 0); // a == a
assertTrue(a.compareTo(b) != 0); // a != b
assertTrue(ab.compareTo(ab) == 0); // ab == ab
assertTrue(a.compareTo(b) == -1); // a < b
assertTrue(aa.compareTo(ab) == -1); // aa < ab
assertTrue(ba.compareTo(bb) == -1); // ba < bb
assertTrue(b.compareTo(a) == 1); // b > a
assertTrue(ab.compareTo(aa) == 1); // ab > aa
assertTrue(bb.compareTo(ba) == 1); // bb > ba
}
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 36
 Warning of Consequences
 Sometimes it is useful to warn other programmers about certain
consequences.
 Eg,, This comment explains why a particular test case is turned off:
// Don't run unless you have some time to kill.
public void _testWithReallyBigFile()
{
writeLinesToFile(10000000);
response.setBody(testFile);
response.readyToSend(this);
String responseString = output.toString();
assertSubString("Content-Length: 1000000000",
responseString);
assertTrue(bytesSent > 1000000000);
}
7. Source code structure
• Separate concepts vertically.
• Related code should appear vertically dense.
• Declare variables close to their usage.
• Dependent functions should be close.
• Similar functions should be close.
• Place functions in the downward direction.
• Keep lines short.
• Don't use horizontal alignment.
• Use white space to associate related things and disassociate weakly related.
• Don't break indentation.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 37
8. Objects and data structures
• Hide internal structure.
• Prefer data structures.
• Avoid hybrids structures (half object and half data).
• Should be small.
• Do one thing.
• Small number of instance variables.
• Base class should know nothing about their derivatives.
• Better to have many functions than to pass some code into a
function to select a behavior.
• Prefer non-static methods to static methods.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 38
• 9. Tests
• One assert per test.
• Readable.
• Fast.
• Independent.
• Repeatable.
• Code smells
• Rigidity. The software is difficult to change. A small change causes a
cascade of subsequent changes.
• Fragility. The software breaks in many places due to a single change.
• Immobility. You cannot reuse parts of the code in other projects because
of involved risks and high effort.
• Needless Complexity.
• Needless Repetition.
• Opacity. The code is hard to understand.4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 39
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 40
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 41
42
Bad Smell
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir)
Bad Smell
• A bad smell in code
• Any symptom in the source code that possibly indicates a deeper
problem.
• The term is coined by Kent Beck.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 43
Bad Smells
• Duplicated Code
• Long Method
• Large Class
• Long Parameter List
• Divergent Change
• …
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 44
Quality vs. Bad Smells in Code
• Duplicated Code – identical or very similar code exists
in more than one location
• Long Method –method that has grown too large
• Large Class – class that has grown too large
• Long Parameter List – hard to understand/read
• Feature Envy – a class that uses methods of another
class excessively
45
Some quality aspects:
 Cohesion
 Comprehensibility/ Cyclomatic Complexity
 Readability
 Reusability4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir)
Code Smell: Uncommunicative Name
• Problem: Name of the method or class does not succinctly describe
what the class is for, or what the method does
• (e.g. When someone other than the developer looks at the code, they
don’t know what is going on)
• Solution: rename or rewrite it!
464/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir)
Bad Smells in Code
• Duplicated code
• Bad because if you modify one instance of duplicated code but not the
others, you (may) have introduced a bug!
• Long method
• long methods are more difficult to understand
• performance concerns with respect to short methods are largely obsolete
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 47
Bad Smells in Code
• Large Class
• Large classes try to do too much, which reduces cohesion
• Long Parameter List
• hard to understand, can become inconsistent if the same parameter chain is
being passed from method to method
• Divergent Change
• symptom: one type of change requires changing one subset of methods;
another type of change requires changing another subset
• e.g., “I have to change these three methods every time I get a new
database.”
• Related to cohesion
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 48
Bad Smells in Code
• Shotgun Surgery
• a change requires lots of little changes in a lot of different classes
• Feature Envy
• a method requires lots of information from some other class
• Move it closer!
• Data Clumps
• attributes that clump together (are used together) but are not part of
the same class
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 49
Bad Smells in Code
• Primitive Obsession
• characterized by a reluctance to use classes instead of primitive data types
• Switch Statements
• Switch statements are often duplicated in code; they can typically be replaced
by use of polymorphism (let OO do your selection for you!)
• Parallel Inheritance Hierarchies
• Similar to shotgun surgery; each time I add a subclass to one hierarchy, I
need to do it for all related hierarchies
• Note: some design patterns encourage the use of parallel inheritance hierarchies (so
they are not always bad!)
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 50
Bad Smells in Code
• Lazy Class
• A class that no longer “pays its way”
• e.g., may be a class that was downsized by a previous refactoring, or represented
planned functionality that did not pan out
• Speculative Generality
• “Oh, I think we need the ability to do this kind of thing someday”
• thus have all sorts of hooks and special cases to handle things that aren’t required
• Temporary Field
• An attribute of an object is only set/used in certain circumstances;
• but an object should need all of its attributes
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 51
Bad Smells in Code
• Message Chains
• a client asks an object for another object and then asks that
object for another object etc.
• client depends on the structure of the navigation
• any change to the intermediate relationships requires a change to
the client
• Middle Man
• If a class is delegating more than half its responsibilities to
another class, do you really need it? Involves trade-offs, some
design patterns encourage this (e.g., Decorator)
• Inappropriate Intimacy
• Pairs of classes that know too much about each other’s
implementation details (loss of encapsulation)
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 52
Bad Smells in Code
• Data Class (information holder)
• These are classes that have fields, getting and setting
methods for the fields, and nothing else; they are data
holders, but objects should be about data AND behavior
• Refused Bequest
• A subclass ignores most of the functionality provided by
its superclass
• Subclass may not pass the “IS-A” test
• Comments (!)
• Comments are sometimes used to hide bad code
• “…comments are often used as a deodorant”(!)
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 53
Tools and Techniques
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 54
Installing Roslyn
• Run Visual Studio Installer
• Select Modify
• Select the Individual components tab
• Check the box for .NET Compiler Platform SDK. You'll find it at the top
under the Compilers, build tools, and runtimes section.
Optionally, you'll also want the DGML editor to display graphs in the
visualizer:
• Check the box for DGML editor. You'll find it under the Code
tools section.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 55
Installing Roslyn
• To create a new analyzer project, go to File->New->Project then select
Extensibility under Templates->Visual C#. Select the Individual
components tab.
4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 56

7-clean-code

  • 1.
    Clean code 4/20/2020 S.Parsa, Associate Professor (www.parsa.iust.ac.ir) 1
  • 2.
    24/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir)
  • 3.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 3 • Make if hard for bugs to hide • Clean code does one thing well • Reads like well-written prose • obscure the designer’s intent • Provides one way rather than many ways for doing one thing • Each routine you read turn out to be pretty much what you expect
  • 4.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 4 • Clean Programming is some thing like martial art • Combination of technique and art. • The Art of Computer Programming by Knuth • Have different school of thoughts • Clean Programming is skill • Good learning results in good use forever • Changing bad learning is hard • Like Driving!
  • 5.
    Clean code doesone thing well Make it hard for bugs to hide 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 5
  • 6.
    Reads like well-writtenprose Never obscure the designer’s intent 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 6
  • 7.
    Provides one wayrather than many ways for doing one thing 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 7
  • 8.
    Each routine youread turn out to be pretty much what you expect 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 8
  • 9.
    4/20/2020 If an objectis doing more than one thing, I break it down into two or more objects. S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 9 In recent years I begin, and nearly end, with Beck’s rules of simple code. In priority order, simple code: • Runs all the tests; • Contains no duplication; • Expresses all the design ideas that are in the system; • Minimizes the number of entities such as classes, methods, functions, and the like. Of these, I focus mostly on duplication. When the same thing is done over and over, it’s a sign that there is an idea in our mind that is not well represented in the code. I try to figure out what it is. Then I try to express that idea more clearly.
  • 10.
     Code isclean if it can be understood easily – by everyone on the team.  With understandability comes readability, changeability, extensibility and maintainability.  Clean code can be read and enhanced by a developer other than its original author. 4/20/2020 10
  • 11.
    • Follow standardconventions. • Keep it simple stupid. Simpler is always better. Reduce complexity as much as possible. • Boy scout rule. Leave the campground cleaner than you found it. • Always find root cause. Always look for the root cause of a problem. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 11
  • 12.
    • Keep configurabledata at high levels. • Prefer polymorphism to if/else or switch/case. • Separate multi-threading code. • Prevent over-configurability. • Use dependency injection. • Follow Law of Demeter. A class should know only its direct dependencies. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 12
  • 13.
    ჻ Be consistent.If you do something a certain way, do all similar things in the same way. ჻ Use explanatory variables. ჻ Encapsulate boundary conditions. Boundary conditions are hard to keep track of. Put the processing for them in one place. ჻ Prefer dedicated value objects to primitive type. ჻ Avoid logical dependency. Don't write methods which works correctly depending on something else in the same class. ჻ Avoid negative conditionals. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 13
  • 14.
    Use descriptive names •Choose descriptive and unambiguous names. • Make meaningful distinction. • Use pronounceable names. • Use searchable names. • Replace magic numbers with named constants. • Avoid encodings. Don't append prefixes or type information. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 14
  • 15.
    Use informative names •Number-series naming (a1, a2, .. aN) is the opposite of intentional naming. • Such names provide no clue to the reader. • They are noninformative. Consider intent. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 15 public static void copyChars(char a1[], char a2[]) { for (int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } }  This function reads much better when source and destination are used for the argument names.
  • 16.
    • If aname is used in multiple places give it a search-friendly name. • They are noninformative. Consider intent. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 16 Use searchable names for (int j=0; j<34; j++)  { s += (t[j]*4)/5; } int realDaysPerIdealDay = 4; const int WORK_DAYS_PER_WEEK = 5; int sum = 0; for (int j=0; j < NUMBER_OF_TASKS; j++) { int realTaskDays = taskEstimate[j] * realDaysPerIdealDay; int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK); sum += realTaskWeeks; }
  • 17.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 17 int d; // elapsed time in days 3. We should choose a name that specifies what is being measured and the unit of that measurement: int elapsedTimeInDays; Int daysSinceCreation; int daysSinceModification; int fileAgeInDays; 1. The name of a variable, function, or class, should answer all the big questions. It should tell you why it exists, what it does, and how it is used. 2. If a name requires a comment, then the name does not reveal its intent Use meaningful names
  • 18.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 18 4. Choosing names that reveal intent can make it much easier to understand and change code. What is the purpose of this code? public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>(); for (int[] x : theList) if (x[0] == 4) list1.add(x); return list1; } Use meaningful names -2
  • 19.
    • Small. • Doone thing. • Use descriptive names. • Prefer fewer arguments. • Have no side effects. • Don't use flag arguments. Split method into several independent methods that can be called from the client without the flag. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 19
  • 20.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 20  How ‫؞‬ What is it that makes a function easy to read and understand? ‫؞‬ How can we make a function communicate its intent? ‫؞‬ What attributes can we give our functions that will allow a casual reader to intuit the kind of program they live inside? 1. Small! ჻ The first rule of functions is that they should be small. How short should your functions be?
  • 21.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 21 public static String renderPageWithSetupsAndTeardowns (PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData)) includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml(); } - 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. - Functions that do one thing cannot be reasonably divided into sections.
  • 22.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 22  If satatements ‫؞‬ blocks within if, else, while and so on should be one line long. ‫؞‬ Probably that line should be a call. ‫؞‬ Function called within the block should have a nicely descriptive name  Switch statements - It’s hard to make a switch statement that does one thing. - By their nature, switch statements always do N things. - Make sure that each switch statement is buried in a low-level class and is never repeated. - We do this, of course, with polymorphism. - The following listing shows just one of the operations that might depend on the type of employee.
  • 23.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 23 - Payroll.java public Money calculatePay(Employee e) throws InvalidEmployeeType { switch (e.type) { case COMMISSIONED: return calculateCommissionedPay(e); case HOURLY: return calculateHourlyPay(e); case SALARIED: return calculateSalariedPay(e); default: throw new InvalidEmployeeType(e.type); } }
  • 24.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 24 • It very clearly does more than one thing. • It violates the Single Responsibility Principle (SRP) because there is more than one reason for it to change. • it violates the Open Closed Principle8 (OCP) because it must change whenever new types are added.
  • 25.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 25  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.  Using an output argument instead of a return value for a transformation is confusing.
  • 26.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 26  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!.  A function with two arguments is harder to understand than a monadic function.  For example, writeField(name) is easier to understand than writeField(output-Stream, name)
  • 27.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 27  Argument Objects  Wrap into a class of their own, more than two or three arguments. following declarations: - Circle makeCircle(double x, double y, double radius); - Circle makeCircle(Point center, double radius);  Argument Lists Functions that take variable arguments can be monads, dyads, or even triads. But it would be a mistake to give them more arguments than that. void monad(Integer... args); void dyad(String name, Integer... args); void triad(String name, int count, Integer... args);
  • 28.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 28  Verbs and Keywords  The function and argument should form a very nice verb/noun pair.  For example, write(name) is very evocative. Have No Side Effects  Side effects are lies. Your function promises to do one thing, but it also does other hidden things.
  • 29.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 29
  • 30.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 30 Side effects are: 1. Call to Session.initialize(), of course. 2. Call to checkPassword function, to checks the password. - This side effect creates a temporal coupling. That is, checkPassword can only be called at certain times (in other words, when it is safe to initialize the session). If it is called out of order, session data may be inadvertently lost. - Temporal couplings are confusing, especially when hidden as a side effect. - If you must have a temporal coupling, you should make it clear in the name of the function. In this case we might rename the function checkPasswordAndInitializeSession, though that certainly violates “Do one thing.”
  • 31.
    6. Comments rules •Always try to explain yourself in code. • Don't be redundant. • Don't add obvious noise. • Don't use closing brace comments. • Don't comment out code. Just remove. • Use as explanation of intent. • Use as clarification of code. • Use as warning of consequences. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 31
  • 32.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 32 • Legit comments: • legal: //copyright and authorship • informative: //returns... • explanation of intent: //we rank these higher because... • clarification • consequence warning • TODOs Some comments are necessary or beneficial. We’ll look at a few that I consider worthy of the bits they consume.
  • 33.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 33  Eg. // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved. // Released under the terms of the GNU General Public License version 2 or later.  Informative Comments  Sometimes it is useful to provide basic information with a comment.  For example, this comment explains the return value: // Returns an instance of the Responder being tested. protected abstract Responder responderInstance();
  • 34.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 34  “Don’t Comment Bad Code – Rewrite It”.  Comments are, at best, a necessary evil.  Comments compensate for failure to express in code • Bad comments: • Mumbling • Redundant comments, Misleading comments • Mandated comments • Journal Comments (History of Changes) • Noise Comments • Position Markers & Closing Brace Comments • Commented Out Code
  • 35.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 35  Clarification  Sometimes it is just helpful to translate the meaning of some obscure argument or return value into something that’s readable. ppublic void testCompareTo() throws Exception { WikiPagePath a = PathParser.parse("PageA"); WikiPagePath ab = PathParser.parse("PageA.PageB"); WikiPagePath b = PathParser.parse("PageB"); WikiPagePath aa = PathParser.parse("PageA.PageA"); WikiPagePath bb = PathParser.parse("PageB.PageB"); WikiPagePath ba = PathParser.parse("PageB.PageA"); assertTrue(a.compareTo(a) == 0); // a == a assertTrue(a.compareTo(b) != 0); // a != b assertTrue(ab.compareTo(ab) == 0); // ab == ab assertTrue(a.compareTo(b) == -1); // a < b assertTrue(aa.compareTo(ab) == -1); // aa < ab assertTrue(ba.compareTo(bb) == -1); // ba < bb assertTrue(b.compareTo(a) == 1); // b > a assertTrue(ab.compareTo(aa) == 1); // ab > aa assertTrue(bb.compareTo(ba) == 1); // bb > ba }
  • 36.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 36  Warning of Consequences  Sometimes it is useful to warn other programmers about certain consequences.  Eg,, This comment explains why a particular test case is turned off: // Don't run unless you have some time to kill. public void _testWithReallyBigFile() { writeLinesToFile(10000000); response.setBody(testFile); response.readyToSend(this); String responseString = output.toString(); assertSubString("Content-Length: 1000000000", responseString); assertTrue(bytesSent > 1000000000); }
  • 37.
    7. Source codestructure • Separate concepts vertically. • Related code should appear vertically dense. • Declare variables close to their usage. • Dependent functions should be close. • Similar functions should be close. • Place functions in the downward direction. • Keep lines short. • Don't use horizontal alignment. • Use white space to associate related things and disassociate weakly related. • Don't break indentation. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 37
  • 38.
    8. Objects anddata structures • Hide internal structure. • Prefer data structures. • Avoid hybrids structures (half object and half data). • Should be small. • Do one thing. • Small number of instance variables. • Base class should know nothing about their derivatives. • Better to have many functions than to pass some code into a function to select a behavior. • Prefer non-static methods to static methods. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 38
  • 39.
    • 9. Tests •One assert per test. • Readable. • Fast. • Independent. • Repeatable. • Code smells • Rigidity. The software is difficult to change. A small change causes a cascade of subsequent changes. • Fragility. The software breaks in many places due to a single change. • Immobility. You cannot reuse parts of the code in other projects because of involved risks and high effort. • Needless Complexity. • Needless Repetition. • Opacity. The code is hard to understand.4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 39
  • 40.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 40
  • 41.
    4/20/2020 S. Parsa,Associate Professor (www.parsa.iust.ac.ir) 41
  • 42.
    42 Bad Smell 4/20/2020 S.Parsa, Associate Professor (www.parsa.iust.ac.ir)
  • 43.
    Bad Smell • Abad smell in code • Any symptom in the source code that possibly indicates a deeper problem. • The term is coined by Kent Beck. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 43
  • 44.
    Bad Smells • DuplicatedCode • Long Method • Large Class • Long Parameter List • Divergent Change • … 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 44
  • 45.
    Quality vs. BadSmells in Code • Duplicated Code – identical or very similar code exists in more than one location • Long Method –method that has grown too large • Large Class – class that has grown too large • Long Parameter List – hard to understand/read • Feature Envy – a class that uses methods of another class excessively 45 Some quality aspects:  Cohesion  Comprehensibility/ Cyclomatic Complexity  Readability  Reusability4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir)
  • 46.
    Code Smell: UncommunicativeName • Problem: Name of the method or class does not succinctly describe what the class is for, or what the method does • (e.g. When someone other than the developer looks at the code, they don’t know what is going on) • Solution: rename or rewrite it! 464/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir)
  • 47.
    Bad Smells inCode • Duplicated code • Bad because if you modify one instance of duplicated code but not the others, you (may) have introduced a bug! • Long method • long methods are more difficult to understand • performance concerns with respect to short methods are largely obsolete 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 47
  • 48.
    Bad Smells inCode • Large Class • Large classes try to do too much, which reduces cohesion • Long Parameter List • hard to understand, can become inconsistent if the same parameter chain is being passed from method to method • Divergent Change • symptom: one type of change requires changing one subset of methods; another type of change requires changing another subset • e.g., “I have to change these three methods every time I get a new database.” • Related to cohesion 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 48
  • 49.
    Bad Smells inCode • Shotgun Surgery • a change requires lots of little changes in a lot of different classes • Feature Envy • a method requires lots of information from some other class • Move it closer! • Data Clumps • attributes that clump together (are used together) but are not part of the same class 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 49
  • 50.
    Bad Smells inCode • Primitive Obsession • characterized by a reluctance to use classes instead of primitive data types • Switch Statements • Switch statements are often duplicated in code; they can typically be replaced by use of polymorphism (let OO do your selection for you!) • Parallel Inheritance Hierarchies • Similar to shotgun surgery; each time I add a subclass to one hierarchy, I need to do it for all related hierarchies • Note: some design patterns encourage the use of parallel inheritance hierarchies (so they are not always bad!) 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 50
  • 51.
    Bad Smells inCode • Lazy Class • A class that no longer “pays its way” • e.g., may be a class that was downsized by a previous refactoring, or represented planned functionality that did not pan out • Speculative Generality • “Oh, I think we need the ability to do this kind of thing someday” • thus have all sorts of hooks and special cases to handle things that aren’t required • Temporary Field • An attribute of an object is only set/used in certain circumstances; • but an object should need all of its attributes 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 51
  • 52.
    Bad Smells inCode • Message Chains • a client asks an object for another object and then asks that object for another object etc. • client depends on the structure of the navigation • any change to the intermediate relationships requires a change to the client • Middle Man • If a class is delegating more than half its responsibilities to another class, do you really need it? Involves trade-offs, some design patterns encourage this (e.g., Decorator) • Inappropriate Intimacy • Pairs of classes that know too much about each other’s implementation details (loss of encapsulation) 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 52
  • 53.
    Bad Smells inCode • Data Class (information holder) • These are classes that have fields, getting and setting methods for the fields, and nothing else; they are data holders, but objects should be about data AND behavior • Refused Bequest • A subclass ignores most of the functionality provided by its superclass • Subclass may not pass the “IS-A” test • Comments (!) • Comments are sometimes used to hide bad code • “…comments are often used as a deodorant”(!) 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 53
  • 54.
    Tools and Techniques 4/20/2020S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 54
  • 55.
    Installing Roslyn • RunVisual Studio Installer • Select Modify • Select the Individual components tab • Check the box for .NET Compiler Platform SDK. You'll find it at the top under the Compilers, build tools, and runtimes section. Optionally, you'll also want the DGML editor to display graphs in the visualizer: • Check the box for DGML editor. You'll find it under the Code tools section. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 55
  • 56.
    Installing Roslyn • Tocreate a new analyzer project, go to File->New->Project then select Extensibility under Templates->Visual C#. Select the Individual components tab. 4/20/2020 S. Parsa, Associate Professor (www.parsa.iust.ac.ir) 56

Editor's Notes

  • #46 The term bad smell has been coined by Kent Beck and Fowler. Code smell is any symptom in the source code of a program that possibly indicates a deeper problem. Code smells are usually not bugs—they are not technically incorrect and do not currently prevent the program from functioning. Instead, they indicate weaknesses in design that may be slowing down development or increasing the risk of bugs or failures in the future. Once you see one of these bad smalls in your code, you need to fix it. It is not fixing a bug, yet it improves the quality of the cost which is a contributing factor to the cost of development. This modification of the code to improve the structure is known as refactoring.
  • #52 temporary field, e.g., orientation in a scatterplot