Friday, November 23, 2007
IThis, IThat, ITheOther
I have seen projects where every class had implemented an interface by default. The interfaces always had the same names as the classes except they were prefixed with an (I). I don't call this good design. The flexibility that an interface gives you has a cost. If an interface is not paying for this cost it should be removed. Only use interfaces when the flexibility is required. It is often difficult to tell in advance where this flexibility is needed so it is usually best to add an interface when the flexibility is required. Also instead of using the (I) prefix I prefer to name the interface by how the client will use the class. So instead of creating and IBook interface for a Book class, I could create a Readable interface instead. Removing the last trace of Hungarian notation from my code.
Wednesday, November 21, 2007
Singleton Anti-Pattern
The Singleton pattern is probably the most over used design pattern there is. Singletons are the same as global variables and make object collaboration less visible. They violate the Single Responsibility Principle mixing an object with its creation logic. They also create difficult to test code because they bind you to the exact type of the Singleton object and Singletons persist state causing test order to be dependent.
A Singleton object should be rarely used and when used it should be only used to solve a performance issue or as a last resort when parameter passing becomes very difficult.
A Singleton object should be rarely used and when used it should be only used to solve a performance issue or as a last resort when parameter passing becomes very difficult.
Thursday, November 8, 2007
What makes an excellent developer excellent?
Is it his knowledge of C# or Java Syntax? Is it his knowledge of every corner of every obscure framework? I don't think so. It is important to know what is possible in a language or framework but you can always lookup the fine details when you need to.
This reminds me of a story of when one of Einstein's colleagues asked him for his telephone number one day. Einstein reached for a telephone directory and looked it up. "You don't remember your own number?" the man asked, startled. "No," Einstein answered. "Why should I memorize something I can so easily get from a book?"
It is the developer’s knowledge of good object oriented design principles and domain modeling that makes a great developer stand out. If you are not strong in these areas it will be very difficult for you to Google them as you go.
This reminds me of a story of when one of Einstein's colleagues asked him for his telephone number one day. Einstein reached for a telephone directory and looked it up. "You don't remember your own number?" the man asked, startled. "No," Einstein answered. "Why should I memorize something I can so easily get from a book?"
It is the developer’s knowledge of good object oriented design principles and domain modeling that makes a great developer stand out. If you are not strong in these areas it will be very difficult for you to Google them as you go.
Tuesday, November 6, 2007
Replace With Direct Cast
An instance of the as operator should always be followed by a check against null.
Customer customer = obj as Customer;
if(customer != null){
customer.Update();
}
If you don't want to check against null than refactor to a direct cast.
(obj as customer).Update;
If the direct cast fails you will get an InvalidCastException instead of a NullReferenceException which will be easier to diagnose.
Customer customer = obj as Customer;
if(customer != null){
customer.Update();
}
If you don't want to check against null than refactor to a direct cast.
(obj as customer).Update;
If the direct cast fails you will get an InvalidCastException instead of a NullReferenceException which will be easier to diagnose.
Monday, November 5, 2007
Remove Unneeded Property
If you have a property that looks like the following just remove it. It is not adding any value.
public string PositionTitle
{
get
{
return this.positionTitle;
}
set
{
this.positionTitle = value;
}
}
Refactoring tools such as Resharper make encapsulating a field simple. So you can always refactor to the property later if you find that you need it.
Now doesn't the following code look so much nicer?
public string positionTitle;
public string PositionTitle
{
get
{
return this.positionTitle;
}
set
{
this.positionTitle = value;
}
}
Refactoring tools such as Resharper make encapsulating a field simple. So you can always refactor to the property later if you find that you need it.
Now doesn't the following code look so much nicer?
public string positionTitle;
Wednesday, October 24, 2007
Replace multidimensional if condition with double dispatch.
If you have a series of if conditions that vary in two dimensions it may be possible to replace the conditionals with double dispatch.
public class passenger
{
public Vehicle vehicle;
public string type;
public void travel()
{
if (vehicle.Type == "Car")
{
if (this.Type = "Rich")
{
RideInLimo();
}
else if (Passenger.Type = "Poor")
{
Drive();
}
else if (vehicle.Type = "Airplane")
{
if (this.Type = "Rich")
FlyInPrivateJet();
else if (Passenger.Type = "Poor")
{
FlyCoach();
}
}
}
}
}
In the above example the first refactoring that I would like to apply is Replace Type Code with Class. However the way a person travels does not only depend on the type of vehicle he uses but also the type of person they are as well. This problem can be solved by passenger passing itself as a parameter to the vehicle class. Then the vehicle class can use method overloading to create to versions of the travel method for each type of person.
Here is the refactored code.
public class Passenger
{
public Vehicle vehicle;
public void Travel()
{
vehicle.Travel(this);
}
}
public class Car : vehicle
{
public void Travel(RichPersion Passenger)
{
RideInLimo();
}
public void Travel(PoorPersion Passenger)
{
Drive();
}
}
public class Plane : vehicle
{
public void Travel(RichPerson Passenger)
{
FlyInPrivateJet();
}
public void Travel(PoorPerson Passenger)
{
FlyCoach();
}
}
One drawback of using this approach is that it violates the Open Close Principle because you will have to add a new version of the travel method on the vehicle object for each new person type that you add to your application.
public class passenger
{
public Vehicle vehicle;
public string type;
public void travel()
{
if (vehicle.Type == "Car")
{
if (this.Type = "Rich")
{
RideInLimo();
}
else if (Passenger.Type = "Poor")
{
Drive();
}
else if (vehicle.Type = "Airplane")
{
if (this.Type = "Rich")
FlyInPrivateJet();
else if (Passenger.Type = "Poor")
{
FlyCoach();
}
}
}
}
}
In the above example the first refactoring that I would like to apply is Replace Type Code with Class. However the way a person travels does not only depend on the type of vehicle he uses but also the type of person they are as well. This problem can be solved by passenger passing itself as a parameter to the vehicle class. Then the vehicle class can use method overloading to create to versions of the travel method for each type of person.
Here is the refactored code.
public class Passenger
{
public Vehicle vehicle;
public void Travel()
{
vehicle.Travel(this);
}
}
public class Car : vehicle
{
public void Travel(RichPersion Passenger)
{
RideInLimo();
}
public void Travel(PoorPersion Passenger)
{
Drive();
}
}
public class Plane : vehicle
{
public void Travel(RichPerson Passenger)
{
FlyInPrivateJet();
}
public void Travel(PoorPerson Passenger)
{
FlyCoach();
}
}
One drawback of using this approach is that it violates the Open Close Principle because you will have to add a new version of the travel method on the vehicle object for each new person type that you add to your application.
Monday, October 22, 2007
Move Foreign Method to Server Class
When I am working with code that is not object oriented I often see a bunch of objects that just contain data and not much behavior. These methods are often passed to helper classes that perform the real work.
Class MyHelperClass
{
public static void DoSomething(MyObject thing)
{
Dothis(thing.This);
Dothat(thing.That);
DoTheother(thing.Other):
}
}
Whenever I see static helper functions I look at the parameter list for objects that would be a better home for the function.
This specific instance of the Move Method refactoring is kind of the reverse of the Foreign Method refactoring. So my name for this refactoring is "Move Foreign Method to Server Class"
Class MyHelperClass
{
public static void DoSomething(MyObject thing)
{
Dothis(thing.This);
Dothat(thing.That);
DoTheother(thing.Other):
}
}
Whenever I see static helper functions I look at the parameter list for objects that would be a better home for the function.
This specific instance of the Move Method refactoring is kind of the reverse of the Foreign Method refactoring. So my name for this refactoring is "Move Foreign Method to Server Class"
Subscribe to:
Posts (Atom)
