Let's say we have the following business requirements:
We have a list of dishes. They have a name and a list of ingredients. The restaurant owner always wants to have a dish (and only one) marked as the "main" dish.
Let's suppose we are using an OOP approach, and we have two possible designs (I'm using python but it should not be relevant):
Design 1
class Dish:
name: str
ingredients: List[Ingredient]
is_main: bool
In this approach, we represent the main dish
requirement as a field inside our object. This has, among others, the following implications for the consumer of this class, let's say, a Menu
class:
class Menu:
dishes: List[Dish]
def __init__(self, dishes: List[Dish]):
self.dishes = dishes
if self.get_main_dish() is None:
raise ValueError("You must provide one main dish")
def get_main_dish() -> Dish:
for dish in self.dishes:
if dish.is_main:
return dish
Design 2
Using the Interface Segregation Principle, someone may suggest the following approach:
from abc import ABC
class DishInterface(ABC):
name: str
ingredients: List[Ingredient]
class NormalDish(DishInterface):
name: str
ingredients: List[Ingredient]
class MainDish(NormalDish):
is_main: bool
Then the Menu
object would be more or less the same, but checking the type of the dish instead of one of its attributes:
class Menu:
dishes: List[DishInterface]
def __init__(self, dishes: List[DishInterface]):
self.dishes = dishes
if self.get_main_dish() is None:
raise ValueError("You must provide one main dish")
def get_main_dish() -> MainDish:
for dish in self.dishes:
if isinstance(MainDish, dish):
return dish
Question
Is this correct? Does this offer any advantages? I think Design 1 is better because it is simpler, but other members of the team suggest Design 2. I want to fully understand why that approach would be better in the long run.
Just to clarify, I see the point of ISP, but I'm not sure that it's applicable here because being the main dish
is something arbitrary defined by the customer. Also it seems a little bit weird to me to have to check the type of the class, because that is usually a code smell in OOP.