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
Saturday, October 18, 2008
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.
Since it is confusing if Clone uses shallow or deep copy, IClonable is deprecated.
3. Best Practices
Rule # 13
Throw exceptions. Do not return integer error code or bool.
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
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
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
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
Subscribe to:
Posts (Atom)