这个Ruby类的设计真的很糟糕吗?

时间:2012-08-24 10:48:54

标签: ruby oop

我对OOP很陌生,我担心我写的这门课真的很糟糕。它似乎违背了OOP的几个原则:

  1. 它不包含自己的数据,但依赖于yaml文件 值。
  2. 需要按特定顺序调用其方法
  3. 它有很多实例变量和方法
  4. 然而,确实有效。它很健壮,但我每次添加页面元素时都需要修改源代码以添加新的getter方法

    它是自动化测试套件中使用的html文档的模型。我一直在想,有些方法可以放在子类中,但是我担心我会有太多的类。

    您怎么看?

    class BrandFlightsPage < FlightSearchPage
    
      attr_reader :route, :date, :itinerary_type, :no_of_pax,
                  :no_results_error_container, :submit_button_element
    
      def initialize(browser, page, brand)
        super(browser, page)
    
        #Get reference to config file
        config_file = File.join(File.dirname(__FILE__), '..', 'config', 'site_config.yml')
    
        #Store hash of config values in local variable
        config = YAML.load_file config_file
    
        @brand = brand        #brand is specified by the customer in the features file
    
        #Define instance variables from the hash keys
        config.each do |k,v|
          instance_variable_set("@#{k}",v)
        end
    
      end
    
      def visit
        @browser.goto(@start_url)
      end
    
      def set_origin(origin)
        self.text_field(@route[:attribute] => @route[:origin]).set origin
      end
    
      def set_destination(destination)
        self.text_field(@route[:attribute] => @route[:destination]).set destination
      end
    
      def set_departure_date(outbound)
        self.text_field(@route[:attribute]  => @date[:outgoing_date]).set outbound
      end
    
      def set_journey_type(type)
        if type == "return"
          self.radio(@route[:attribute]  => @itinerary_type[:single]).set
        else
          self.radio(@route[:attribute]  => @itinerary_type[:return]).set
        end
      end
    
      def set_return_date(inbound)
        self.text_field(@route[:attribute]  => @date[:incoming_date]).set inbound
      end
    
      def set_number_of_adults(adults)
         self.select_list(@route[:attribute]  => @no_of_pax[:adults]).select adults
      end
    
      def set_no_of_children(children)
        self.select_list(@route[:attribute]  => @no_of_pax[:children]).select children
      end
    
      def set_no_of_seniors(seniors)
        self.select_list(@route[:attribute]  => @no_of_adults[:seniors]).select seniors
      end
    
      def no_flights_found_message
        @browser.div(@no_results_error_container[:attribute] => @no_results_error_container[:error_element]).text
        raise UserErrorNotDisplayed, "Expected user error message not displayed" unless divFlightResultErrTitle.exists?
      end
    
      def submit_search
        self.link(@submit_button_element[:attribute] => @submit_button_element[:button_element]).click
      end
    end
    

1 个答案:

答案 0 :(得分:0)

如果这个类被设计为Facade,那么它的设计就不那么糟糕了。它提供了一种连贯的统一方式来执行依赖于各种不相关行为持有者的相关操作。

关注点似乎很差,因为这个类基本上耦合了所有各种实现细节,这可能会让维护变得有些棘手。

最后,需要按特定顺序调用事实方法可能会暗示您正在尝试建模状态机 - 在这种情况下,它可能应该分解为几个类(每个“状态”一个) 。我认为没有“太多的方法”或“太多的课程”指向你达到的目标,事实上你需要每个类提供的功能是连贯的和有意义的。绘制线的位置由您和您的特定实现的域要求决定。