Object Oriented Design (in .NET C#)

Elements of OO

3 elements of object oriented: Inheritance, encapsulation, and polymorphisn. Interface is another important element of the OOP.

Inheritance

Categories

Inherit is way to describe the relationship between between classes. If class A IS-A class B, we call class A Subclass or Derived class, call class B as Parent class or Base Class or Super Class.

Subclass could inherit the properties and methods from parent class, and subclass could also add or modify new properties and methods.

In .NET, it cloud be divided into 2 categories:

  • Inherit a class
    • Can only inherit one class at one time
    • The top parent class for any class in .NET is System.Object
    • System.Object has 4 functions: ToString, Equals, GetHashCode, Finalize.
  • Inherit an interface
    • Can inherit several interfaces at one time
    • Can divide the objects (class) and actions (interface) during the inherit

Modify existing classes - Adapter Design Patterns

Adapter pattern is a way to modify the existing classes to meet the new requirements. It has two categories:

  • Adapter pattern of class
    • Design a new subclass which inherits previous classes and the new interface
  • Adapter pattern of object
    • Design a new subclass which inherits the new interface and get the parameter of previous base class

Additional Knowledge - Abstract Class

  • Abstract class
    • The class can only be inherited but cannot be instantiated.
    • All abstract methods in the abstract class need to be override in subclass.
  • Abstract function v.s. Virtual functions
    • Abstract function doesn’t have the function body, and it requires to be override in the subclass.
    • Virtual function could have the function body, and it could be override or not in the subclass.

Encapsulation

It is for class to hide some private field or methods but leave public interface for other classes. The rules include

  • Field
    • Declare field (variables of class) as private
  • Property
    • Declare property as public
    • supporting get and/or set
    • Use property instead of field directly
    • Property is transferred to function during the compile
  • Functions
    • Functions that other classes need to call can be declared as public; other functions of classes should be declared as private

Polymorphisn

This allows users to set a base class reference points to different subclass. When call the methods in base class, the same method acts differently according to the implement in subclass. The specific relationship between reference and real methods will be determined after the compile.

We can declare a base class variable / interface but still points to the subclass object. Assume the base class is A, and the subclass is B. When we call a method in A, the compiler will check whether this method was declared virtual.

  • If it is not declared virtual, call this method directly.
  • If it is declared virtual, then will check whether subclass B has override this method
    • If there is a override method, call this method
    • If there is not override method, recursively check the parent class whether override this method

Interface

  • Interface usually ends with able, which shows a kind of ability of the class, also described a can-do.
  • Interface is like a class containing abstract methods. The methods inside interface are declared public abstract automatically.
  • Methods in interface need to be implemented in the subclass, but no need to use abstract, virtual, override keywords.
  • Interface only contains the single category of functions.
  • When create a new object, we can declare the pointer as the interface but points to object inherited from the interface.

See here for more info.

Design Principles of OO

The final design principles of OO is Abstract-oriented, loosely coupled.

Single Responsibility Principle

One class only do one thing, and only change due to one reason.

For example, an interface defines the basic actions and class A inherit the interface and implement those actions. Class B adds some judging methods and it also inherits the interface and include a field inheriting from the interface (an object of class A), so class B just call A’s functions instead of implement them.

Open Closed Principle

Open for extension, closed for modifying. Program for abstract instead of specific.

For example, if there will be much similar methods, we can put them into different classes but inherits a same interface. Then we use another manager class to create an interface reference for different classes. When a new method adds into the system, we can just implement the new class inheriting from the interface.

Dependency Inversion Principle

Depends on abstract. Classes should depend on interface rather than other classes.

Some principle:

  • Less inheritance, more aggregate
  • One-way dependency (Low coupling, high cohesion)
  • Encapsulation abstraction
  • Dependence should ends on abstract class or interface

For example, use interface pointer to call method. Since different object implement different methods, the method will automatically link to the right method according to the type of created object. When new kinds of methods add, just implement new classes inherited from the interface and previous code don’t need to change.

In other words, we solve the problem of deciding what versions of the similar method to use by the Polymorphisn(different methods have a same interface) rather than write judging code.

Interface Segregation Principle

Use many small interface instead of a big interface.

Class could inherit several interfaces that are useful to the class.

Liskov Substitution Principle

Subclass must be able to replace base class.

Subclass must have all the methods of base class. The base class should declare the method virtual and subclass override that method. This can reduce the unnecessary judging code.

Composite/Aggregate Reuse Principle

Reduce coupling between classes by aggregating existing classes/interface instead of inheriting objects.

One example is the adapter pattern, which is a way to modify the existing classes to meet the new requirements. It has two categories:

  • Adapter pattern of class
    • Design a new subclass which inherits previous classes and the new interface
    • Requires to inherit a class, will increasing the coupling between classes
  • Adapter pattern of object
    • Design a new subclass which inherits the new interface and contains a field which is the base class of classes that need to be extended
    • Use aggregate (combine class and interface together), reduce coupling

Design Pattern of OO

Dependency / coupling

Kinds of coupling

  • Non-coupling: two classes are independent
  • Concrete coupling: one class have the reference of another class
  • Abstract coupling: one class have the reference of another abstract class, which can achieve the Polymorphisn

Reasons causing the coupling

  • Inheritance
  • Aggregation
  • Interface
  • Call methods or reference
  • Call services

Design principle to reduce the coupling

  • Dependency Inversion Principle (DIP)
    • Add a middle class
    • Let class use the reference of the interface which another class inherits from, instead of use the reference of another class
  • Inversion of Control (IoC)
    • Let the system control the code
  • Dependency Injection (DI)
    • Interface Injection (Use the parameters of methods of method)
    • Constructor Injection (Use constructor method)
    • Setter Injection (Properties)

Design Pattern to reduce the coupling happening in when need to create(new) an object

  • Factory Mode
    • Use interface and generic
  • Dependency Injection
    • Use Unity container to create new object
    • Use the resolve method of Unity container to dynamically create different objects inherited from the same abstract class or interface

Design Pattern

| Category | Name | Function |
| — | — |
| Creation Pattern | Factory Method Pattern | A dynamic way to deal with the process when create a new object, especially for creating different objects but those objects have same base class or interface |
| | Singleton Pattern | One class only have one instance |
| Structural model | Bridge Pattern | Divide the implement with the logic |
| | Proxy Pattern | Encapsulation the complex logic, use proxy to control the the create and call the original object |
| | Adapter Pattern | Don’t change previous classes, add new interfaces |
| | Composite Pattern | Use the same method to process all objects in a composite |
| | Decorator Pattern | Dynamically add or remove status or actions |
| | Facade Pattern | Divide the logic layer and the presentation layer |
| Behavioral model | Template Method Pattern | Define the template in base class and implement them in subclass |
| | Iterator Pattern | Provide a method to get every element in a container but not exposure to outside |
| | Chain of Responsibility Pattern | Form the methods a linked list,traverse the linked list and get the right method |
| | Command Pattern | Encapsulation the request as a class, divide the execution of order and duty |
| | Observer Pattern | one v.s. many. One object’s status changes, other objects will get the event, then they will change. e.g. the delegate and event in C# |
| | Strategy Pattern | Encapsulation the part changing a lot as interface |

Object-Oriented & Object-Based

Object-Based: Handle the object with field and method, but the object doesn’t inherit any class, thus no Polymorphisn.

.NET Closure

Closure is the body formed by methods and environment attached to the method. It can allow several methods operate the same element.

Good Code

  • Good Name
    • Pascal Casing for namespace, class, interface, method, event, enum
    • Camel Casing for paramenters, private members
    • Attribute, delegate, exception as the suffix
  • Security of thread

Reference

  1. 《你必须知道的.NET(第二版)》,第1部分,王涛著