銀行員からのRailsエンジニア

銀行員からのRailsエンジニア

銀行員から転身したサービス作りが大好きなRailsエンジニアのブログです。個人で開発したサービスをいくつか運営しており、今も新しいサービスを開発しています。転職して日々感じていること、個人開発サービス運営のことなどを等身大で書いていきます。

当ブログではアフィリエイト広告を利用しています

【Rubyによるデザインパターンまとめ14】DSL(ドメイン特化言語)

コードの品質向上のため、Rubyデザインパターンを解説した名著である Rubyによるデザインパターン で紹介されているデザインパターンを1つずつまとめており、今回が第14弾です。(毎週1つが目標です!)

前回の記事(インタプリタパターンのまとめ)はこちらです。
【Rubyによるデザインパターンまとめ13】インタプリタパターン - 銀行員からのRailsエンジニア

今回は DSLドメイン特化言語 についてまとめました。

Railsのコードで実際に使われている箇所をピックアップして説明しています。
f:id:ysk_pro:20200307105417p:plain

DSLドメイン特化言語)とは

ある特定の問題を解決するために専用の言語を定義するパターンです。

Railsでは、Validations・ActiveRecord・Rake・RSpecなど幅広く使われています。

文章の説明よりも実際のコードを見た方が分かりやすので、以下のコードをご覧ください。

コード

Railsのコードのmodelでよく目にする、以下のようなバリデーションを実装したコードはDSLを活用しています。

class Item < ActiveRecord::Base
  validates :title, length: { maximum: 40 }
end

上記のvalidatesは、Railsのコードの中の以下メソッドを呼び出しています。

def validates(*attributes)
  defaults = attributes.extract_options!.dup
  validations = defaults.slice!(*_validates_default_keys)

  raise ArgumentError, "You need to supply at least one attribute" if attributes.empty?
  raise ArgumentError, "You need to supply at least one validation" if validations.empty?

  defaults[:attributes] = attributes

  validations.each do |key, options|
    key = "#{key.to_s.camelize}Validator"

    begin
      validator = key.include?("::") ? key.constantize : const_get(key)
    rescue NameError
      raise ArgumentError, "Unknown validator: '#{key}'"
    end

    next unless options

    validates_with(validator, defaults.merge(_parse_validates_options(options)))
  end
end

rails/validates.rb at 526dd6472b3f3ab72ecc2538067b6c94f395fa36 · rails/rails · GitHub

バリデーションのために専用の言語/記法(例: validates :title, length: { maximum: 40 } )を作ることによって可読性を上げています。

おわりに

ここまで読んでいただきありがとうございます。

Rubyによるデザインパターン の中では、ファイルバックアップ機能を作成するオリジナルのコードを使って説明されていて分かりやすかったので、ご興味ある方は是非合わせてご覧ください。

Rubyによるデザインパターン

Rubyによるデザインパターン

次回は、メタプログラミングをまとめます。

来週も頑張ります!

(追記)
メタプログラミングについてまとめました!
是非合わせてご覧ください。
ysk-pro.hatenablog.com

【Rubyによるデザインパターンまとめ13】インタプリタパターン

コードの品質向上のため、Rubyデザインパターンを解説した名著である Rubyによるデザインパターン で紹介されているデザインパターンを1つずつまとめており、今回が第13弾です。(毎週1つが目標です!)

前回の記事(ビルダパターンのまとめ)はこちらです。
【Rubyによるデザインパターンまとめ11】ファクトリメソッドパターン - 銀行員からのRailsエンジニア【Rubyによるデザインパターンまとめ12】ビルダパターン - 銀行員からのRailsエンジニア

言葉での説明よりもコードを見た方が分かりやすいので、サンプルコードでの説明をメインにしています。

今回は インタプリタInterpreter)パターン についてまとめました。

f:id:ysk_pro:20200229160054p:plain

インタプリタパターンとは

クラスで表現した文法規則で構文を解析し、その結果得られた手順に基づいて処理を実行するパターンです。

Interpreter」は「通訳」という意味です。

文章の説明よりも実際のコードを見た方が分かりやすので、以下のサンプルコードをご覧ください。

サンプルコード

文字列をプラスマイナスできるプログラムを考えます。

