読者です 読者をやめる 読者になる 読者になる

開発合宿行ってきた

いつも一緒に活動してるメンバー5人で、久々に開発合宿してきましたー

今回は「勉強したい技術を使って、何か作ってみる」をテーマとして、1泊2日。場所は伊東の山喜旅館。両日とも会議室を貸し切ることができたので、快適なネット環境の元、集中して開発できました

事前準備

場所と日時を決める

まずはメンバーの都合が合う日程を伝助とかで調整して、その後合宿会場を予約。今回は伊東の山喜旅館にしました。開発合宿では「チェックイン、チェックアウトの時間」が問題になりやすいのですが、山喜旅館は会議室があって1時間1000円くらいで予約できました。チェックインしてない時間は、この会議室を予約することで、開発の時間を多くとれました

www.ito-yamaki.jp

旅館のホームページ、いい感じです

テーマ・タイムテーブル決める

今回は「勉強したい技術を使って、何か作ってみる」をテーマにしました。また、タイムテーブルは事前に決めて共有しておくと、当日はかどる。ということで今回はこんな感じにしました。

1日目

時間 内容
10:00 - 12:00 開発
12:00 - 13:00 ランチ
13:00 - 15:00 開発
15:00 - 15:30 部屋へ移動
15:30 - 19:00 開発
19:00 - 20:30 夕飯
20:30 - フリータイム

開発時間:7.5h

2日目

時間 内容
8:00 - 10:00 起床、朝食 、チェックアウト
10:00 - 12:00 開発
12:00 - 13:00 ランチ
13:00 - 14:00 開発
14:00 - 15:00 成果発表!
15:00 - 解散!

開発時間:3h

技術調査をしておく

当日開発に集中するために、ある程度技術調査というか勉強はしておく。自分はswiftiosアプリを作りたかったので、以下のようなことをしておきました

当日の様子

f:id:maeharin:20150314103040j:plain

f:id:maeharin:20150314151224j:plain

f:id:maeharin:20150314124225j:plain

f:id:maeharin:20150314160928j:plain

f:id:maeharin:20150314191002j:plain

f:id:maeharin:20150315100600j:plain

f:id:maeharin:20150315124034j:plain

f:id:maeharin:20150315140608j:plain

f:id:maeharin:20150315140946j:plain

振り返り

  • よかった点
    • wifi完備の会議室を長い時間予約できたので、開発環境は問題なし
    • 成果物発表を目標にしたので、集中できた
    • 事前にタイムテーブル作っておいたので、スムーズ
  • 反省点
    • 旅館の部屋、隙間があって寒かった
    • 帰りの電車調べてなくて混乱した。(自由席がない特急が来て待ち時間無駄になった)
    • 個人的には、もう少し事前にiosチュートリアルやっておけばよかった

レガシーシステムを理解する方法

結構年季が入ったJavaのレガシーなwebアプリをRailsに移行するというプロジェクトを進めている。レガシーシステムは以下のような状態。

・オリジナルを作ったエンジニアは既に不在
ビジネスロジックに対するドキュメントは殆ど存在しない
単体テストは存在しない
・社内WAFで、ドキュメントなし
複数のシステムが連動している

このような状態は、年季の入ったシステムではわりとよくあることだと思うが、いかんせん「仕様がわからない」ということが色んな所でボトルネックになっていた。その対策方法について、メモしておく。

仕様を理解するための時間を確保する

「その内時間が経てば理解できるよ」という考えもあるだろうが、ある程度年季が入ったシステムをリプレースするなら、初期段階で多少コストをかけてでも、既存仕様を理解するための時間を作った方が効率的だと思う。既存仕様をよく理解しないまま移行開発を行っても、色々な抜け漏れが発生する。また、移行作業とは別に通常開発やテクニカルサポートも行うわけだが、既存システムへの理解が浅いままだと、毎回の調査時間が馬鹿にならない。チームの人数や仕様理解度にもよるが、初期段階で仕様理解の体制を整備してチーム内で共有する時間をとった方が、トータルでみた時間コストが少なくなるというケースは多そうだ。

レガシーコードといえば、「レガシーコード改善ガイド」が有名だが、この本にも以下のように書いてある。

多くの人は、自分にできる最も手近な方法でコードを理解しようとし、その他の方法を使いません。結局のところ、何かを理解しようとするために多くの時間を費やすのは、作業がはかどらず、正しくないやり方に思えるからです。理解する段階をさっさと終わらせることができたら、自分の稼ぎを得るための仕事に取りかかれるはずだと考えるのです。しかし、こうした考えは愚かではないでしょうか。

