views:

150

answers:

5

I understand that there are several questions on OOD; this one is not a duplicate (I hope) because of its specific nature - can a functionality that process data be a class?

First, some background.

This came up from a discussion my supervisor had with me. I was supposed to write a video loading class. His idea was to have a single Video class that loads itself.

I thought through it and came up with a Video class that stores the codec, filename, frame per second and more importantly the byte arrays, and a VideoLoader class that takes a filename, a reference to the Video class and then populate it.

My supervisor said this is not correct. "A class should always have a state". I assume he meant private members here. "The VideoLoader is just a bunch of processing functions. It shouldn't be a class". I argue that I am doing decoupling. The VideoLoader in the future could have an abstract base class in case we are using different libraries (currently FFMPEG) to load videos.

It still kind of bother me, though. OOD always describes finding the verbs and the nouns, and 'processing-only classes' rarely come out from OOD design. Are there guidelines in OOD for this?

+2  A: 

I agree with your approach.

Consider your VideoLoader a helper class that is used to instantiate or populate as you say the instances of Video. It is a part of a good design to separate responsibilities and not put it all into one entity. Anyway, in many object-oriented frameworks it is not possible to have standalone methods without wrapper classes.

If you wish to please your supervisor you could put a Load method in your Video class and make it the only way to instantiate videos.

public class Video
{
    private Video ()
    {
    }

    public Video Load (/* Parameters */)
    {
        Video video = new Video ();

        // Set up this video object

        return video;
    }
}

The way you are doing it actually has a term - Factory pattern.

Have a look here: Factory method pattern. This is exactly what you are doing. You use a factory to instantiate video classes of potentially various types (codec-dependent or else).

Developer Art
+2  A: 

I'm always a bit dubious of classes who's name ends in 'er', like Loader, Runner, Writer etc. Often, these get named that way becuase you either cannot at that momement think of a better name, or you haven't identified the underlying role of the class correctly. I'm not immune to this, only yesterday I created an "Echoer" class. Maybe today I'll find out what it really should be called.

Regarding the lack of state, yes, I would say if the class has no state and is just a bunch of functions there is something wrong. But I wouldn't worry about it too much, you'll probably soon identify what is wrong and find that fixing it introduces some state.

At the end of the day, obhject oriented design and programming is an iterative, explorative process. Don't be too concerened about getting things right first time - one of the greatest strengths of OO techniques is that changes and corrections (aka refactoring) can normally be made without breaking many, if any, other parts of the system.

anon
+1  A: 

That sounds fine to me, and the way you describe (provided the methods are non-static) it is an example of the Strategy pattern. I've never heard of any guideline indicating that classes must always have a state.

marijne
+1  A: 

I don't really understand this 'class must have state' argument. A class is just a way of encapsulating functionality. Whether it actually maintains internal state, or calculates answers on demand, and whether that state can be accessed or changed by a particular caller, are all implementation details that seem irrelevant to me.

The two patterns that come to mind are factory (mentioned by another poster) and flyweight. In both cases its quite reasonable to expect no state in the class that implements the pattern. In your case your VideoLoader class allows you to choose between Video implementations. As you say, this seems to be a clear case of useful decoupling (via Factory).

If I implement a Fibonacci class that calculates the Fibonacci sequence for an integer you provide, does it make any difference to you whether I actually calculate it, or provide you with a cached value stored internally as 'state'? As long as I give you the correct number when you ask for one, the contract is maintained.

An example of using flyweight objects with no state is to implement generic objects, like rocks or gold pieces in an RPG. Each gold piece is identical in every way, but you still would like to define multiple methods to allow interaction with the gold piece. For example, you might want to inspect the gold piece more closely, and receive some information. It makes sense to make this information available via the gold piece class. It makes no sense for each gold piece object to store identical state that can't change. A pointer to a piece of shared state is obviously correct. But from an external object's point of view the gold piece object looks just like any other object; just with an interface that is read-only.

ire_and_curses
A: 

VideoProcessor could have a state.

  1. Number of bytes processed.
  2. Number of errors during processing.
  3. Stage of processing.
akhilss