概要
書籍 Build Awesome Command-Line Applications in Ruby2
章
Have a Clear Concise Purposee | サブセットを持つコマンド
サブセットを持つコマンド例:仕様
※書籍に載っていたものとは全く別のものです。
同じような内容を自分独自の仕様で考えました。
Personの関連情報を出力するコマンド群を作成する。
Personの情報は persons.txt にcsv形式で保存されている。
firstname,lastname,age kazuo,tanaka,34 ken,sato,54 ichiro,suzuki,45
Personの情報を取得し、
姓を出力する
名を出力する
姓名を出力する
年齢を出力する
コマンドを作成します。
サブセットを持つコマンド例:コード(修正前)
各コマンドをバラバラに作成してしまった悪い例。
類似処理をバラバラに実装しているためWETな実装になっている。
personal-firstname.rb
require 'csv' table = CSV.table('./personals.csv') table.each { |row|puts row[:lastname] }
personal-lastname.rb
require 'csv' table = CSV.table('./personals.csv') table.each { |row|puts row[:lastname] }
personal-fullname.rb
require 'csv' table = CSV.table('./personals.csv') table.each { |row|puts "#{row[:firstname]} #{row[:lastname]}" }
personal-age.rb
require 'csv' table = CSV.table('./personals.csv') table.each { |row|puts row[:age] }
出力
$ ruby personal-firstname.rb tanaka sato suzuki $ ruby personal-lastname.rb tanaka sato suzuki $ ruby personal-fullname.rb kazuo tanaka ken sato ichiro suzuki $ ruby personal-age.rb 34 54 45
ツールの単純化例:コード(修正後)
各コマンドを1箇所にまとめて共通化し、DRYな実装に。
各コマンドはサブコマンドとして実装。
personal.rb
require 'csv' PERSONALS = './personals.csv' if ARGV.size == 0 command = 'firstname' else command = ARGV.shift end table = CSV.table(PERSONALS) case command when 'firstname' table.each { |row|puts row[:firstname] } when 'lastname' table.each { |row|puts row[:lastname] } when 'fullname' table.each { |row|puts "#{row[:firstname]} #{row[:lastname]}" } when 'age' table.each { |row|puts row[:age] } else fail "invalid sub command #{command}" exit false end
出力
$ ruby personal.rb firstname kazuo ken ichiro $ ruby personal.rb lastname tanaka sato suzuki $ ruby personal.rb fullname kazuo tanaka ken sato ichiro suzuki $ ruby personal.rb age 34 54 45