とはいえ、場当たり的に調査しても効率が悪い。レガシーコード改善ガイドには、レガシーコードを理解するための技法がいくつか解説されているが、自分はその中から以下の3つを好んで使っている。

・仕様化テスト
・ラフスケッチ
・試行リファクタリング

「仕様化テスト」でユーザーから見た仕様を理解する

ユーザーからみたアプリケーションの仕様(一番外側の仕様)を把握する際に効果的。レガシーコード改善ガイドによると、仕様化テストとは以下のようなテストをさす。

仕様化テストは、コードの実際の振る舞いを明らかにするテストです。「システムはこれをするべきだ」とか「こうしていると思う」ということを確認するテストではありません。仕様化テストは、システムの現在の振る舞いをそのまま文書化します。(略)実際のシステムの動きをそのまま文書化したものになります。システムの一部分の動作を理解できると、その知識と、システムに新しく期待する動作に関する知識とを使って、変更を行えるようになります。率直にいって、システムの実際の動作に関する知識はとても重要です。

このやり方の何がよいかというと、仕様理解とテストケース作成の両方が進むということ。(もちろん、テストを正式にやろうとなると、メンテナンスコストが発生するので、実際に運用にのせる際には、注意深く検討する必要がある。)

リプレースプロジェクトなら、単体テストではなく、E2Eテスト

自分のプロジェクトでは「ユーザーからみた仕様は殆ど変えずにリプレースする」という大前提がある。なので、既存のレガシーアプリに単体テストを書いても結局捨て去る事になり、殆ど意味がない。なのでE2Eの仕様化テストを書くようにしている。

ツールとしては、selenium ideが便利。見返しやすいし(slowモードで再生すれば、ああ、こういう動きねというのが分かる)、後々自動テストを整備する際の資産にもなる。もちろん、selenium ideはメンテナンスがちょっと。。というのがあればcapybaraなど使って書くのもあり。この辺は用途やチームの状況に合わせて好きなツールを選択したらよいと思う。


「ラフスケッチ」で主要テーブル・クラスを理解する

コードを読むだけでは混乱する場合、絵を描いたり、メモを取ったりすることが有効です。(略)これらのスケッチには、完全なUMLダイアグラムや、関数呼び出しを表現する特別な記法を使う必要はありません。

上記の通り、形式はラフでよい。テーブル・クラスについて理解を深める時に効果的と思う。ただ、全てのテーブル・クラスを網羅しようとすると大変なので、スケッチの対象は、ビジネス上最も重要なテーブルやクラスのみにする。

ER図もどき

テーブルの関連だけ書いたER図があると、何かと便利。エクセルだとマスター管理が微妙なので、google driveの図形描画を使って、主要なテーブルの関連を書いている(とはいえ、結局主要テーブル以外の関連も調べるケースがあるので、erdというrubyのgemでER図を作るのもあり)

クラス図もどき

ビジネス上非常に重要な役割を担っているクラスは、クラス構造のスケッチがあると便利。別にUMLで正確に書く必要はなくて、継承や集約をざっと書いて、主要なpublicメソッドだけ書いておくだけでも役に立つ。継承関係の矢印ひっぱったりするのが面倒なら、手書きで書いておくだけでもいい。

「試行リファクタリング」で細かいロジックを理解する

ロジックが複雑で、かつそのロジックを把握しておかないとまずい部分は、試行リファクタリングを行う。レガシーコード改善ガイドによると、試行リファクタリングとは以下のようなリファクタリングをさす

まず、バージョン管理システムからコードをチェックアウトしてください。テストを書く事は忘れましょう。メソッドの抽出でも、変数の移動でも、そのコードを理解しやすくするために、あらゆる方法を用いてリファクタリングしてください。ただし、そのコードは再びチェックインせずに破棄します。これは試行リファクタリング(scratch refactoring)と呼ばれる手法です

リファクタリングを自由に行って、徐々にロジックへの理解を深めて行く。深掘りするとどこまでもいけるので、理解すべきポイントを把握したらすぐに切り上げるようにする。終わったら別ブランチに保存しておくか、もしくは破棄する。(決して稼働中のアプリに影響を与えないようにする)

まとめ