class Word
  def initialize(value)
    @value = value
  end

  def execute
    @value
  end
end

class Plus
  def initialize(first, second)
    @first = first
    @second = second
  end

  def execute
    @first.execute + @second.execute
  end
end

class Minus
  def initialize(first, second)
    @first = first
    @second = second
  end

  def execute
    index = @first.execute =~ /#{@second.execute}/
    second_index = index + @second.execute.length
    @first.execute[0,index] + @first.execute[second_index..-1]
  end
end

class Interpreter
  def self.parse(input)
    @waiting_second_word = false
    words = []
    operations = []
    input.split.each do |value|
      if value =~ /^[^+-].*/ && !@waiting_second_word
        words << Word.new(value)
      else
        if symbol = operations.pop()
          first = words.pop
          second = Word.new(value)
          case symbol
          when /\A\+/
            words << Word.new(Plus.new(first, second).execute)
          when /\A\-/
            words << Word.new(Minus.new(first, second).execute)
          end
          @waiting_second_word = false
        else
          @waiting_second_word = true
          operations << value
        end
      end
    end
    words.pop.execute
  end
end

次のように実行すると

puts Interpreter.parse("おはよう + ございます - ござい")

このような結果になります。

おはようます

サンプルコードはこちらを参考にさせていただきました。
GitHub - piscolomo/ruby-patterns: Examples of Patterns in Ruby

おわりに

ここまで読んでいただきありがとうございます。

Rubyによるデザインパターン の中でも、ファイル検索のプログラムを作る過程を通じて説明されており分かりやすかったので、ご興味ある方は是非合わせてご覧ください。

Rubyによるデザインパターン

Rubyによるデザインパターン

次回は、DSLドメイン特化言語)をまとめます。

来週も頑張ります!

(追記)
DSLドメイン特化言語)についてまとめました!
是非合わせてご覧ください。
ysk-pro.hatenablog.com

【Rubyによるデザインパターンまとめ12】ビルダパターン

コードの品質向上のため、Rubyデザインパターンを解説した名著である Rubyによるデザインパターン で紹介されているデザインパターンを1つずつまとめており、今回が第12弾です。(毎週1つが目標です!)

前回の記事(ファクトリメソッドパターンのまとめ)はこちらです。
【Rubyによるデザインパターンまとめ11】ファクトリメソッドパターン - 銀行員からのRailsエンジニア

言葉での説明よりもコードを見た方が分かりやすいので、サンプルコードでの説明をメインにしています。

今回は ビルダ(Build)パターン についてまとめました。

f:id:ysk_pro:20200222105019p:plain

ビルダパターンとは

オブジェクトを作るのに大量のコードを書かなければいけない場合などに、オブジェクトの生成のためのコードを別のクラス(ビルダクラス)に分離するパターンです。

つまり、オブジェクトの生成手順(コード上ではコンストラクタ)を外出しします。複雑なオブジェクトの生成手順を分離することで、構造がシンプルになり、再利用性も高めることができます

文章の説明よりも実際のコードを見た方が分かりやすので、以下のサンプルコードをご覧ください。

サンプルコード

ユーザーのオブジェクトを作るプログラムを考えてみましょう。

まずはビルダパターンを使わずに実装してみます。

class User
  attr_accessor :first_name, :last_name, :birthday, :gender, :status, :email, :password

  def initialize(first_name, last_name, birthday, gender, status, email, password)
    @first_name = first_name
    @last_name = last_name
    @birthday = birthday
    @gender = gender
    @status = status
    @email = email
    @password = password
  end
end

このように実行すると、

user = User.new('テスト', '太郎', '1991-08-11', 1, 1, 'test@example.com', 'pass1234')
p user

次のようにオブジェクトができていることが分かります。

#<UserBuilder:0x00007f911d911f08 @user=#<User:0x00007f911d911ee0 @first_name="テスト", @last_name="太郎", @gender=1, @status=1, @email="test@example.com", @password="pass1234">>

このコードはオブジェクトの生成時に大量のパラメータを渡す必要があり、今後新しいパラメータが追加された場合などには、どんどん複雑になり分かりにくくなってしまいます

これをビルダパターンを使って書き換えてみましょう。

class User
  attr_accessor :first_name, :last_name, :birthday, :gender, :status, :email, :password
