Showing posts with label clean code. Show all posts
Showing posts with label clean code. Show all posts

Monday, May 29, 2017

Clean code: Writing code for Humans

May 29, 2017

Study the code on pluralsight.com. The course is called "Clean code: Writing code for Humans".

Read the article on pluralsight.com. "7 reasons clean code matters" article is here to read.

Take some notes here.

11:13 pm, 5/29/2017

The course is released on Oct. 7, 2013. It is always on time!

Julia, it is always better to learn coding styles, principles first and then practice leetcode algorithms.


Cory House   - the lecturer of the course's website is here.


assign booleans implicitly (Julia's favorite rating: 7 out of 10)

- 3 good reasons to create a function (10 out of 10)

convey intent, eliminate excessive indentation, avoid duplication

problem with zombie code



Boundaries matter - (Julia's rating: 9 out of 10)

dynamic JS in C# (JavaScript and C# etc),
html in JS string,
JS in HTML (JavaScript and Html),
inline Styles (css and html),
Dynamic SQL in C# strings


Stay native - advantages (Julia's favorite ranking 9 out of 10)
1. Cached
2. Code colored
3. Syntax checked
4. Separation of concerns
5. Reusable
6. Avoids string parsing
7. Can minify & obfuscate

Maximize signal to noise ratio (Excellent concept!)

Signal
Logic that follows the TED rules:

Terse
Expressive
Do one thing

Noise

High cyclomatic complexity
Excessive indentation
zombie code
unnecessary comments
poorly named structures
huge classes
long methods
repetition
no white space
overly verbose


Self-documenting code

Well written code is self-documenting.

Clear intent
Layers of abstractions
Format for readability
Favor code over comments

Complex conditionals


Discussion topic - excessive indentation: solutions

extract method
fail fast
return early

Mayfly variable - just in time

Continue


June 5, 2017  11:00 pm - 11:53 pm

Demo 42 minutes

Bug Fix: What a contrast (Julia's rating: 10 out of 10)

Terse
Expressive
Do One Thing

Watch the lecture titled "Clean Code"

Follow up 


July 29, 2017  10:30 pm - 11:30 pm
Go over the lecture video again

TED Principle
Terse, expressive, do one thing
Don't repeat yourself

How to write Self-document code?
clear intent
layers of abstraction




Wednesday, April 27, 2016

Clean Code - book reading

April 27, 2016

 Julia was recommended to read this book "Clean Code". So, plan to read the book in next 2 weeks.

 Put some notes together on this blog.

http://goo.gl/hHBZPS

Short slides about the book: clean code

Nov. 15, 2016
Spent 1+ hour to read the chapter 3:
Chapter 3 - Functions
small
do one thing
one level of Abstraction per function

Julia likes to google and work on those 3 key concepts.

Google search:
Keyword:
one level of Abstraction per function

http://principles-wiki.net/principles:single_level_of_abstraction

Wednesday, November 18, 2015

The clean code talks

Nov. 18, 2015

Review the video about the testing, and try to get more from this lecture:

"The Clean Code Talks -- Inheritance, Polymorphism, & Testing"

https://www.youtube.com/watch?v=4F72VULWFvc

action items:
1. put sample code in C#, and then, check in git;
2. write down key words, and easy for review and follow as rules.

Julia's sample code in C#:
C# code using conditional implementation, one class Node

The source code folder is here.

better solution: Node, OpNode, ValueNode:

optimal solution:

Perfect example to learn S.O.L.I.D. OO principles, open for extension, close for change. The above optimal solution does not have any if statement, and any new arithmetic operation just needs a new class, no need to touch existing code. Julia passes the learn Open/Close principle. Move on to next one, Liskov substitution principle!

Notes:
Premise - Most ifs can be replaced by polymorphism
Why?
Easy to read, test without ifs.
polymorphic systems are easier to maintain.

Julia: write down the sentence in the talk:  supporting facts: one execution path, so easy to understand, test, and extend.

Use polymorphism
 If an object should behave differently based on its state.
 If you have to check the same conditions in multiple places.

- binding is not on compile time,

  Use conditionals
  Mainly to do comparisons of primitive objects: >,<,==, !=
  There other uses, but today we focus on avoiding if

  Do not return null in the method
  To be if free
  Never return a null, instead return a Null object, e.g. an empty list

  Don't return error codes, instead throw an Exception (Run Time please!)

  Rampant (wild, unchecked) subclassing
  Polymorphism uses subclassing
  Be careful about runaway subclassing (another talk focuses on that)
  avoid pitfall: inheritance hierarchy - too complex

  State based behavior

  Replace conditionals with polymorphism
  You have a conditional that chooses different behavior depending on the type of an object.

  Move each leg of the conditional to an overriding method in a subclass.
  Make the original method abstract.


   Example:
  double getSpeed(){
    switch (_type){
       case EUROPEAN:
          return getBaseSpeed();
       case AFRICAN:
         return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts;
       case NORWEGIAN_BLUE:
         return (_isNailed)? 0 : getBaseSpeed(_voltage);
   }
   throw new RuntimeException ("Should be unreachable");
}

Suggestion to solve the problem: use subclasses
Isn't there already a type system?

An Exercise:
Model this!
1 + 2 * 3

favorite interview question by the speaker:

Represent this as a tree

   +
/     \
1     *
    /    \
  2      3
Node object to store the information

evaluate()
computes the result of an expression

Most of people come out solution like the following:
 Using conditionals

  class Node{
     char operator;
     double value;
     Node left;
     Node right;
     double evaluate(){
       switch(operator){
        case '#': return value;
        case '+': return left.evaluate() + right.evaluate();
        case '*" return left.evaluate() * right.evaluate();
        case ...  // edit this for each new operator
       }
    }
 }

 Big problem on this:
  graphic representation,
  Node
  op:char
  value: double
  left: Node
  right:Node
 --------------
   evaluate():double

Julia could not figure out the analysis here <- first time to memorize this analysis, and also try to learn reasoning

    Analyzing attributes

                           #      +        *
function                      yes     yes
value                  yes
left                              yes     yes
right                            yes     yes

Two different behaviors are fighting here, (see the above table),
if you are the operation node, then you need your left and right child; whereas value node, you just need value.


Either you need value or you need left and right, but you never need both.
One class have multiple tasks entangled, polymorphism is through if statement, not through polymorphism.

video time:  11:42/38:24
Let us break it up:
     Node
   --------------
   evaluate(): double
         |                                  |
ValueNode                         OpNode
  value: double                   op: char
---------------                       left: Node
 evaluate: double                right: Node
                                          ----------------
                                          evaluate(): double
As showing above, break Node into ValueNode and OpNode, so ValueNode does not have left and right child because of no meaning over there.


Operations and values

abstract class Node{
   abstract double evaluate();
}

class ValueNode extends Node{
    double value;
    double evaluate(){
           return value;
    }
}

class OpNode extends Node{
   char operator;
   Node left;
   Node right;
   double evaluate(){
         switch(operator) {
             case '+': return left.evaluate() + right.evaluate();
             case '-':  return left.evaluate() + right.evaluate();
             case ...   // edit this for each new operator
         }
    }
}

How to extend this? Every time you add a new operator, need to hold on source code, and add code in switch statement, how to make it better?

Tree looks like:

          OpNode
              +
    /                            \
ValueNode         OpNode
       1                         *
                        /                    \
                 ValueNode      ValueNode
                        2                     3


OpNode divides into AdditionNode  and MultiplicationNode

           OpNode
         ------------------
         left: Node
         right: Node
        ------------------
         evaluate(): double

 AdditionNode                                 MultiplicationNode
----------------------------                    --------------------------
   evaluate(): double                           evaluate(): double


  abstract class Node{
           abstract double evaluate();
  }

  class ValueNode extends Node{
       double value;
       double  evaluate(){
          return value;
       }
 }

  class abstract OpNode extends Node{
  Node left;
  Node right;
  abstract evaluate();
  }

  video time:   14:39/38:24

  Operation classes
  class AdditionNode extends OpNode{
      double evaluate(){
         return left.evaluate() + right.evaluate();
      }
}

  class MultiplicationNode extends OpNode{
     double evaluate(){
          return left.evaluate() + right.evaluate();
     }
 }

 Now, the new tree diagram:

      AdditionalNode
              +
    /                            \
ValueNode         MultiplicationNode
       1                         *
                        /                    \
                 ValueNode      ValueNode
                        2                     3

Julia's C# implementation, the SOLID principle applied solution. Here is the code.


Further exploration

Define toString() prints the infix expression placing parenthesis only when necessary.

Add new math operators: exponentiation, factorial, logarithm, trigonometry


Summary

A polymorphic solution is often better because:

1. new behavior can be added without having the original source code, and
2. each operation/concern is separated in a separate file which makes it easy to test/understand.

Prefer polymorphism over conditionals:

switch almost always means you should use polymorphism
if is more subtle ... sometimes an if is just an if

Repeated Condition

  22:36/38:24

Two piles

piles of Objects                                             pile of Construction
. business logic                                             . factories
. the fun stuff                                                . builders
                                                                      . Provider<T>
. given the collaborators needed                   .created and provides collaborators (Denpendency                                                                                        Injection)

Construction
 class Consumer{
   Consumer(Update u) {...}
}

class Factory{
  Consumer build(){
      Update u = FLAG_i18n_ENABLED? new I18NUpdate() : new NonI18NUpdate();

       return new Consumer(u);
  }
}

Benefits

Conditional is localized in one place
No more duplication
Separation of responsibilities, and global state

Common code is in one location
Testing independently easily, and in parallel
Looking at the subclasses makes it clear what the differences are

When to use polymorphism

Behavior changes based on state
Parallel conditionals are in multiple places in code

Be pragramatic

You will still have some conditionals

Question and answers:
Argument:   Easy to read switch statement    vs  a lot of subclasses
File over thousand line of length
Easy to create a new class
Single responsibility
Behavior is controlled by a lot of flags     vs.   a lot of classes collaboration

Julia's comment:
1. Julia watched the video over 3 times, she likes the teaching and sample code.

2. Julia likes to refactor the C# code, learn OO design. Strongly recommend this video to friends.

3. C# code using conditional implementation, one class Node. Here is the link.