tags:

views:

228

answers:

5

Hi All,

I want to develop a process() method. The method takes some data in the form of a data class, and processes it. The data classes are similar, but slightly different.

For example we have the following classes of data processDataObject_A, processDataObject_B and processDataObject_C.

Is it better to overload the method:

void process(processDataObject_A data)
{
//Process processDataObject_A here
}

void process(processDataObject_B data)
{
//Process processDataObject_B here
}

void process(processDataObject_C data)
{
//Process processDataObject_C here
}

OR have the concrete data classes extend some Abstract Data Class, and pass that to the process method and then have the method check the type and act accordingly:

void process(AbstractProcessDataObject data)
{
//Check for type here and do something  
}

OR is there some better way to address it? Would the approach change if this were to be a Web Method?

Thanks in advance

A: 

How about polymorphism on AbstractProcessDataObject - i.e. a virtual method? If this isn't appropriate (separation of concerns etc), then the overload would seem preferable.

Re web-methods; very different: neither polymorphism nor overloading are very well supported (at least, not on basic-profile). The detection option "Check for type here and do something" might be the best route. Or have different named methods for each type.


per request:

abstract class SomeBase { // think: AbstractProcessDataObject
    public abstract void Process();
}
class Foo : SomeBase {
    public override void Process() { /* do A */ }
}
class Bar : SomeBase {
    public override void Process() { /* do B */ }
}
SomeBase obj = new Foo();
obj.Process();
Marc Gravell
Would it be possible expand on the virtual method solution?
jheppinstall
see edit for detail
Marc Gravell
+6  A: 

I would go with:

process (data) {
   data.doProcessing();
}
Dev er dev
That on its own does nothing to indicate how that works - what methodology is being used, etc; if doProcessing() is virtual (polymorphism), what is the point of the process(data) method? Just call it directly.
Marc Gravell
+1: Delegate process() to the classes as a polymorphic method.
S.Lott
+1  A: 

The fact that your methods return void lead me to believe that you may have your responsibilities turned around. I think it may be better to think about this as having each of your classes implement an interface, IProcessable, that defines a Process method. Then each class would know how to manipulate it's own data. This, I think, is less coupled than having a class which manipulates data inside each object. Assuming all of theses classes derive from the same base class you could put the pieces of the processing algorithm that are shared in the base class.

This is slightly different than the case where you may have multiple algorithms that operate on identical data. If you need this sort of functionality then you may still want to implement the interface, but have the Process method take a strategy type parameter and use a factory to create an appropriate strategy based on its type. You'd end up having a strategy class for each supported algorithm and data class pair this way, but you'd be able keep the code decoupled. I'd probably only do this if the algorithms were reasonably complex so that separating the code makes it more readable. If it's just a few lines that are different, using the switch statement on the strategy type would probably suffice.

With regard to web methods, I think I'd have a different signature per class. Getting the data across the wire correctly will be much easier if the methods take concrete classes of the individual types so it knows how to serialize/deserialize it properly. Of course, on the back end the web methods could use the approach described above.

public interface IProcessable
{
    public void Process() {....}
}

public abstract class ProcessableBase : IProcessable
{
    public virtual void Process()
    {
        ... standard processing code...
    }
}

public class FooProcessable : ProcessableBase
{
    public override void Process()
    {
        base.Process();
        ... specific processing code
    }
}

...

IProcessable foo = new FooProcessable();
foo.Process();

Implementing the strategy-based mechanism is a little more complex.

Web interface, using data access objects

[WebService]
public class ProcessingWebService
{
    public void ProcessFoo( FooDataObject foo )
    {
        // you'd need a constructor to convert the DAO
        // to a Processable object.
        IProcessable fooProc = new FooProcessable( foo );
        fooProc.Process();
    }

}
tvanfosson
It's not necessary a good idea to place the processing in data classes. These classes may be used in many places and the processing might be specific to a particular use case. You don't want to have that always in the data class. Your second variant also has the same drawback that data classes must know anything about how they will be processed.Of course, since we do not have more detail about the classes all answers are highly speculative. We probably should learn more about the problem at hand before we come up with more advice...
Robert Klemme
+1  A: 

I second Marko's design. Imagine you need to add another type of data structure and process logic, say processDataObject_D. With your first proposed solution (method overloading), you will have to modify the class by adding another method. With your second proposed solution, you will have to add another condition to the type checking and execution statement. Both requires you to modify the existing code. Marko's solution is to avoid modifying the existing code by leveraging polymorphism. You don't have to code if-else type checking. It allows you to add new data structure and process logic without modifying the existing code as long as the new class inherits the same super class.

Studying Strategy Pattern of the design patterns will give you full theoritical understanding of the problem you are facing. The book "Head First Design Pattern" from O'Reilly is the best introduction I know of.

toshi
A: 

I believe the Strategy pattern would help you.

pablito