end

class UserBuilder
  attr_reader :user

  def initialize
    @user = User.new
  end

  def set_name(first_name, last_name)
    @user.first_name = first_name
    @user.last_name = last_name
  end

  def set_birthday(birthday)
    @user.birthday = birthday
  end

  def set_as_man
    @user.gender = 1
  end

  def set_as_woman
    @user.gender = 2
  end

  def set_as_active
    @user.status = 1
  end

  def set_login_credectiols(email, password)
    @user.email = email
    @user.password = password
  end
end

次のように実行すると先ほどと同じ結果となり、ユーザーのオブジェクトを作ることができました。

user_builder = UserBuilder.new
user_builder.set_name('テスト', '太郎')
user_builder.set_birthday('1991-08-11')
user_builder.set_as_man
user_builder.set_as_active
user_builder.set_login_credectiols('test@example.com', 'pass1234')
user = user_builder.user
p user

こうすることでオブジェクトの生成手順が分かりやすくなり、今後ユーザーと近いオブジェクトを作る際にはビルダクラスを共通化することもできるので再利用性も高まりました

今回のサンプルコードは、こちらのサイトを参考にさせていただきました。英語ですがとても分かりやすくて勉強になりました。
Builder design pattern in Ruby - kkempin’s dev blog - Medium

おわりに

ここまで読んでいただきありがとうございます。

Rubyによるデザインパターン の中でも、ビルダクラスを使ってリファクタリングしていく形式で分かりやすかったので、ご興味ある方は是非合わせてご覧ください。

Rubyによるデザインパターン

Rubyによるデザインパターン

次回は、インタプリタInterpreter)パターンをまとめます。

来週も頑張ります!

(追記)
インタプリタパターンについてまとめました!
是非合わせてご覧ください。
ysk-pro.hatenablog.com

【Rubyによるデザインパターンまとめ11】ファクトリメソッドパターン

コードの品質向上のため、Rubyデザインパターンを解説した名著である Rubyによるデザインパターン で紹介されているデザインパターンを1つずつまとめており、今回が第11弾です。(毎週1つが目標です!)

前回の記事(シングルトンパターンのまとめ)はこちらです。
【Rubyによるデザインパターンまとめ10】シングルトンパターン - 銀行員からのRailsエンジニア

言葉での説明よりもコードを見た方が分かりやすいので、サンプルコードでの説明をメインにしています。

今回は ファクトリメソッド(Factory Method)パターン についてまとめました。

f:id:ysk_pro:20200209075739p:plain

ファクトリメソッドパターンとは

オブジェクトの生成をファクトリメソッドに任せることで、クラス名を指定せずにオブジェクトを生成することができるデザインパターンです。

コードの責務を分割して、保守しやすいコードになることがメリットです。

ファクトリ(Factory)とは「工場」という意味で、ファクトリメソッド = オブジェクトを生産するメソッドというイメージです。

文章の説明よりも実際のコードを見た方が分かりやすので、以下のサンプルコードをご覧ください。

サンプルコード

Hashで与えられるデータを指定した形式(json または csv)で出力するプログラムを考えてみましょう。
まずはファクトリメソッドパターンを使わずに実装してみます。

require 'json'

class Report
  def self.generate(data, type)
    case type
    when 'json'
      data.to_json
    when 'csv'
      data.keys.join(',') + "\n" + data.values.join(',')
    end
  end
end

次のように実行すると

data = {age: 28, hobby: 'golf'}
puts Report.generate(data, 'json')
puts '---'
puts Report.generate(data, 'csv')

実行結果はこのようになります。

{"age":28,"hobby":"golf"}
---
age,hobby
28,golf

このコードの問題点は、Reportクラスが 以下の2つの責務を持ってしまっている点です。

  • 対応する形式(jsoncsv)の定義
  • それぞれの形式に変換するロジック

複数の責務を持ってしまっていることは、有名なSOLID原則の「S」Single Responsibility Principle:単一責任の原則 に反しますね。

このサンプルコードでは対応する形式の種類が少なく、変換のロジックもシンプルなため問題が無いように感じますが、形式の種類が増えたりロジックが複雑になると、可読性が低く保守しづらいコードになってしまいます。