上記の方針で少しずつレガシーコードの理解を進めていて、結構いい感じにワークしている。なお、Object-Oriented Reengineering Patternsという書籍はこのテーマについて突っ込んで書いているようなので、読んでいるところ。以下から無料のpdfがダウンロードできる
http://scg.unibe.ch/download/oorp/



レガシーコード改善ガイド (Object Oriented SELECTION)
マイケル・C・フェザーズ
翔泳社
売り上げランキング: 118,912

「Webアプリエンジニア養成読本」を献本してもらった!読んだ!

「Webアプリエンジニア養成読本」を献本してもらいました。あざす!


Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)
和田 裕介 石田 絢一 (uzulla) すがわら まさのり 斎藤 祐一郎
技術評論社
売り上げランキング: 316

「点」ではなく「線」

私自身は「28歳の時に未経験からWebエンジニアに転職する」という無謀な試みをして、今年3年目になります。日々開発に勤しむ日々を過ごしておりますが、Webアプリを作るために必要な技術要素って広い!と日々痛感しております。

たまたま自分は本書の著者の1人であるゆーすけべーさんはじめ、先輩諸氏から色々教わることができましたが、教えてくれる人が身近にいて一番よかったのは

何を勉強すればよいのかが分かった

ことです。本書にはその「何を勉強すればよいのか」がコンパクトにまとまっていると思いました。技術書って「点」で書かれているものが多いと思います(PHPRubyMySQLみたいに特定技術ピンポイントで深堀されてる本)。一方、本書は「Webアプリを作るための技術要素」という「線」で書かれているように思いました。

この本をざっと読んで手を動かせば、脳内でWebアプリを作るために必要な技術要素という「点」が繋がって「線」になっていくように思います。Webアプリエンジニア先輩諸氏がconnecting the dotsしてくれた感じで素敵です。

未経験の人は「索引作り」に

まだWebアプリを作ったことが無い方は、きっと「Webアプリを作るために必要な技術的要素の索引」がまだ頭の中に出来上がっていない状態だと思うので、頭の中に索引を作るイメージで読み進めるとよいかと思います。

まずは、この本に書いてあることを、ざっと手を動かしてやってみる(全体を見失わないようにとにかく先に進める)。すると「何を勉強すればよいのか」当たりがつけられるようになる。その後は自分でアプリの企画を考えて実際に作ってみたり、より深く勉強したい技術的要素があればさらに勉強していくみたいな感じで進めるとよいかと。

あ、ただ本書ではクライアントサイドJavaScriptとデータベースについて本当にさらっとしか触れられていないので、その部分はちょい踏み込んで自分で調べる必要が出てくると思います。

2-3年の経験がある人は「穴埋め」に

自分のように2, 3年の経験がある人にとっては、「穴を埋める」という視点で読むとよいかと思いました。もちろん「この本に書かれていることは全て知り尽くしている」という方もいらっしゃるでしょうが、自分は結構穴がありました。例えば、自分は「開発」に携わることが多く「運用」の経験が浅いです。なので、やはりその「運用」を扱っている3章,4章は穴が多かったです。

また、PHPの章はいわゆる「モダン」な開発手法が用いられているので、「レガシーなPHPの保守に手一杯でモダンなPHPの学習が追いついていない」なんて方は結構新しい発見があるのではないでしょうか。具体的にはComposerでライブラリ管理して、WAFとしてSlim(RubySinatraライクなWAF)、テンプレートにTwig、ORMにEloquent(Laravelで使われているORM)を使ってサンプルアプリを開発していくという構成になっているので、その辺の経験がなければ新しい発見があるかと。

まとめ

未経験だった頃の自分には無条件でオススメしたい。今の自分にとっても穴が把握できてよかったです!

Backbone.jsでViewからModel・DOMを操作する時の流れ

自分の頭の中の整理のために。

はじめに

Backbone.jsガイドブックを読んでいたら、このような事が書いてあった。

Backbone流MVCでは、ビューとコントローラは両方ともViewが担当します。(略)これらはそれぞれViewのメソッドとして実装しますが、本書では区別のために前者をビューメソッド、後者をコントローラメソッドと呼ぶことにします。(略)重要な点は、DOMイベントに応じてコントローラメソッドが実行されることで処理が始まり、その中でmodelやcollectionを操作し、その結果生じるイベントがビューメソッドを呼ぶ、という流れを意識することです。そのためにも、コントローラメソッドには処理の起点になる以上の仕事を与えず、DOM操作はすべてビューメソッドに集めるよう明確に区別しましょう。

図にするとこんな感じになる(点線がイベントで実線が直操作)

