# Foundation - Open Closed Principle

The acronym SOLID is quite popular in the OOP realm, but I tend to notice that the “O” which stands for Open Closed Principle tends to get overlooked.

## What is this principle?

The Open-Closed Principle (OCP) states that software entities (classes, modules, methods, etc.) should be open for extension, but closed for modification.

Enough about theory let’s see an example.

class ReportService

def initialize(user)
@user = user
end

def generate
send_report(extensive_report)
else
send_report(basic_report)
end
end

private

def basic_report
# generate a limited report version for the last 30 days
end

def extensive_report
# generate an extensive report version for the last 90 days
end

def send_report(data)
# send content to user.email_address
end
end


I’m generating and sending a report based on the user subscription model in this service class. The new requirement introduced a new type of membership, let’s name it “VIP”. The acceptance criteria are:

For users with a “VIP” membership, add a suggestion section to the report and send an SMS notification with the email.

The typical way of handling this new change would be to go and edit the generate method by adding a new if condition. That’s how the OCP principle isn’t respected as it should be closed for modification but open to extensions. To achieve that we can use the strategy pattern.

class UserReport

def initialize(user)
@user = user
end
def send_report
raise NotImplementedError
end

def prepare_data
raise NotImplementedError
end

private

# format content for the email template
# send the email to the specified address
end

end

class BasicReport < UserReport

def send_report
end

def prepare_data
# generate a limited report version for the last 30 days
end
end

def send_report
end

def prepare_data
# generate an extensive report version for the last 90 days
end
end

class VIPReport < UserReport

def send_report
end

def prepare_data
# generate an extensive report version for the last 90 days with a suggestion section
end

private
# send a notification sms with a customizable text content
end
end

class ReportService

def initialize(user_report)
@user_report = user_report
end

def generate
user_report.send_report
end
end

## Usage example

report_service = ReportService.new(VIPReport.new(vip_user))
report_service.generate


This is a simplified example but in real-life cases, you will notice a lot of if or case conditions based on a specific field or type. These conditions tend to affect most methods until they start spiraling out of control.

That’s it, so have fun and keep coding 🙂