これをファクトリメソッドパターンを使って書き換えてみましょう。

class Formatter
  def self.type(type) # これがファクトリメソッド!
    case type
    when 'json'
      JsonFormatter.new
    when 'csv'
      CsvFormatter.new
    end
  end
end

class JsonFormatter
  def format(data)
    data.to_json
  end
end

class CsvFormatter
  def format(data)
    data.keys.join(',') + "\n" + data.values.join(',')
  end
end

class Report
  def self.generate(data, type)
    Formatter.type(type).format(data)
  end
end

実行方法、結果は先ほどと同じです。

先ほど課題であった、Reportクラスが持ってしまっていた2つの責務を以下のように分けることができました。

  • 対応する形式の定義 → Formatterクラス
  • 変換ロジック → JsonFormatter/CsvFormatterクラス

対応する形式を増やす場合や、変換ロジックに修正が入った場合には、FormatterクラスやJsonFormatter/CsvFormatterクラスを修正すればよく、Reportクラスの修正は不要になりました。

Reportクラスの責務はレポートを出力することであり、レポート出力に関係ない変換ロジックなどの修正でReportクラスを変更しなくてよくなり、保守性が上がっていると思います。

またこれはGoFの原則の1つ「変わるものを変わらないものから分離する」にも則っています。

今回のサンプルコードは、こちらのサイトを参考にさせていただきました。英語ですがとても分かりやすくて勉強になりました。
Ruby - Factory Method pattern - Ruby Blog

おわりに

ここまで読んでいただきありがとうございます。

これまでのブログと形式を変えて、デザインパターンを使っていないコードとその問題点を提示してから、デザインパターンでその問題点を解決していく」という形式で書いてみました。
個人的にはこの方が分かりやすい気がしているので、次回からもこの形で書いていこうと思います。

Rubyによるデザインパターン の中でも、ファクトリメソッドを使っていないコードをファクトリメソッドを使って改善してく流れの説明が分かりやすかったので、ご興味ある方は是非合わせてご覧ください。

Rubyによるデザインパターン

Rubyによるデザインパターン

次回は、ビルダ(Builder)パターンをまとめます。

来週も頑張ります!

(追記)
ビルダパターンについてまとめました!
是非合わせてご覧ください。
ysk-pro.hatenablog.com

AtCoderで緑色になりました!【やってきたことまとめ】

こんにちは。先週末についに AtCoder緑色 になりましたーーー!!始めた頃から緑色を最初の目標にしていたのでめっちゃ嬉しいです!!

2019/9にAtCoderを始めて、5ヶ月かかりました...!

緑色になってテンションの高いうちに、ここまでやってきたことなどをまとめてみます。 

f:id:ysk_pro:20200121214811p:plain

そもそもAtCoderとは?

AtCoderのホームページにある説明です。

AtCoderは、世界最高峰の競技プログラミングサイトです。
リアルタイムのオンラインコンテストで競い合うことや、
3,000以上の過去問にいつでもチャレンジすることができます。

AtCoderトップページより引用)

競技プログラミングの定義ってなんだろと思って、ウィキペディアで調べてみました。

競技プログラミングでは、参加者全員に同一の課題が出題され、より早く与えられた要求を満足するプログラムを正確に記述することを競う。

ウィキペディア/競技プログラミングより引用)

与えられたお題をクリアするプログラムを誰が最初に書けるか、みたいな感じです。

実際の問題を見たほうが雰囲気が分かると思うので引用します。

直近(2020/1/19)に行われた AtCoder Beginner Contest 152(初心者向けのコンテスト)の一番簡単な問題(A問題)です。

<問題文>
高橋君は、プログラミングコンテスト AXC001 に参加しており、問題 A にコードを提出しました。
この問題にはN個のテストケースがあり、すべてのテストケースに正解した場合のみ提出は AC となります。
高橋君の提出は、N個のテストケースのうち M個のテストケースに正解しました。
高橋君の提出が AC となるか判定してください。

<制約>
1 ≤ N ≤ 100
0 ≤ M ≤ N
入力はすべて整数である。

<入力>
入力は以下の形式で標準入力から与えられる。

N M

<出力>
高橋君の提出が AC となる場合は Yes, そうでない場合は No と出力せよ。

