What good ruby ​​idioms for breaking a large class into modules?

I have a large class with many methods, and it starts to get a little disorganized and hard to navigate. I would like to break it down into modules, where each module is a set of class and instance methods. Maybe something like this:

UPDATE: I realized this is a pretty bad example. You probably won’t want to transfer checks or attributes from the main class.

class Large
  include Validations
  include Attributes
  include BusinessLogic
  include Callbacks
end

After reading Yehuda's “Best Ruby Idioms” post , I am curious how others solve this problem. Here are two methods that I can think of.

First method

module Foo
  module Validations
    module ClassMethods
      def bar
        "bar"
      end
    end

    module InstanceMethods
      def baz
        "baz"
      end
    end
  end

  class Large
    extend Validations::ClassMethods
    include Validations::InstanceMethods
  end
end

Second method

module Foo
  module Validations
    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods
      def bar
        "bar"
      end
    end

    def baz
      "baz"
    end
  end

  class Base
    include Validations
  end
end

My questions:

  • Is there a better way to do this?
  • How do you get a single-line mixin module for a set of class / instance methods with the least amount of magic?
  • , ?
  • ?
+3
5

, ( Ruby), . , , . , , , .

: , - : /. . , , , . , .

+10

, , , , - :

  • ?
  • ?

1 - , 2 - , IMHO, , , .

, , , , , . .

- , - A C, , , .

+3

, , , , .

( ) , , : concerned_with

( readme)

# app/models/user.rb
class User < ActiveRecord::Base
  concerned_with :validations,
                 :authentication
end

# app/models/user/validations.rb
class User < ActiveRecord::Base
  validates_presence_of :name
end

#app/models/user/authentication.rb
class User < ActiveRecord::Base
  def self.authenticate(name, password)
    find_by_name_and_password(name, password)
  end
end
+1

foo.rb
foo/base.rb
foo/validations.rb
foo/network.rb
foo/bar.rb

foo.rb -

class Foo
  include Foo::Base
  include Foo::Validations
  include Foo::Network
  include Foo::Bar
end

, , . . , , , , . , .

BEWARE: Rails , , , . , , , . , , Ruby, , , foo.rb foo/directory Rails ( , ).

0

Ruby , , , .

, , , - - . Ruby , , . :

class Dog
  def initialize(name)
    @name = name
  end

  def bark  
    "woof"
  end

  def fetch(object)
    "here that #{object}"
  end

  def sit
    "sitting down"
  end

  private
  attr_accessor :name
end

, , . , . , , , , , !? , :

class Tricks
  def initialize(name)
    @name = name
  end

  def fetch(object)
    "here that #{object}"
  end

  def sit
    "sitting down"
  end

  def come_when_called(my_name)
    "I'm coming" if my_name == name
  end

  def put_toy_away(object)
    "#{fetch(object)}, I'll put it away"
  end

  private 
  attr_reader :name
end

class Dog
  def initialize(name)
    @name = name
  end

  delegate :sit, :fetch, :come_when_called, :put_away_toy, to: :tricks_klass

  def bark  
    "woof"
  end

  private
  attr_accessor :name

  def tricks_klass
    @tricks_klass ||= Tricks.new(name)
  end
end

, Dog , , . , Tricks , ( ).

Now we can have a Cat class that delegates responsibility for this Tricks class, although it would be one smart Cat!

Now you can also use the Tricks class yourself, so that the force that encapsulates single behavior in your class. You can even separate this behavior even more, but only you, as a developer, know whether it is worth it!

0
source

Source: https://habr.com/ru/post/1726861/


All Articles