Search code examples
rubydependenciescircular-dependencysingle-responsibility-principle

Two Ruby Classes Depending on Each Other


I'm currently having a little trouble managing my dependencies whilst trying to maintain Single Responsibility and OOD.

I have a master class call Menu:

class Menu

  def initialize(dishes:, prices:, menuFormatter:)
    @dishes = dishes
    @prices = prices
    @menuFormatter = menuFormatter
  end

  def avaliable_dishes
    dishes.dishes_list
  end

  def dish_prices
    prices.prices_list
  end

  def formatted_menu
    menuFormatter.formatted_menu
  end

  private

  attr_reader :dishes, :prices, :menuFormatter
end

Now, the way I see it is that the Menu class pulls together all of the different parts of the menu, and supplies it to the hypothetical customer. The dishes are handled, updated, removed in their own class (Dishes), the prices are done in the same way (Prices) and then there is a separate class MenuFormatter who's responsibility is to take the contents of the Menu and turn it into a nicely arranged menu. Lines 17 to 19 are where my MenuFormatter class is called into action but my problem arises within that class:

class MenuFormatter

  def avaliable_dishes
    menu.avaliable_dishes
  end

  def dish_prices
    menu.dish_prices
  end

  def format_menu
    #Loop through dishes and prices and arrange them.
  end
end

The error i'm now faced with is that the MenuFormatter doesn't know what menu is because i've not defined it within the class. I'm unsure how to make my menu variable point to the instance of Menu so that it can have access to the dishes and prices.

I'd hoped not to give MenuFormatter access to Dishes or Prices as I feel that could lead to further coupling than necessary within my code.


Solution

  • How about passing the instance of menu itself as an argument to the format_menu method:

    def formatted_menu
      menuFormatter.formatted_menu(self)
    end
    

    Here, in the definition of an instance method of the Menu class, self refers to the instance of menu on which the formatted_menu method is called.

    And then in MenuFormatter:

    def formatted_menu(menu)
      # menu.dishes... 
      # menu.prices....
    end