書いたプログラムで入力を受け取って、正しい出力を返せれば正解となります。

様々な言語で回答することができ、僕が Ruby で書いたコードはこちらです。

  1. n, m = gets.chomp.split.map(&:to_i)
  2. if n == m
  3.  puts 'Yes'
  4. else
  5.  puts 'No'
  6. end

すごい簡単ですよね。

コンテストでは、こんな感じの問題が複数出題されて、早くたくさん解いた順にランキングがつけられます。

 

一見複雑な問題を考察して、シンプルなアルゴリズムに落とし込んで解けたときは最高に気持ちいいです...!

 

緑色ってどのくらいのレベルなの?

AtCoderでは、オンラインで行われるコンテストに出場すると、結果に応じてレーティングがつき、レーティングによって色が変わります。

上から順に「赤・橙・黄・青・水・緑・茶・灰」となっており、緑は下から3番目です。

AtCoderの社長(競技プログラミングがとても強い方でもあります)のブログでは緑色のレベル感について次のような説明がされていました。

緑色になれれば、競技プログラミングに熱心に取り組んでいる人」と考えて問題ないでしょう。要求レベルも決して低くなく、出場回数が足りないとマイナス補正がかかるため、運だけで到達することはまず出来ないラインです。他社アルゴリズム力判定サービスだと、上位1%の最高ランクが付く実力です。(あくまで「アルゴリズム力部分だけであることに注意してください)

 

AtCoderをはじめたきっかけ

元々学生時代は数学が好きだったこともあり(相関があるのか不明ですが)、競技プログラミングというものに興味がありました。

時間ができたときに、試しに少しやってみよーと思ってやってみたら一瞬でハマっていました

みんなでやるとより楽しいので、今では会社内外で布教活動もしています(このブログもその一環かな)。

 

やってきたこと

前置きが長くなってしまいましたがここからが本題です。

コンテストへの出場

AtCoderでは、ほぼ毎週末(土曜 or 日曜の 21:00 からが多い)に初心者向けのコンテストが行われており、予定が無い日は極力参加しています。

コンテスト後にAtCoderの中の方がYoutubeで解説をしてくださるのですが、解法のみではなく考え方から教えてくださり、とっても分かりやすいので自分が解けなかった問題の解説は必ず見ています。

また、コンテスト後は全員の提出したコードが見れるので、同じ言語で提出されたコードを見て「こんな書き方あるのか〜」と参考にしています。

今まで参加してきたコンテストの結果はこんな感じです。14回のコンテストに出てきました。

f:id:ysk_pro:20200120215545p:plain

パフォーマンスというのが、そのコンテスト1回でのレーティングのようなものらしいです。

少しは成長しているようなしていないような。

レーティング推移も載せておきます。

f:id:ysk_pro:20200121214943p:plain

 

AtCoderの過去問

AtCoder Problems という神サービスを使って、過去問を毎日やっています。

自分が過去問の何割くらいを解いたのかであったり、何日連続で問題に取り組めているかを見れるのでモチベーションの維持にも役立ちます。

f:id:ysk_pro:20200120213900p:plain

赤枠で囲ったのですが、現在37日連続で問題に取り組めています。いい感じ。

f:id:ysk_pro:20200120213913p:plain

GitHubのように草も生やせます。楽しい。

 

蟻本

競技プログラミング界では超有名な プログラミングコンテストチャレンジブック(通称 蟻本)にも取り組みました。

難しくて初級編までしか読めておらず、初級編の理解も怪しいので、定期的に読み返そうと思っています。

 

モチベーションの維持

仲間を見つける

会社でAtCoderを一緒に始める仲間を見つけることができたので、slackでatcoderチャンネルを作って毎日ワイワイ盛り上がっています。

同時期に始めたので、レーティングを競い合ったりできて楽しいです。

会社外でも、個人開発のコミュニティ「運営者ギルド」のslackで最近ワイワイやり始めました。

 

おわりに

AtCoderめっちゃ楽しいです!

敷居も低いです!

ご興味ある方は是非一度チャレンジしてみてください!

 

次は水色目指して頑張ります。

【読書まとめ25】スクラムブートキャンプ(SCRUM BOOT CAMP THE BOOK)

