Showing posts with label OO design. Show all posts
Showing posts with label OO design. Show all posts

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.




Sunday, November 15, 2015

book reading: 97 Things Every Programmer Should Know (I)

Nov. 15, 2015.

 I like to tell how I get here to read this book - 97 things every programmer should know. It is a long story, but it can be described as this flow:

Julia works on leetcode questions (January 2015) ->
Challenged on August, 2015 about SOLID OO principles (Only know / remember S, basic decoupling, work on interface)
-> procedural code's concern, try to follow DRY principles, Oct. 2015
-> Learn SOLID priciples through videos in Nov., 2015:
-> Recommended reading: the book

Spent 3 hours to read the book on Sunday morning, take some notes about my favorite ideas:

1. Act with prudence - Seb Rose

"doing it right"   vs "doing it quick"

Julia's comment: thinking about it later :-)  Prudence means " be careful".

2. Apply Functional Programming Principles - Edward Garson

Julia's comment:
   Look into the term: "high degree of referential transparency"
   Questions from Julia, list a 3-5 principles of functional programming principles, most popular ones.

3.  Ask, "What Would the User Do?" (You are not the user) - Giles Colborne
Julia's comment:
     Look up the term: the false consensus bias - psychologists call it.

4. Automate your coding Standard - Filip van Laenen

Julia's comment: Look up the meaning of "antipatterns", things talked about are interesting: test coverage, coding standard. Read the article later.

5. Beauty is in simplicity - Jorn Olmheim

Julia's comment: Four things we strive for in our code:
   Readability (1), maintainability (2), speed of development (3), the elusive quality of beauty (4)
Simple objects with a single responsibility, with simple, focused methods with descriptive names.
Desirable goal is to have short methods of 5-10 lines of code. (Julia likes this argument!)

6. Before you refactor - Rajith Attapattu

Julia's comment: great topic, and good to hear some advice.

7. Beware the Share - Udi Dahan

8. The Boy Scout Rule - Robert C. Martin (Uncle Bob)

Julia's favorite: Make it better: improve name of one variable, or split one function into two smaller functions. Or break a circular dependency, or add an interface to decouple policy from detail.

And more about team spirit, help one another and clean up after one another.

9. Check Your Code First before looking to blame others - Allan Kelly
    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth.
    http://www.allankelly.net/

10. Choose Your tools with Care - Giovanni Asproni
      existing tools - components, libraries, and frameworks
http://www.atlantec.ie/giovanni-asproni-to-be-added/
 
11. Code in the language of the Domain - Dan North
consulting service:
http://dannorth.net/about/

12. Code is Design - Ryan Brush
http://conferences.oreilly.com/strata/stratany2014/public/schedule/speaker/138579

13. Code layout matters - Steve Freeman

Julia is still working on the code layout; she thinks that the good layout helps, her favorite book: the art of readable code

15. Code Reviews - Mattias Karlsson
 Code review - increase code quality and reduce defect rate.

used to be:  Lead programmer does the review, architect reviews everything.

16 Coding with Reason - Yechiel Kimchi

http://programmer.97things.oreilly.com/wiki/index.php/Coding_with_Reason

Julia likes the idea -
1. Try to reason about software correctness by hand
2. Automated tools are preferable but not always possible
3. a middle path - reasoning semiformally about correctness
    Julia likes this middle path, in detail,
   To divide all the code under consideration into short sections - from a single line, such as a function call, to blocks of less than 10 lines - and argue about their correctness.

Julia likes to memorize those good advices, so just write it down word by word.
1. Avoid using goto statements, as they make remote sections highly interdependent.
2. Avoid using modifiable global variables, as they make all sections that use them dependent.
3. Each variable should have the smallest possible scope. For example, a local object can be declared right before its first usage.
4. Make objects immutable when relevant.
5. Make the code readable using spacing, both horizontal and vertical.
6. Make the code self-documenting by choosing descriptive name for objects, types, functions, etc.
7. If you need a nested section, make it a function. <- Julia's favorite: avoid nested section, add a function
8. Make your functions short and focus on a single task. <-  great advice, obey it.
The old 24-line limit still applies. Although screen size and resolution have changed, nothing has changed in human cognition since 1960s. ( 24 lines, Julia can do it! )
9. Function should have few parameters ( four is a good upper bound). This does not restrict the data communicated to functions: Grouping related parameters into a single object benefits from object invariants and saves reasoning, such as their coherence and consistency.

17. Convenience is Not an -ility - Gregor Hohpe

It is a great topic about API design. A good API follows a consistent level of abstraction, exhibits consistency and symmetry, and forms the vocabulary for an expressive language.

API design reading, found one through search:
http://lcsd05.cs.tamu.edu/slides/keynote.pdf

18. Deliberate practice

Leading Lean Software Development (Addison-Wesley Professional)

19. Domain-Specific Languages

https://about.me/mhunger

20 Do not afraid to break things - Mike Lewis

21. Encapsulate Behavior, Not just State - Julia's favorite article

http://www.researchgate.net/profile/Einar_Landre/publications

http://programmer.97things.oreilly.com/wiki/index.php/Encapsulate_Behavior,_not_Just_State

Examples:
  It is easy to find a class with a single 3,000-line main method, or a class with only set and get method for its primitive attributes.
