RubyのリファクタリングでNull Objectを使ってコードをスッキリさせる方法
前回、Rubyのリファクタリングでイケてないコードを美しいオブジェクト指向設計のコードへ改良するための方法という記事を書いて、いい反響をいただいたので第2弾を書いた。
Ben Orenstein氏の講演で話されていた前回のとはまた別のリファクタリング方法。元ネタはこちら。
github.com
【リファクタリング前のコード】
class JobSite attr_reader :contact def initialize(location, contact) @location = location @contact = contact end def contact_name if contact contact.name else 'no name' end end def contact_phone if contact contact.phone else 'no phone' end end def email_contact(email_body) if contact contact.deliver_personalized_email(email_body) end end end class Contact < OpenStruct def deliver_personalized_email(email) email.deliver(name) end end
これはどんなプロジェクトでもよく散見される種類のコードだと思う。インスタンスを初期化して作成した後、それぞれの要素があるかどうか判断して、ある場合はAを返す。無い場合はBを返す、というパターン。
コードで言うとここ。
def contact_name if contact contact.name else 'no name' end end
contact_nameではif contactとしてcontactが入っていたらnameを返し、もし無ければ'no name'としている。同じようにcontact_phone、email_contactがあって、そのメソッドの中身はif文で分岐されている。
Railsなんかでもよくあるのがcuurent_userの有り無しによって分けるパターン。
例えばこういうの。
if current_user AAA else BBB end
で、そこは前回と同じで「聞くな、言え」の法則に反している。
毎回contactがあるかどうかを「聞いて」から処理をするのではなく「ただ言う」だけにした方がいいですよ、と。
その方法がNull Objectになる。まずは初期化のところを変更する。
【変更後】
def initialize(location, contact) @location = location @contact = contact || NullContact.new end
initializeにNull Objectを追加した。名前はNullContact。したがってもし引数のcontactが入ってなければ@contactにはNullContactのインスタンスが入ることになる。
そのNullContactの定義がこれ。
【変更後】
class NullContact def name 'no name' end def phone 'no phone' end def deliver_personalized_email(email) end end
つまり「もしcontactが無ければ返していたモノが全部入っているクラス」になる。
後はリファクタリング前のコードには何回も入っていたif文を全て取り除く。
【リファクタリング後の全体像】
class JobSite attr_reader :contact def initialize(location, contact) @location = location @contact = contact || NullContact.new end def contact_name contact.name end def contact_phone contact.phone end def email_contact(email_body) contact.deliver_personalized_email(email_body) end end class NullContact def name 'no name' end def phone 'no phone' end def deliver_personalized_email(email) end end class Contact < OpenStruct def deliver_personalized_email(email) email.deliver(name) end end
すごいシンプルで読みやすい。全10行もあったif文の分岐が全て無くなり、ただ「言う」だけで処理が完結している。
さらに変更の容易さも上がっている。リファクタリング前のコードではcontactが無い場合の処理が分散していた。例えば「contactが無い場合の表示がno nameとか愛想が無さすぎだから、もうちょっとマシなのに変えようかな」となったとする。するとそれぞれのif文のelseの箇所を探して、そこだけを変更していかなければならなかった。
ところがリファクタリング後のコードはNullContactクラスに定義がまとめられているので「NullContactを変更だけすればOk」となっている。
単一責任の小さなクラスを実装、というオブジェクト指向デザインの基本そのままになっている。
ということで「RubyのリファクタリングでNull Objectを使ってコードをスッキリさせる方法」でした。
ここに書いたリファクタリングの解説とオブジェクト指向デザインの内容はほとんど「Practical Object-Oriented Design in Ruby」の受け売り。
Practical Object-Oriented Design in Ruby: An Agile Primer (Addison-Wesley Professional Ruby)
- 作者: Sandi Metz
- 出版社/メーカー: Addison-Wesley Professional
- 発売日: 2012/09/14
- メディア: ペーパーバック
- この商品を含むブログを見る
tango-ruby.hatenablog.com
次世代スマフォのあり方を再定義したAmazonのFireタブレット
Amazonの激安Fireタブレットを買ってしばらく経ったのでそのレビューを書いた。
仕事がら常に最新のスマフォに触れている。いつもデスクにはiPhone4から最新のiPhone6sまでの歴代機とAndroidがそれぞれのバージョンと主要メーカーのがデバッグ機として置いてある。それだけのスマフォを毎日ゴチャゴチャ触ってデバッグして仕事してたら、それぞれの端末の特徴なりそれを作った会社のスマフォに対する考え方などが把握できてくる。
Fireタブレットなんて普通に見たら「とにかく安いタブレット」で、最新のiPhoneやiPadに比べればかなり見劣りする。
しかしたくさんの機器に触れているエンジニア目線で見ても「コレにはなにかがあるのかも?」と心を離さない変な感じがずっとあった。なので試しに買ってみた。
- 出版社/メーカー: Amazon
- 発売日: 2015/09/30
- メディア: エレクトロニクス
- この商品を含むブログ (26件) を見る
使って気が付いたのはFireタブレットはもう次世代スマフォのあり方を再定義してしまっている、ということ。
初代iPhoneからiPhone4sまで、つまりステーブ・ジョブズが存命の時代には確実に「新しいスマフォに対するトキメキ」があった。新しいのが出るたびにそのデザインと新機能にいちいち興奮して「次のは○○って新機能が入るらしいぞ!」などと言っていた。WWDCなんて毎回リアルタイムでチェックして、その後も何度も見返してジョブズのプレゼンのセリフとか暗記してしまうレベルだった。
それから時が経って今となっては次の新しいiPhoneがどうであろうか、正直どっちでも良くなってきた。WWDCも要点だけウェブでチェックして終わり。
iPhoneやスマフォはほとんど全ての人に行き渡ってコモディティ化したのだ。イチイチその機能やスペックを論じる時代では無くなり、その代わりにユーザーの関心が「そのスマフォを何に使うか?」に移行した。
そこで出てきたAmazonがFireタブレットを通して訴えるメッセージが極めて痛快で気持ちがいい。そのメッセージとは
「スペックは絞って端末代は究極の低価格でいい。その代わりAmazonプライムが提供する充実のコンテンツを存分に楽しんでくれ!」だ。
プライム会員になった場合、プライムビデオを通してそこにある映画はダウンロードし放題。音楽もプライムミュージックを通してダウンロードし放題。Kindle本も月1冊無料でダウンロード可能。
少し前まで制限されていたマイクロSDカードも今ではコンテンツを入れられるようになって125Gまで容量増やせるし、Google Playも入れればAndroidアプリもインストールし放題。なんかアマゾンの無敵感が半端ない。
Fireタブレットを手にしてから、生活が変わった。やはり映画やドキュメンタリーなんかのしっかり考えて作られた映像コンテンツに接すると生活の質が濃くなる。
今までiPhoneを使ってやっていたことと言えば各種のSNSの投稿をながめたり、ニュースをチェックしたり、地図を使ったりとその程度。良質の映画やドキュメンタリーをまるまる1本iPhoneで観る、なんてことは私はしなかった。いくらiTuneで映画を買うかレンタルすればiPhoneでも観れますよ、と言われても何かが違う。
そのレンタル料を払って、映画をiPhoneの小さな画面で観るのか?という迷いがあった。
ところがFireタブレットは違う。「無料だしどんどんダンロードして観てみてね(ハート)」と言われるのだ。次に観るつもりの映画やドキュメンタリーは常に5,6本ダウンロードして入っている状態だ。これでいつでもどこでも映画が視聴できる。しかもサイズは7インチでちょうど観やすい。画質も予想外に良好でアマゾンがそのためだけに作った意気込みを感じる。
生活における観る映像、聴く音楽、読む本の全てがアマゾンに囲い込まれてしまった。もしこれに多額の料金がかかるのなら考え直すが、ここまで楽しんで年間3900円、月にするとたったの325円。
月々たったの325円でこんなに充実したコンテンツを提供している会社を他には知らない。アマゾン恐るべし。
もうアマゾン無しでは生きていけない。
今までスマフォの新機能に一喜一憂して、iPhoneを高額な2年縛り契約購入とかやって、結局それでやることと言えばツイッターのつぶやきを眺めるだけ、とか一体自分は何をしていたんだ、とふと思ってしまう。
次世代スマフォによってデザインされたユーザー体験というのはもう充実したコンテンツとセットでなければ成り立たない時代になったことをFireタブレットを持って実感できた。正直これは説明されても感覚的なところは分からないような気がする。持ってみてはじめて体感できる感覚だった。
- 出版社/メーカー: Amazon
- 発売日: 2015/09/30
- メディア: エレクトロニクス
- この商品を含むブログ (26件) を見る
「ポケモンGO」の世界的大ヒットをとても嬉しく思う海外在住日本人の視点
海外在住の日本人としてポケモンGOの快挙をとてもとても嬉しく思っている。
あらかじめ言っておくと本日時点でシンガポールではまだポケモンGOがリリースされていない。したがって街のどこを見ても誰もポケモンGOをやっている人は居ない。それでもここ数日、ポケモンGOに沸き立つウェブニュースを見続けて嬉しくてしょうがない。
職場で世界各国から来ている同僚達に何回もポケモンGOの話をした。同僚に「お前またその話?まだ1秒もプレイしてないのになんなんだよ」とまで言われた。
開発したのはGoogle社内ベンチャーからスタートしたNianticだ、とか。任天堂関連会社のポケモンの知的財産に対するライセンス料を受け取るだけ、とか。なんか「100%日本発のアプリ」とは言い切れない部分が見て取れる。それでもポケモン自体は「日本発」と言っていいと思う。
多国籍なシンガポールという都市に居ると国境の意味がほとんど無くなっていることを実感する。過度なナショナリズムの煽り方にひとつもいいことが無いのも理解している。それでもポケモンにナショナリズムもクソも無く、この嬉しさだけは黙ってガマンできないのだ。
なんでこんなに嬉しいのかと言うと、海外のITスタートアップに勤めていて職場の同僚達に「本当の意味で自慢できる日本発のアプリ」なんて今まで存在しなかったからだ。
「LINEは?」と言われそうだが、東南アジア出身の人の中ではそれなりに地名度はあるがアメリカ人とヨーロッパ人の中ではほぼ無名。
アメリカ人に言っても「LINE?あっあー知ってる」という感じでなんかIT業界の人として「マイナーなアプリを知っている=よく勉強している」的な扱いで、余計にがっかりしてしまうこともある。
それにひきかえIT業界におけるアメリカ人の「説明しなくてもみんなオレ様の国から発信してる有名なアプリ、分かってるだろ?」というあの態度。「Facebookもインスタグラムも説明要らないよね?」と言う前から顔に書いてあるのだ。まーその通りなんだけど、やっぱり日本からもそれと同等のがあったらなー、と願っていたらポケモンGOが出てきた!嬉しいねー。
同僚のアメリカ人エンジニアのAの妹はポートランドに住んでいるらしい。Aに「ポートランドの妹にポケモンGOの感想を聞いておいてくれ!」と頼んでおいた。数日経ってAからの返答は「妹がな『街中で普通にスマフォ持ってポケモンGOやってる人達があちこちに居る。あれ見たら誰でもダウンロードして試したくなるわ。』だってよ」と。
ああ、嬉しい。私はその妹さんの報告どうこうではなく「ポケモン」という日本発の言葉を変な英語なまりでAが「Pokemon」とか言ってるのを聞くだけで嬉しかった。だって日本発だし。あー嬉しい。また明日職場でポケモンGOの話しよ。まだ1秒もプレイしたことないけど。