Saturday, October 18, 2008

Design by contract - Interfaces

Interface is one of the mechanism to implement design by contract

Interface illustrate the power of abstraction
1. Decoupled systems i.e clients from server

2. Separate design from implementation

3. No performance penalty

Use

1. PITL (Programming in the large)

Interface between the layers.

2. Polymorphism

You should know about

1. IClonable
2. IComparer defines objects that overrides default sorting process.
3. IComparable defines contract for sorting.
4. IDisposable

Friday, October 17, 2008

Design Rules for Classes

1. Always

Rule # 1

Classes should always override the ToString() method. Objects should have a way to be represented as strings.

.NET calls the method whenever it needs to display object as string.

Rule # 2

Use constructors to guarantee initialization.

Bad Design

Customer cust = new Customer();
Cust.FirstName = "Sachin";
Cust.LastName = "Surana";

People who want to use Customer object need to be worried about how many fields are there, do I fill them all ? Very error prone way to do things.

Good Design

Force to supply values.

Customer cust = new Customer("Sachin", "Surana");

Rule # 3

In case of overloading, have one central contructor or central method. The other methods call the central method.

Rule # 4

If a class has static fields, guarantee initialization using static constructors.

Rule # 5

Declare constants as read-only fields.

i. It helps to define constant without embedding it within clients.

ii. You can initialise it using run-time constructor.


public class Globals {

public static readonly string AppHomeDir

Rule # 6

Use enum to define a set of related constants.

2. Consider

Rule # 7

All fileds should be private. Consider hiding data from unwarranted access. If access is needed, provide using properties.

Rule # 8

Consider overriding Equals(object obj)

.NET calls this method when searching.

Rule # 9

If override Equals, also override GetHashCode

1. Used internally by hashing algorithms.

2. If two objects are Equal, GHS they must return same value.

3. Define GHC in terms of same fields as Equals.

Rule # 10

Define Dispose() if your objects need cleanup.

Rule # 11

If class needs Dispose(), you should also need finalizer.

Rule # 12

Consider supplying a method for cloning objects. Use IClonable interface.



public class Customer : IClonable{

public object Clone(){
return new Customer("Sachin", "Surana");
}
}

Which is equivalent to

public class Customer : IClonable{

public object Clone(){
return this.MemberwiseClone(); // Creates a shallow copy
}
}



Since it is confusing if Clone uses shallow or deep copy, IClonable is deprecated.



public class Customer {

public Customer ShallowCopy()..

public Customer DeepCopy()...
}



3. Best Practices

Rule # 13

Throw exceptions. Do not return integer error code or bool.

Command Pattern - Encapsulate method invocation

The command pattern allows you to decouple the requester of an action (i.e. the object which wants to invoke the method) from the object that actually performs the action. A command object encapsulates a request to do something on a specific object.

Or in other words, objects are used to represent actions. A command object encapsulates an action and its parameters.


There are two objects involved : Invoker and Receiver



class Invoker{

Receiver receiver = null;

void Invoker(Receiver receiver){
this.receiver = receiver;
}

void Method(){
receiver.M1();
}
}

class Receiver{
void M1()
}



In the example above, the invoker and receiver are not decoupled. The invoker knows about the receiver.

Invoker -> Receiver

Now if we want to decouple the invoker and receiver, an option is to let invoker know only about command objects.

Invoker -> Command -> Receiver



public interface Command{
void Execute()
}

public interface ConcreteCommand : Command{

Receiver receiver = null;

public ConcreteCommand(Receiver rcv){
receiver = rcv
}

public void Execute(){
rcv.M1()
}
}

class Invoker{

void Method(){
cmd.Execute();
}

void SetCommand(Command cmd){
}
}


So command pattern gives us a way tp package a piece of computation (receiver and a set of actions) and pass it as a first class objects.

But an important question is still unanswered. Who creates object of concrete command and calls the SetCommand of Invoker object ? Well... it is the client which does that.

Uses of command pattern

1. Implementing thread pools and job schedulers.

2. Macro commands

3. Logging requests