しかし、なぜこのような書き方にするとよいのか?2つの疑問をもった

1. なぜコントローラメソッドとビューメソッドを切り分けるのか?
2. なぜコントローラメソッドがビューメソッドを直接呼び出さないのか?

以降、それぞれ整理してみる

1. なぜコントローラメソッドとビューメソッドを切り分けるのか?

まず、なぜわざわざコントローラメソッドとビューメソッドを切り分ける必要があるのか?逆に以下のように一緒にすると何が困るのか?

思うに、この書き方の問題は、DOMの更新を担当する部分のコードが再利用できないことにあると思う。例えば以下のように複数イベントハンドラが同じDOM更新を行う場合、上記の書き方だとコードが重複する。

DOM更新の部分を切り出して別メソッドにすれば再利用できる

役割が分離されているので、テストもしやすくなるし、理解もしやすくなる。

2. なぜコントローラメソッドがビューメソッドを直接呼び出さないのか?

では次に、なぜコントローラメソッドが直接ビューメソッドを呼び出さない方がよいのか?つまり以下のように書くと、なぜよくないのか?

恐らく、問題はModelとViewが1対多になった時に起こる。自分が作ったWebサービス音楽制作のためのWebサービス)でModelとViewが1対多になる部分が多くあったので例にあげる。例えばこんな部分。

この部分では音源を表す1つのModelに対して、再生ボタンを管理するPlayButtonViewと波形を管理するWaveformViewという2つのViewが存在している。例えば音源が停止している状態から再生ボタンと波形それぞれをクリックすると、以下のような動きをする。

・再生ボタンをクリック

  • > PlayButtonViewがModelを再生
  • > PlayButtonViewが再生ボタンを停止ボタンにする + WaveformViewが波形を動かす

・波形部分をクリック

  • > WaveformViewがModelを再生
  • > PlayButtonViewが再生ボタンを停止ボタンにする + WaveformViewが波形を動かす
ビューメソッドを直接呼び出すと

これをコントローラメソッドがビューメソッドを直接呼び出すように書くと、以下のようになる。

Modelに対してViewが2つであったとしても、既にかなり複雑になっている。これが3つ、4つとなってきたら確実に破綻する。

Modelのイベントを購読すると

では、これをビューメソッドがモデルのイベントを購読するように変更したらどうなるだろうか?図にすると以下のようになる。

Modelのイベントを介することによって、View1とView2が疎結合になった。DRYだし、理解しやすいし、テストもしやすい。

まとめ

もちろん、コントローラとなるViewのメソッドが必ずModelとDOMを更新するわけではない(ただDOMを更新するだけの時や、イベントを発火するだけの時など様々なケースがある)し、ViewとModelが複雑でイベント仲介者(Mediator)を置かないと厳しいこともあるが、「Model更新->DOM更新の基本的ケース」においては、上記のような書き方をするとだいたい幸せになれるように思った。

Backbone.jsをRailsで使った際の、初期設定とルール

こないだまでRailsとBackbone.jsを使ったWEBサービスを作ってました。折角なので、その際の初期設定とちょっとしたルールをまとめておきます。ちなみに、規模感は以下のような感じです。

・ModelとCollection 各約10個
・ViewとTemplate 各約30個
・Routerは使わない(SinglePageApplicationではないので)

バージョンは

・backbone.js: 1.1.0
rails: 3.2.13

です

ライブラリの配置

依存ライブラリは以下のように配置した

