Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am using a class through a dll to which I do not have direct control. So in effect, I am only a client of this class.

The class represents a form that can be printed, sent to clients and tracked in the system. I need to calculate two types of dates after which, if the form is received it is considered late.

Rather than simply calculate the late dates in the method where I am already handling the form, I want to extract the algorithm for calculating the late dates in a separate class as it is complicated and can be subject to change for administrative reasons.

Since I cannot modify the original class. I came up with these possible solutions:

(For reference the code is in C# 4/.Net 4.)

A- Create a FormLateDateCalculator class that has methods to return a late date for a given form.

B- Create a FormLateDate class that takes a form in it's constructor and has a property for each type of late date.

C- Create two extension methods on the Form class that calculate the late dates.

While all three of these methods work (and I am sure there are others), I would like to know which is the best in regards to object-oriented design and why?

share|improve this question
    
Why would you limit yourself to the Object Oriented paradigm in a multi-paradigm language like C# ? –  Matthieu Jan 27 '12 at 20:04
    
@MAtthieu: That's a really good observation. I'm open to more functional answers if you think they offer benefits. –  Gilles Jan 27 '12 at 20:07
    
It's a good question anyway =) You could edit it to open this door explicitly. The third option (C) is already outside of the realm of pure OO as explained by Eric Lippert. –  Matthieu Jan 27 '12 at 20:16

4 Answers 4

up vote 7 down vote accepted

I'd use approach A and hide it behind an interface, since it'll make the algorithm easily exchangeable where you use it.

I'd only use B when I have to store/cache multiple values that are created by a single algorithm. If the costs of a calculation are cheap and I only have to calculate two dates then I'd stick with A and calculate the dates whenever necessary. You can also use a combination of A and B where B is the container and contains the strategy interface (A) internally. But, as I said, I'd only create such a container if I really have to deal with many values (more than 4?)

I'd refrain from the extension methods as you can't have multiple implementations and as you can't interchange the algorithm easily during runtime, which may or may not be a requirement some day, who can predict the future after all?

Edit:

...separate class as it is complicated and can be subject to change for administrative reasons.

Use a strategy pattern. Will you need to have half the forms calculated with the old algorithm and the other half calculated with a newer algorithm or even worse? Will it be likely that you need two or more implementations of the algorithm simultaneously? Do you want to keep the algorithms or configure which one to use? If you have to answer one of these questions with "yes" then C is not an option anymore.

Option C is plain and simple and totally does the job when you are only ever going to need a single algorithm in place for every point in time.

share|improve this answer
    
As I dug deeped into the problem I realized - A: I would need to call a webservice to be able to calculate the date, B: I would need some info on the form that would be calculated by a colleague of mine who agreed to supply me with a Specification (right now I have only it's interface that I mock in my tests). –  Gilles Jan 27 '12 at 20:37

All options are valid, I don't see anything particularly bad about any of them (well, maybe A unless it's a static class... but that logically resolves to C eventually anyway) but I see C as being the one I would choose. Here's why:

  1. In code, you'll already have a form, and that's really all you should need to find out if it's late.
  2. myForm.IsLate() or myForm.IsLateOn(DateTime) is short and perfectly clear.
  3. Future developers will see this and not have to question what its purpose is. The static class can be named FormExtensions and there should be no confusion.
share|improve this answer
    
But you can't have multiple implementations and the algorithms are subject to change and maybe need to be made interchangeable someday. Then you'd have to create a strategy anyway and use extension methods as some sort of factory. In terms of maintainability I'd refrain from C. –  Falcon Jan 27 '12 at 19:57
    
I like extensions. Clean and simple. But They are not pure OO, cited here also. That's definetly not a reason enough to not use them as Eric Lippert explains. –  Matthieu Jan 27 '12 at 20:03
    
@Matthieu: I like extension methods, too, but not for an algorithm implementation that possibly needs to be interchangeable. Maybe some day he wants to have a "calculation mode selector" somewhere in the UI or Business Logic? –  Falcon Jan 27 '12 at 20:05
    
@Falcon : your point is valid. I wish I could make my mind on the three choices offered considering your point and YAGNI and my experiences, but then I would write an answer of my own =) –  Matthieu Jan 27 '12 at 20:13
    
I really liked your answer and gave it a +1. In the end I chose another because of implementation details that came up when I started digging deeper in the problem. Your answers is as valid in a more general sense. –  Gilles Jan 27 '12 at 20:35

I would go with option A. It appears you have to calculate 2 different types of "due by" dates already, with things being subject to change, 1 of which could be adding a new means of determining lateness. Abstracting lateness calculations to another class lets you use the strategy pattern to figure out when the form is late.

For reference on the strategy pattern:

Wikipedia

DoFactory

share|improve this answer

Abstract it down first.

Look at the overall behavior before jumping into an implementation.
Forget the details and isolate the behavior - What are you actually trying to do?

If you think you are trying to determine if a form has arrived late, you are not abstracting it enough. Ask yourself what the code needs to do to be able to identify and handle forms that arrive late? The code needs to 1) identify if a form is late and 2) handle it. In other words, you are trying to 1) evaluate a condition and 2) trigger functionality based on that evaluation.

This is the functionality that you should encapsulate for re-use - the first, but almost certainly not the last, implementation being the specific late date issue.

That would speak to me of the following things... An interface that provides a specification for classes that can evaluate a condition and trigger a method when that condition is true. I am sure there is a pattern for this even though I couldn't name it. At least one implementation of that interface that checks for late dates and performs required processing. A class which represents a list of these, I'll call them validators, which has a performValidations() method that takes the form as input and runs all the validators on it.

Some people will say that you should just code for the specific behavior being asked for, meaning forget the interface and just code the late date specific code in a method or class somewhere - I say that as soon as you do that, you will be asked to provide another thing just like it, or you will discover that there are already many other requirements that could be handled the same way.

Bottom line - identify and isolate the behaviors underlying the functionality you want to provide, and provide the desired functionality as a symptom of the operation of these behaviors.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.