Skip to main content

Python Example

Violate OCP

  • potential issues:
    • if later, you want to add a new option or new question type to the quiz
      • e.g.: a range of values type
    • refer to Violate OCP Extended
def print_quiz(questions):
for question in questions:
print(question["description"])
if question["type"] == "boolean":
print("1. True")
print("2.False")
elif question["type"] == "multipleChoice":
for index, option in enumerate(question["options"]):
print(f"{index + 1}. {option}")
elif question["type"] == "text":
print("Answer: _______________")
else:
print("")


questions = [
{
"type": "boolean",
"description": "This video is useful.",
},
{
"type": "multipleChoice",
"description": "What is your favorite language?",
"options": ["CSS", "HTML", "JS", "Python"],
},
{
"type": "text",
"description": "Describe your favorite JS feature",
},
]

print_quiz(questions)

Violate OCP Extended

def print_quiz(questions):
# this allows us to extend new types, which passes the open portion of the open-closed principle
# when we add new features, it automatically extends the new questions and works
# thus, modification of the open portion is not required
for question in questions:
print(question["description"])
if question["type"] == "boolean":
print("1. True")
print("2.False")
elif question["type"] == "multipleChoice":
for index, option in enumerate(question["options"]):
print(f"{index + 1}. {option}")
elif question["type"] == "text":
print("Answer: _______________")
# this violates the closed portion of the open-closed principle
# this function should be closed and not allowed for modifications
# it should just work when new features are extended
elif question["type"] == "range":
print("Minimum: ______________")
print("Maximum: ______________")
else:
print("")


questions = [
{
"type": "boolean",
"description": "This video is useful.",
},
{
"type": "multipleChoice",
"description": "What is your favorite language?",
"options": ["CSS", "HTML", "JS", "Python"],
},
{
"type": "text",
"description": "Describe your favorite JS feature",
},
# this is ok to modify as it is just extending new feature
{
"type": "range",
"description": "What is the speed limit in your city?",
},
]

print_quiz(questions)

Pass OCP

# Polymorphic open-closed principle
class Question:
def __init__(self, description):
self.description = description

def print_question_choices(self):
print("")


class BooleanQuestion(Question):
def __init__(self, description):
super().__init__(description)

def print_question_choices(self):
print("1. True")
print("2. False")


class MultipleChoiceQuestion(Question):
def __init__(self, description, options):
super().__init__(description)
self.options = options

def print_question_choices(self):
for index, option in enumerate(self.options):
print(f"{index + 1}. {option}")


class TextQuestion(Question):
def __init__(self, description):
super().__init__(description)

def print_question_choices(self):
print("Answer: _______________")


class RangeQuestion(Question):
def __init__(self, description):
super().__init__(description)

def print_question_choices(self):
print("Minimum: ______________")
print("Maximum: ______________")


# this is open to be extended
# closed for modification as we do not need to touch this function
def print_quiz(questions):
for question in questions:
print(question.description)
question.print_question_choices()


# only need to extend new features here
questions = [
BooleanQuestion("This video is useful."),
MultipleChoiceQuestion(
"What is your favorite language?",
[
"CSS",
"HTML",
"JS",
"Python",
],
),
TextQuestion("Describe your favorite JS feature."),
RangeQuestion("What is the speed limit in your city?"),
]

print_quiz(questions)