// vendor/assets/javascripts/配下
.
|-- backbone/
|   |-- backbone-min.js
|   `-- backbone-min.map
|-- json2/
|   `-- json2.js
|-- underscore/
|   |-- underscore-min.js
|   `-- underscore-min.map
...

ディレクトリ構成

jsコードのディレクトリ構成は以下のようにした。collectionsとmodelsは直下にファイルをおき、viewsとtemplatesはモデルに対してディレクトリを作ってその下にファイルを置いて行った(その構造に合わないファイルも沢山出てきたので、ある程度自由にディレクトリを切っていった)

// app/assets/javascripts/配下
.
|-- collections/
|   `-- users.js
|-- models/
|   `-- user.js
|-- templates/
|   `-- users/
|       `-- xxx.hbs
|-- views/
|   `-- users/
|       `-- xxx.js

テンプレート

テンプレートにはhandlebarを使った。rails用のgemでhandlebars_assetsというのがあったので、これを利用

https://github.com/leshill/handlebars_assets

gemをインストール

group :assets do
  gem 'handlebars_assets'
end

テンプレートはこんな感じになる

// app/assets/javascripts/templates/users/user-detail.hbs
<span>名前:</span><span>{{name}}</span>
<span>メール:</span><span>{{mail}}</span>

テンプレート関数のデフォルト名は「HandlebarsTemplates」だが、気に入らなければ変えられる。例えば「JST」という名前にしたければ、config/initializers/handlebars.rbというファイルを新規作成し、その中身を以下のようにする

HandlebarsAssets::Config.template_namespace = 'JST'

するとViewからはこのようにテンプレートを使えるようになる

// app/assets/javascripts/views/users/user_detail.js
MYAPP.UserDetailView = Backbone.View.extend({
  template: JST['users/user-detail'],

  render: function() {
    this.$el.html(this.template({
      name: this.model.get('name'),
      mail: this.model.get('mail')
    }));

    return this;
  }
});

application.js

以上を動かすためのapplication.jsは以下のようになる。require_treeでディレクトリを再起的に読み込むようにする

//= require jquery
//= require jquery_ujs
//= require json2/json2
//= require underscore/underscore-min
//= require backbone/backbone-min
//= require handlebars.runtime
//= require_tree ./templates
//= require application
//= require_tree ./models
//= require_tree ./collections
//= require_tree ./views
//= require_tree .

名前空間

名前の衝突を避けるために、アプリケーションに関する名前空間を作る(といってもグローバルなオブジェクトを1つ作るだけ)。application.jsに以下を記載。

window.MYAPP = window.MYAPP || {};

クラス名規則

上記の名前空間の下にクラスとなるオブジェクトを作っていくのだが、その際のクラス名は以下のようにした。全て大文字ではじめる。CollectionはModelの複数形。ViewはModel/Collectionと1対1であれば頭にModel名をつける(そのような関係にならない場合も多いので、その場合は自由に命名する)。

// Model
MYAPP.User = Backbone.Model.extend({ /* ... */ });

// Collection
MYAPP.Users = Backbone.Collection.extend({ /* ... */ });

// View
MYAPP.UserListView = Backbone.View.extend({ /* ... */ });

アプリケーション全体での共通前処理

アプリケーション全体で必ず実行したい共通の前処理が存在したので、Backboneオブジェクト自体のイベントを利用した。application.jsに共通前処理を書き、それが終わったらBackbone.triggerでカスタムイベント(以下の例ではinit)を発火する。各ページのjavascriptではこのイベントを購読しておくという形。

application.js

$(function() {
  // 共通前処理
  // ...
  Backbone.trigger('init');
});

各ページ

Backbone.on('init', function() {
  // 各ページの処理
});

サーバーサイドで生成するjsonのハンドリング

サーバーサイドで生成するjsonのハンドリングは、基本的にはas_jsonメソッドを用いた。使い方はこちらのブログが詳しい

http://d.hatena.ne.jp/gutskun/20130409/1365518684

もっと細かいハンドリングをしたい場合にはgemを使った方がよいと思う。Rails4からはデフォルトで組み込まれているJbuilderかRABLあたりが有名

http://railscasts.com/episodes/320-jbuilder?language=ja&view=asciicast
http://railscasts.com/episodes/322-rabl?language=ja&view=asciicast

初期データ投入

大きく2つの方法があるように思う。1つはデータが空のオブジェクトを作ってからサーバーにfetchするもの。もう1つはhtmlレンダリング時にデータも入れてしまうもの。

1つ目の方法
<div id="user-list-container"></div>

<%= javascript_tag do %>
  Backbone.on('init', function() {
    var users = new MYAPP.Users();
    var userListView = new MYAPP.UserListView({collection: users});
    $('#user-list-container').html(userListView.render().el);
    users.fetch({reset: true});
  });
<% end %>

この場合の流れは
・データが空の状態でViewレンダリング
・ model/collectionがサーバーへデータをfetch
・ model/collectionのresetイベント発火
・ viewがresetイベントキャッチして、再度レンダリング

2つ目の方法
<div id="user-list-container"></div>

<%= javascript_tag do %>
  Backbone.on('init', function() {
    var users = new MYAPP.Users(JSON.parse('<%= j @users.to_json.html_safe %>'));
    var userListView = new MYAPP.UserListView({collection: users});
    $('#user-list-container').html(userListView.render().el);
  });
<% end %>

この場合の流れは
・モデルのjsonデータをサーバー側でjsコードとして出力
・データがある状態でViewがレンダリング

2つ目の方法の方がレンダリングが速いので、特に理由がなければ2つ目の方法を使う。

クライアントサイドでレンダリングするか、サーバーサイドでレンダリングするか

前述コードは、backbone管理下の要素をクライアントサイドで生成するようなコードだった。けれど、そうするとその部分の要素に関してはSEOが死ぬ。この問題は別にbackboneに限った話ではなく、angularのような他のライブラリを使っていても、クライアントサイドでレンダリングする限り起こる問題。対策法はこちらのサイトなどが詳しい

http://info.appdirect.com/blog/solving-the-javascript-seo-conundrum-part-one
http://www.ng-newsletter.com/posts/serious-angular-seo.html

けれど、今回はそこまで大掛かりなことをせずに局所的に対策すればよい程度だったので、SEO対策な必要なページはサーバーサイドでレンダリングし、クライアントサイドではサーバーサイドでレンダリングされたhtmlに対してbackbone.jsのオブジェクトをアタッチするようにした。参考にしたのはこちらのstackoverflowのポスト

http://stackoverflow.com/questions/7549306/single-page-js-websites-and-seo

コードはこんな感じ。

<div id="user-list-container">
  <% @users.each do |user| %>
    <div class="user-detail" data-id="<%= user.id %>">
      <span>名前:</span><span><%= user.name %></span>
      <span>メール:</span><span><%= user.mail %></span>
    </div>
  <% end %>
</div>

<%= javascript_tag do %>
  Backbone.on('init', function() {
    var users = new MYAPP.Users(JSON.parse('<%= j @users.to_json.html_safe %>'));
    var userListView = new MYAPP.UserListView({el: $('#user-list-container'), collection: users});
    userListView.$('div.user-detail').each(function(i, el) {
      var el = $(el);
      var id = el.attr('data-id');
      var user = users.get(id);
      new MYAPP.UserDetailView({el: el, model: user});
    });
  });
<% end %>

このアプローチだと、テンプレートをクライアント側でも使いたい場合にコードの重複が発生するが、今回はそのような箇所がそれほど多くなかったので、よしとした。

参考になったソース

https://github.com/documentcloud/documentcloud
Backbone.jsの本家本元、documentcloud。そのソースコードGithubで公開されてる。サーバーサイドはRails。ちょっとバージョンが古いので、書き方もレガシーなメソッドを使っていたりするけど、Todoアプリみたいなサンプルとは違って実運用されている大きなアプリケーションなので多いに参考になった。

https://github.com/samuelclay/NewsBlur
SinglePageApplicationのRSSリーダーNewsBlur。こちらもdocumentcloudのメンバーが作っているっぽい。サーバーサイドはDjango。 media/js/newsblur/配下にbackboneを使ったjsコードが沢山ある。

終わり

いわゆるSinglePageApplicationといったような、ほとんど画面遷移をしないアプリケーションにする場合、またちょっとポイントが変わってくるとは思います(Routerの役割が大きくなるので)。けれどそこまでいかないアプリケーションであれば、上記のような構成+ルールで破綻せずにいけそうな感じでしたー

RubyのIntegerを拡張してFizzBuzzを問題をやってみた

FizzBuzz問題というのをやったことが無かったので、Rubyでやってみた。「ある整数がある整数で割り切れるか?」という部分を抽象化すると、少し汎用的になってよいかと思った。

class Integer
  def dividable?(n)
    self % n == 0
  end                                                                                                                                                                                                       
end

(1..100).each do |n|
  puts n.dividable?(15) ? 'FizzBuzz' : n.dividable?(5) ? 'Buzz' : n.dividable?(3) ? 'Fizz' : n
end

Rubyだと0はtrueになるので、== 0の結果を返してあげる

ネーミングに困ったとき、RailsのAPIが参考になった

最近ちょっとしたORMを書いていて、SQLプレースホルダに「紐付ける値」をなんと命名したらよいか悩んでいたのだけど、こういう定石的な命名は、自分でウンウン悩むよりフレームワークAPIを参照するのが早いと思った

RubyのORMをざっと調べてみたところ、やはりRailsActiveRecord)はシンプルで分かりやすいネーミングをしている思った。ということで、bindsというネーミングをいただきました。

Rails(ActiveRecord)

find_by_sql(sql, binds = [])

Sequel

with_sql(sql, *args)

DataMapper

query(statement, *bind_values)