Extending Ruby Code with the Open/Closed Principle
smiley khera(Immediate Joiner)
Full Stack Developer | ReactJS | Ruby on Rails | AngularJS | Crafting Web Solutions
The "Open for extension, but closed for modification" principle, also known as the Open/Closed Principle (OCP), is one of the key concepts in software design and development, particularly within the context of object-oriented programming. This principle states that software entities such as classes, modules, and functions should be open for extension but closed for modification. This means that the behavior of a module can be extended without modifying its source code.
In Ruby, adhering to this principle involves designing classes and modules in a way that allows their behavior to be extended via inheritance, modules, or other means, without changing the existing code. Here’s how you can apply this principle in Ruby:
Example Scenario
Imagine you have a system that calculates the area of various shapes. You start with a base class Shape and want to add new shapes without modifying the existing code.
Step-by-Step Implementation
class Shape
def area
raise NotImplementedError, "This method must be overridden in a subclass"
end
end
2. Create Subclasses for Specific Shapes:
class Circle < Shape
attr_reader :radius
def initialize(radius)
@radius = radius
end
def area
Math::PI * @radius ** 2
end
end
class Rectangle < Shape
attr_reader :width, :height
def initialize(width, height)
@width = width
@height = height
end
def area
@width * @height
end
end
3. Extend the System by Adding New Shapes without Modifying Existing Code:
领英推荐
class Triangle < Shape
attr_reader :base, :height
def initialize(base, height)
@base = base
@height = height
end
def area
0.5 * @base * @height
end
end
4. Use a Factory or Strategy Pattern to Handle Shape Creation (Optional):
This step can help in managing the creation and handling of different shapes without modifying the existing code.
class ShapeFactory
def self.create_shape(type, *args)
case type
when :circle
Circle.new(*args)
when :rectangle
Rectangle.new(*args)
when :triangle
Triangle.new(*args)
else
raise "Unknown shape type"
end
end
end
5.Using the Shapes:
shapes = [
ShapeFactory.create_shape(:circle, 5),
ShapeFactory.create_shape(:rectangle, 4, 6),
ShapeFactory.create_shape(:triangle, 3, 7)
]
shapes.each do |shape|
puts "The area of the #{shape.class} is #{shape.area}"
end
Explanation
By following this principle, your codebase becomes more maintainable and adaptable to change, as new functionality can be added with minimal impact on the existing system.