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.

Days before, I created Question, Quiz, and Main classes. One Quiz has one or more Questions. From the main class I first create Question objects (the constructor accepts an array of numbers). The Quiz is like when I display the questions I omit the last number of the array and the user will try to figure out that number. Then from Main I created a Quiz Object. From Main I only call methods of the Quiz class and from Quiz Class I only call methods in Question class.

Then I also created a web application (with JSP and Servlets) which uses the same Question and Quiz classes but not Main. Instead of Main I used JSP and Servlets to display the data. So without modifying the model classes(Quiz and Question) I am able to use them from other applications.

But now, I need to add a HINT, which will give the user hints for every questions. If I go and modify those 2 model classes, I am going to violate the Open-Close principle. If I am going to create a class called Hint(one hint per question) and extend from question class, it doesn't make a sense because Hint is not a Question. But Question has a hint.

Can you please guide how to have a HINT in my application so that I will use the previous classes without modification and violating any OOP concepts?

share|improve this question
    
Does a QuestionWithHint need any additional public methods that a Question does not have? –  Aaron Kurtzhals Aug 17 '12 at 13:55
add comment

4 Answers

up vote 5 down vote accepted

I don't see why you would want to be so picky about following OOP principles. OOP is great, and the principles are sound, but then again each project has it's own particularities. Wanting to be OOP-perfect at all costs sounds like a drawback to me.

The more I code, the more flexible I am with those principles. They are not here to make your life harder, they are here to make your coding cleaner. If your code is clean and makes sense, to hell with principles.

Adding a "hint" method to your question class, that returns nothing if there is no hint or that is not called from your apps that don't need it changes nothing to the portability of your code and your commitment to OOP.
As for extending the question class, it seems to me that you are having a nomenclature problem. Your issue is that if you call your extended question class "hint", it lacks sense because hint isn't a question. But in that case, if your extended class, instead of "hint", was called "question_with_hint", then it would make sense, right? You are calling it "hint" just to make it shorter and more usable. Call it "question_extended" if it eases your mind.

share|improve this answer
add comment

If the "hint" functionality applies to the whole hierarchy, then you no are not violating the open-closed principle by adding it to the superclass.

Open-closed principle is a guide that tells you not to modify an existing class when you need to add specialized behavior, but to extend instead (or dependency injection).

But when you are making a legitimate improvement to a base class, you are OK, as long as you don't fail to fullfill the contracts.

share|improve this answer
add comment

I don't see the OCP applying much to domain classes, but more to application and service classes. Don't let OCP stop you from building the domain in evolutionary steps. Instead, notice how patterns in the way you use outside libraries (the standard libraries, JDBC, JMS, Servlet, JSP, and so on) emerge, then push those into simple adapter classes that become increasingly Closed over time.

share|improve this answer
add comment

Abstraction

There are two ways to adhere to the Open-Closed Principle. The original definition of the principle expected you to use inheritance but it led to problems with great trees of inherited classes, just to add a field like you are doing. As Xananax says, you could make it "correct" by naming the class QuestionWithHint, but then what when you want to add tags, etc?

Uncle Bob wrote a piece in '96 which describes another approach, which had become popular by then, where you would rename the class QuestionWithoutHint, extract a Question interface from the QuestionWithoutHint class and then create a new one called QuestionWithHint, also implementing Question. You can then replace this around your code until there are no more references to QuestionWithoutHint and get rid of that class, renaming the new one to something more simple (QuestionImpl).

This is the more modern way to adhere to the OCP.

However, it is my strong belief that this should only be done for cases where logic is being replaced, not for adding new fields/properties, where existing code which uses the class will be unaffected. This is, after all, the problem that OCP aims to solve.

share|improve this answer
1  
The simpler approach (just modify the class, don't follow OCP) would be appropriate when the object's logic is not modified by the addition of new fields/properties. If you need to add the same field/property to several classes, you may make an interface for that field/property. If you have several different Questions that would have different logic depending on whether it has hints, extract Question into an interface. –  rwong May 15 '11 at 22:38
add comment

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.