勤めている会社で、スクラムで開発を進めているプロジェクトに初めて入ることになったので、先輩におすすめいただいた スクラムブートキャンプ(SCRUM BOOT CAMP THE BOOK) を読みました。

この本の紹介に書いてある「はじめて『スクラム』をやることになったら読む本」という言葉通り、マンガをはさんだストーリー仕立ての説明はとても分かりやすかったです。

後から見返せるように、ポイントをまとめてみました。このブログを読むだけでもスクラムの雰囲気は分かると思います。

f:id:ysk_pro:20200115221028p:plain

 

ソフトウェアをつくる上で大事なこと

  • できたものを使って利用者が便利になる等の成果をあげること。何かを作ることは目的ではなく、あくまで手段である。当初作ろうと思っていたものよりも良いアイデアが出れば、目的を達成するためにそれを受け入れながら、作るものを変えていく。そうすることで成果を最大化できる
  • このような考え方で、成果を最大化するために考案された開発の進め方がアジャイル開発である

アジャイル開発とは

  • 次のような開発の進め方をアジャイル開発と言う
    • 関係者は目的の達成のためにお互いに協力し合いながら進める 
    • 利用者の反応関係者からのフィードバック継続的に得ながら、計画を調整する 
    • 一度にまとめてではなく、少しずつ作る。そして実際にできあがったものが求めているものと合っているかを頻繁に確認する
  • あらかじめおおよその全体像を明らかにしたうえで、どのくらいの期間と人数で仕事をするかを決めて、その範囲の中で大事な要求から順にプロダクトを作っていく

スクラムとは

  • 目的を達成できるプロダクトをつくるために、常に進む方向を調整しながら全員が一丸となって行うべき作業、会議、成果物を定めたものスクラムと言う

スクラムの進め方

  • スクラムではプロダクトオーナー(後述)が要求を並べ替えて、開発チームがスプリント単位でプロダクトをつくっていく
  • 「プロダクトバックログ(プロダクトへの要求を抽出して順番に並べ替えたリスト)を作成し、常にメンテナンスして最新に保つ
  • スプリント(1週間〜4週間)の固定の期間内で、計画、設計、開発、テストなどプロダクトのリリースに必要なすべてのことを行う

スクラムのチーム編成

プロダクトオーナー

  • プロダクトバックログを管理する責任者。プロダクトバックログは誰でも追加して良いが、順序(優先度)を最終的に判断して責任を持つのはプロダクトオーナーである

開発チーム

  • 通常3~9人で構成される。3人未満だと個人のスキルに依存してしまい、10人以上だとコミュニケーションコストが増えてしまう
  • 開発チーム内での仕事の進め方は、開発チームのメンバーの合意のもとに決められ、外部から仕事の進め方を指示されることはない

スクラムマスター

  • スクラムのプロセスを円滑を回して、プロダクトオーナーや開発チームを支える

スクラムで実施するミーティング

スプリントプランニング

  • スプリントの開始時に行う
  • 2つのトピックを扱う
    1. スプリントで何を達成するかを決める。プロダクトオーナーが今回のスプリントで達成したい目標を明らかにし、それを達成するためのプロダクトバックログ項目を選ぶ。バックログの個数は、ベロシティ(後述)を踏まえて決める。スプリントの目標をスプリントゴールとして簡潔にまとめておくと良い 
    2. 開発チームが選択したプロダクトバックログ項目をどうやって実現するかの計画を立てる。具体的な作業を洗い出し、プロダクトバックログの項目と作業を一覧にしたスプリントバックログを作成する。個々の作業は1日以内で終わるように分割するのが一般的で、時間での見積もりがよく使われる
  • 2週間スプリントであれば、4時間程度を使う

プロダクトバックログリファインメント

  • スプリントプランニングでプロダクトバックログの項目からスムーズに選択できるようにするため、プロダクトバックログの上位の項目について事前準備を行う
  • 準備する内容の一例
    • 中身を具体的にする
    • 疑問点を解決する
    • 何ができたら完成なのか(受け入れ基準)を明確にする(デモ手順まで決めておくと認識が揃いやすい)
    • 自分たちが扱えるサイズに分割する(具体的な分割方法はこちらの記事が参考になりました)
    • 見積もる
  • いつどのように行うかはスクラムでは定義していないが、使う時間はスプリントの10%以内にするのが一般的

