4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

継承をさせるかMixinさせるか考えてみた

Posted at

最近コードを書いている時にDRYなコードを書くのには親クラスを作って継承させるべきなのかModuleでMixinするべきなのか、どっちが良いのか整理して考えてみた。
最初にお断りをしておくと、多分どちらでも問題ないと思うし、好みの問題だと思います。

##ある高校の先生を例に考えてみる。

teacher.rb
class Teacher
  def prepare_lesson
  	#授業の予習をする
  	@naiyou = "教科書を読んでくる"
  end
  def lesson
    #授業をする
    @naiyou.show
  end
  def create_test
    #英語のテストを作成
    @test = "先生が考えてくる"
  end
  def examine
    #テストを実行する
    @test.exec
  end
  def check_test
    #テストを採点
    @test.check
  end
  
  etc...
end

先生のやる事は挙げればきりがないが例えば上記のような事をすると考えよう。
でも先生は1人で数学や英語、化学や国語を教えたりするスーパーマンではない。もしそんなスーパーマンがいたらコードの中身はきっとifやcaseで埋め尽くされてしまう。

##どうしようか・・・ 継承 or Mixin
そうならないように役割をもう少し分けて共通項はDRYにした方がいいよねと思い立った故に、あれ継承?Mixin?
授業の予習や、テストを作るといった事は教科によって内容が変わるのでそれぞれの専門のクラスに持たせるとするが授業をしたりテストを実施するのは教科の内容にかかわらず鐘がなってから終わるまで準備してきたもの生徒たちに提供するだけなので親クラスやモジュールにまとめることにする。

math_teacher.rb
class Teacher 
  def lesson
    @naiyou.show
  end
  def examine
    @text.exec
  end
end

class Teacher::MathTeacher < Teacher
  def prepare_lesson
  	#数学の授業の予習をする
  	@naiyou = "数学の問題をといてくる"
  end
  def create_test
    #数学のテストを作成
    @test = "数学の教科書から作る"
  end
end

class Teacher::EnglishTeacher < Teacher
  def prepare_lesson
  	#英語の授業の予習をする
  	@naiyou = "英語の教科書を読んでくる"
  end
  def create_test
    #英語のテストを作成
    @test = "英語の教科書から作る"
  end  
end
english_teacher.rb
module Teacher
  def lesson
    @naiyou.show
  end
  def examine
    @test.exec
  end
end

class Teacher::MathTeacher
  include Teacher
  def prepare_lesson
  	#数学の授業の予習をする
  	@naiyou = "数学の問題をといてくる"
  end
  def create_test
    #数学のテストを作成
    @test = "数学の教科書から作る"
  end
end

class Teacher::EnglishTeacher
  include Teacher
  def prepare_lesson
  	#英語の授業の予習をする
  	@naiyou = "英語の教科書を読んでくる"
  end
  def create_test
    #英語のテストを作成
    @test = "英語の教科書から作る"
  end  
end

上は継承 下はMixin
この状態であれば、結論付けられないので他のクラスを登場させてみる。

##生徒クラス登場

student.rb
class Student
  def take_lessons
    #授業を受ける
  end
  def move_to_a gymnasium
  	#体育館に移動する
  end
end

ここで生徒クラスを登場させてみる。生徒は教師と大きく関わりを持つが教師がやるべきことと生徒がやるべきことは同じじゃない。 そん中でも教師と生徒が同じ動作をすることはある。例えば全校集会の為に体育館に移動するとか。 生徒クラスにも教師クラスにも体育館に移動するメソッドは全く同じであるが、2つを内包するような上位概念があるだろうか? schoolクラスを作る? schoolクラスからインスタンス化されたオブジェクトはそれ単体でも実行できる。 学校というオブジェクトが体育館に移動するという主語になるかと言われると気持ちが悪くて想像したくない。

school.rb
class School
  def move_to_a_gymnasium
    #体育館に移動する
  end
end

class Teacher < School
  ...#その他
end  

class Student < School
  ...#その他
end

Teacher.new.move_to_a_gymnasium
Student.new.move_to_a_gymnasium
School.new.move_to_a_gymnasium !?!?!?!?

そこで、こんな時こそ微妙な距離感の2つのクラスの間にはModuleでMixinするというのがあっているのではないかと思いました。ということで全校集会は学校のイベントなのでSchoolEventモジュールを用意

school_event.rb
module SchoolEvent
  def move_to_a_gymnasium
    #体育館に移動する
  end
end

class Teacher
  include SchoolEvent
  ...#その他
end  

class Student
  include SchoolEvent
  ...#その他
end

Teacher.new.move_to_a_gymnasium
Student.new.move_to_a_gymnasium

##結論
プレフィックスを持つようなグループに分けられるようなクラスをDRYにする時は親クラスを用いて、汎用的な共通の処理が必要な場合はModule化してMixinを使ってあげるというのが良いかなと思いました。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?