Analysis: do not understand the object-oriented thinking, do not take advantage of the power of objects as modeling constructs.

Given an example, 3 classes: Customer, Order, and Item.
A Customer  object is the natural placeholder for the credit limit and credit validation rules.
An Order object knows about its associated Customer, and its addItem operation delegates the actual credit check by calling customer.ValidateCredit(Item.Price()).

Less experienced OO developer, design one objects: OrderManager or OrderService to wrap all business rules. In the design, Order, Customer, and Item are treated as little more than record types.
All logic is factored out of the classes and tied together in one large, procedural method with a lot of internal if-then-else constructs.

But, these methods are easily broken and almost are impossible to maintain. Because encapsulation is broken.

22. Hard work does not pay off - Olve Maudal

23. Know your limits
http://www.boost.org/doc/libs/1_34_0/people/greg_colvin.htm

24. A message to the Future - Linda Rising

Her website:
http://www.lindarising.org/

Julia really likes the short story written in the chapter. The problem solved is difficult, and the solution should be just as difficult for everyone (maybe even for themselves a few months after the code was written) to understand and maintain. But, the code should be easy to understand.

25. Only the code tells the truth - Peter Sommerlad

https://www.youtube.com/watch?v=XLsZkA77h8c
Notes from video:
Less code = More Software
Let Julia read those sentences and laugh about mistakes she made as well:
1. Complexity is one of the biggest problems with software if not THE biggest.
2. It is much easier to create a complicated "solution" than to really solve a problem.
3. Much software complexity is accidental not inherent to the problem solved.
4. It starts in the small, one statement at a time.
5. Architects and developers need to value Simplicity!
  . Good Abstractions are the key, as are
  . Managing Dependencies (Avoid global variables)
6. Software needs to be simpler to solve more complex problems.
7. Simple software requires work and skill but pays off in the long run.

Famous Quotes by Sir C.A.R. (Tony) Hoare
1. Inside every large problem, there is a small program trying to get out.
2. There are two ways of constructing a software design:
   1. one way is to make it so simple that there are obviously no deficiencies, and
   2. the other way is to make it so complicated that there are no obvious deficiencies.
   The first method is far more difficult.

Good advice:

 1. Strive for good names.
 2. Structure your code with respect to cohesive functionality, which also naming.
 3. Decouple your code to achieve orthogonality.
 4. Write automated tests explaining the intended behavior and check the interfaces.
 5. Refactor mercilessly when you learn how to code a simpler, better solution.
 6. Make your code as simple as possible to read the understand.

- to be continued.

More reading about authors:

1.  Enjoy reading the blog of one of authors:

To junior developer:

http://dearjunior.blogspot.ca/2014/11/make-implicit-concepts-explicit-in-code.html

Note:

Eric Evans, the thought leader of Domain Driven Design.

http://dearjunior.blogspot.ca/2012/03/dry-and-false-negatives.html


Saturday, November 14, 2015

OO design principles - DRY - Don't repeat yourself principle

Nov. 14, 2015

It is so great to find something to work on this weekend of November. My favorite time to study the video:

The Don't repeat yourself princple, part 2

https://www.youtube.com/watch?v=wweNdRuM64g&list=PLD4GnSXHpkQ2_eKG5fKzszXs5hYcEsft7&index=2

Video time: 30:15/31:07
Summary
. Repetition breed errors and waste
. Abstract repetitive logic in code
. Related fundamentals:
  . template method pattern
  . command pattern
  . dependency inversion principle
Recommended reading:
  . The pragmatic programming: From Journeyman to Master
  . 97 Things Every Programmer Should Know.

So, Julia found one book to read this weekend, 97 Things Every Programmer Should Know.

Further reading: (Nov. 18, 2015)
Template method pattern:
https://en.wikipedia.org/wiki/Template_method_pattern

Thursday, October 22, 2015

Good API video watching and notes taken

Oct. 22, 2015

  Spent time to look into the note through the video, and then study more later:


How To Design A Good API and Why it Matters (Julia's rating: A+)
https://www.youtube.com/watch?v=aAb7hSCtvGw


1. Watched again on 10/21/2015, notes taken to share:
54:40/1:00:18
Use Appropriate Parameter and Return Types
. Favor interface types over classes for input
- provides flexibility, performance
. Use most specific possible input parameter type
- Moves error from runtime to compile time (Julia's comment: Great tip, reduce time on debugging, fix things in compiling time!)
. Don't use string if a better type exists
- Strings are cumbersome, error-prone, and slow
. Don't use floating point for monetary values
- Binary floating point causes inexact results!
- Use double (64 bits) rather than float (32bits)
-Precision loss is real, performance loss negligible

2. watched again on 10/21/2015, notes taken to share:
49:19/1:00:18
Don't violate the Principle of Least Astonishment

Read more on this article:
http://programmers.stackexchange.com/questions/187457/what-is-the-principle-of-least-astonishment

3. watched again on 10/21/2015, notes taken to share:
42:31/1:00:18

Subclass only where it Makes Sense
. Subclassing implies substitutability (Liskov)
-- Subclass only when is-a relationship exists
-- Otherwise, use composition 

. Public classes should not subclass other public classes for ease of implementation
Bad: Properties extends Hashtable 
        Stack extends Vector 

Good: Set extends Collection