デイリースクラム

  • スプリント期間中、毎日、同じ場所、同じ時間に行う
  • スプリントバックログの残作業を確認し、このまま進めてスプリントゴールが達成できるのかを確認する
  • 開発チームのメンバーが以下の3つを話す形で進めることが多い
    • スプリントゴールの達成のために、自分が昨日やったことは何か
    • スプリントゴールの達成のために、自分が今日やることは何か
    • スプリントゴールを達成する上で、障害となるものがあるか
  • 問題解決の場ではないことに注意する。開発チームのメンバーが問題を報告した場合は、デイリースクラム終了後に改めて、問題解決に必要な人を集めた別の会議を設定する
  • 開発チームの人数に関係なく 15分間で行う

スプリントレビュー

  • スプリントの終わりに行う
  • 開発チームのスプリントでの成果物を関係者にデモを行い、フィードバックを得てプロダクトバックログを見直す
  • デモができるのは完成したものだけである
  • 2週間スプリントであれば、2時間程度を使う

スプリントレトロスペクティブ

  • スプリントレビューの後に行う
  • スプリントの振り返りを行う。うまくいったこと、今後改善すべき点を整理し、今後のアクションプランをつくる。アクションプランのうち少なくとも1つは次のスプリントのスプリントバックログに含めると良い
  • アクションを検討するときは、アイデアを具体化するために便利な指標であるSMARTを意識すると効果が高まる
    • Specific(具体的な)
    • Measurable(計測可能な)
    • Achievable(達成可能な)
    • Relevant(問題に関連のある)
    • Timely / Time-bounded(すぐできる / 期日のある)
  • 2週間スプリントであれば、1.5時間程度を使う

スクラムを行う上で知っておいた方がいいこと

  • プロダクトバックログは詳細なフォーマットは定められていないが、以下のどちらかの形式で書かれることが多い
    • 機能・目的・詳細でまとめて一覧にした形式
    • 実際に使うユーザーに何を提供してその目的は何かを簡潔に書く、ユーザーストーリーという形式
  • プロダクトバックログに重要な項目が漏れないようにするためのやり方:スクラムチームみんなで、プロダクトバックログに含めたほうがいいと思う項目を付箋などに書き出していく。様々な人のいろんな観点で洗い出すことで、致命的な漏れをなくすことができる
  • インセプションデッキは、プロジェクトを始める前に明らかにしておくべきことを知るための活動。10個の質問という形でまとめられていて、それぞれの質問についてスクラムチーム全員で話し合う。話し合って明らかになったことは、プレゼン資料のようなスライドにまとめていく。スクラムではゴールやミッションを常に強く意識しながら行動することが重要であり、スクラムチーム全員で話し合うことが大切
  • 多くのスクラムチームでは、相対見積もりが使われる。基準となる作業とその時の数字を決めて、それとの比較で作業量を見積もる。実際のやり方としては、多くのチームではラニングポーカーという手法が使われる。それぞれの項目について、1人1人が見積もりを考えて、同時に公開してすり合わせる
  • スプリントごとに終わらせられるポイント数は、ベロシティと呼ばれている。ベロシティはスクラムチームのスピードのようなものである。ベロシティは決めるものではなく測るものであり、実際に行った数字を使うのが一番確実である
  • プロジェクトで調整できるものは次の4つしかない。品質予算期間スコープ である

 

 おわりに

本書は、最初にスクラムについてのポイントをまとめ、その後は実践編としてマンガをはさみながらのストーリー仕立てで解説していくという構成でした。

サクサク読めてとても分かりやすかったので、ご興味ある方は是非お手に取ってみてください。 

次は、会社の方におすすめいただいた カイゼン・ジャーニー (アジャイル開発の実例を書いた有名な本です)を読む予定です。

 

以下の記事を合わせて読むことでスクラムのベースとなるアジャイル開発についての理解がさらに深まると思うので、ご興味ある方は是非ご覧ください。

ysk-pro.hatenablog.com

ysk-pro.hatenablog.com

ysk-pro.hatenablog.com

【Rubyによるデザインパターンまとめ10】シングルトンパターン

