Принцип інтерфейсів (Interface Segregation Principle - ISP) є одним з п’яти принципів SOLID і стверджує, що клієнти не повинні залежати від інтерфейсів, які вони не використовують. Замість того, щоб визначати одне велике інтерфейс, котрий включає усі можливі методи, ISP підтримує ідею розділення цього інтерфейсу на менші, специфічні для клієнтів.
Основні ідеї ISP.
Розділення інтерфейсу - інтерфейси повинні бути невеликими та специфічними для клієнтів. Клієнти повинні залежати лише від тих інтерфейсів, які необхідні для їхньої роботи.
Мінімізація залежностей - клієнти не повинні отримувати методи, які для них не є необхідними. Збільшення кількості методів в інтерфейсі може призвести до зайвих або непотрібних залежностей.
Робота з інтерфейсами замість конкретних класів - клієнти повинні програмувати на основі інтерфейсів, а не конкретних класів. Це дозволяє легше замінювати реалізації інтерфейсів без впливу на клієнтський код.
В Ruby інтерфейси набагато менш формальні, оскільки мова не має строгого поняття інтерфейсу, як у Java або C#. Проте, в Ruby ми можемо використовувати модулі для створення схожого ефекту. Давайте розглянемо приклад:
# Поганий приклад з єдиним модулем
module Worker
def work
raise NotImplementedError, 'Subclasses must implement the work method'
end
def eat
raise NotImplementedError, 'Subclasses must implement the eat method'
end
def sleep
raise NotImplementedError, 'Subclasses must implement the sleep method'
end
end
class Programmer
include Worker
def work
puts "Programming..."
end
def eat
puts "Eating lunch..."
end
def sleep
puts "Sleeping at night..."
end
end
class Manager
include Worker
def work
puts "Managing projects..."
end
def eat
puts "Eating lunch..."
end
def sleep
puts "Sleeping at night..."
end
end
В цьому прикладі модуль Worker
включає методи work
, eat
і sleep
, але не всі класи, які його включають, можуть використовувати всі ці методи. Це може порушити принцип інтерфейсів (ISP), оскільки класи, можливо, не використовують всі методи інтерфейсу.
Тепер давайте розділимо цей модуль на менші, специфічні для класів модулі:
module Workable
def work
raise NotImplementedError, 'Subclasses must implement the work method'
end
end
module Eatable
def eat
raise NotImplementedError, 'Subclasses must implement the eat method'
end
end
module Sleepable
def sleep
raise NotImplementedError, 'Subclasses must implement the sleep method'
end
end
class Programmer
include Workable
include Eatable
include Sleepable
def work
puts "Programming..."
end
def eat
puts "Eating lunch..."
end
def sleep
puts "Sleeping at night..."
end
end
class Manager
include Workable
include Eatable
include Sleepable
def work
puts "Managing projects..."
end
def eat
puts "Eating lunch..."
end
def sleep
puts "Sleeping at night..."
end
end
Тепер класи включають лише ті модулі, які є для них важливими, виконуючи тим самим принцип інтерфейсів (ISP) - залежати лише від того, що необхідно.