tags:

views:

85

answers:

3

I have an order edit and quote edit screen that are very similar. I want to try to avoid code like this:

if (order is Order)
    SetupScreenForOrder();
if (order is Quote)
    SetupScreenForQuote();

But maintaining two screens is not good either. If I create some common interface between a Quote and Order then how do you deal with fields like OrderNumber or QuoteDate?

What's the best way to handle this?

+1  A: 

I think a common interface between the two objects would be a good idea.

Perhaps define the uncommon fields as nullable and have the screen check for null and determine how to display those fields.

int? OrderNumber {get;set;}

DateTime? QuoteDate {get;set;}

EDIT: in response to JC's comment

Perhaps consider trying to take it a step further and, at least logically, consider an Order and a Quote to be the same kind of object but at different stages in the "Order lifecycle". I.e. a "Quote" is an order at the beginning of the lifecycle, whereas an "Order" is an order at the middle or end of the lifecycle.

You could have an OrderState property defined on your interface, and then your UI could use the OrderState property to decide how the quote/order should be displayed, rather than checking each piece of data individually.

If you feel that the problem is more that you have too many if statements in your UI, then perhaps consider creating small user controls to handle displaying chunks of the UI for either a quote or for an order. You could then either dynamically add the appropriate control (a quote control or an order controL) to your UI, or have both controls already added and just show/hide them as appropriate. I would caution, though, that this sounds like it could be a messy approach, so just be careful that the solution doesn't end up being more complicated than the problem that you're trying to solve.

Dr. Wily's Apprentice
I think this leads to the same code I posted since you will need to check the concrete type of IOrder. So I don't think making these fields nullable would gain anything.
JC
+1  A: 
Foo foo = GetFoo();
if (foo is Order) 
  ...
if (foo is Quote) 
  ...

If you don't want to write these conditionals, avoid referring to Order instances and Quote instances by their common parent type (if any).

Order order = GetOrder()
SetupScreen(order); // resolves to void SetupScreen(Order order)

Quote quote = GetQuote()
SetupScreen(quote); //resolves to void SetupScreen(Quote quote)
David B
+1  A: 

Often if the display screens for two classes are similar, it's because they have fields that are similar in function, even if they don't have the same name.

For example, it might be that each instance (of an order or a quote) will have a date displayed with it. So you might have an interface:

interface displayableInOrderAndQuoteList {
   Date getDisplayDate();
}

public class Order {
   private Date orderDate;

   public Date getOrderDate() { //used only when treating object as an order
       return orderDate;
   }

   public Date getDisplayDate() {//used when displaying object via interface
       return orderDate;
   }
}


public class Quote {
   private Date quoteDate;

   public Date getQuoteDate() { //used only when treating object as a quote
       return quoteDate;
   }

   public Date getDisplayDate() {//used when displaying object via interface
       return quoteDate;
   }
}

In other words, the interface represents questions you want to ask the object in order to build the screen. Each object decides how to answer those questions.

If the display is different enough that you need to ask the objects totally different questions, then you probably should have two screens.

JacobM