コードの品質向上のため、Rubyデザインパターンを解説した名著である Rubyによるデザインパターン で紹介されているデザインパターンを1つずつまとめており、今回が第10弾です。(毎週1つが目標です!)

前回の記事(デコレータパターンのまとめ)はこちらです。
【Rubyによるデザインパターンまとめ9】デコレータパターン - 銀行員からのRailsエンジニア

この本で紹介されているサンプルコードそのままではなく、オリジナルのコードで説明しています。

今回は シングルトン(Singleton)パターン についてまとめました。

f:id:ysk_pro:20200112100112p:plain

シングルトンパターンとは

ただ1つのインスタンスしか持てないクラスを作り、その1つのインスタンスへのアクセスをグローバルに提供するパターンです。

Singletonという単語は、トランプの一枚札(唯一存在するカード)という意味で、インスタンスが1つしか存在しないことを表しています。

文章の説明よりも実際のコードを見た方が分かりやすいと思うので、以下のサンプルコードをご覧ください。

サンプルコード

ジムでダンベルを使いたいとき、他の人に使われているとテンションが下がりますよね。。

ということで、ダンベルの貸し借りを管理する簡単なプログラムを考えてみましょう。

class Dumbbell
  def initialize
    @usable = true # ダンベルを使用できるかどうか
  end

  def borrow
    if @usable
      @usable = false
      puts 'ダンベルを借りたよ。筋トレファイト!'
    else
      puts 'ダンベルはレンタル中だよ。他の筋トレをしよう!'
    end
  end

  def return
    @usable = true
    puts 'ダンベルを返却したよ。お疲れさま!'
  end

  @@instance = Dumbbell.new # クラス変数

  def self.instance
    @@instance
  end

  private_class_method :new
end

インスタンスが1つしか存在しないことを利用して、唯一のインスタンスインスタンス変数(@usable)でダンベルを使用できるかを管理しています。

以下のように実行します。

Dumbbell.instance.borrow
Dumbbell.instance.borrow
Dumbbell.instance.return

Dumbell.instanceで、唯一存在するインスタンスを呼び出しています。

ダンベルを借りたよ。筋トレファイト!
ダンベルはレンタル中だよ。他の筋トレをしよう!
ダンベルを返却したよ。お疲れさま!

newメソッドをプライベートメソッドにすることで、外部からDumbbell.newインスタンスを作ることができなくなり、Dumbbelクラスがインスタンスをただ1つしか持たないことを保証しています。

以下のように実行するとエラーとなります。

Dumbbell.new.borrow


また、RubyにはSingletonモジュールが用意されており、Singletonモジュールを使用するとシングルトンパターンがシンプルに実装できます。

先ほどのコードをSingletonモジュールを使ってリファクタリングしてみましょう。

require 'singleton'

class Dumbbell
  include Singleton

  def initialize
    @usable = true # ダンベルを使用できるかどうか
  end

  def borrow
    if @usable
      @usable = false
      puts 'ダンベルを借りたよ。筋トレファイト!'
    else
      puts 'ダンベルはレンタル中だよ。他の筋トレをしよう!'
    end
  end

  def return
    @usable = true
    puts 'ダンベルを返却したよ。お疲れさま!'
  end
end

Singletonモジュールをincludeすると、先に書いたコードと同様の以下3点を行ってくれます。

  • インスタンスを作成し、それをクラス変数に格納すること
  • instance というクラスメソッドを作ること
  • newメソッドをプライベート化すること

全て(実行の仕方・結果・newを呼び出すとエラーとなること)先ほどと同じ結果になります。

シンプルに実装でき、実装漏れもなくなるので、実際にシングルトンパターンを使うときはSingletonモジュールを利用するのが良さそうです。

おわりに

ここまで読んでいただきありがとうございます。

Rubyによるデザインパターン の中では、Loggerクラスを題材にしたリアルなサンプルコードの説明や、シングルトンパターンを使う際の注意点などが記載されていて分かりやすかったので、ご興味ある方は是非合わせてご覧ください。

Rubyによるデザインパターン

Rubyによるデザインパターン

次回は、ファクトリ(Factory)メソッドパターンをまとめます。

来週も頑張ります!

(追記)
ファクトリメソッドパターンについてまとめました!
是非合わせてご覧ください。
ysk-pro.hatenablog.com