この記事の対象
- railsといったフレームワークに頼り切っており、コーディングの手が度々止まってしまう。
- 設計ってよくわからない。
- テストめんどい
- 1つアプリケーションを作ったけど、レベルアップするにはどうすればいいかわからない。
という方対象。僕がインターンを通して上司から教えていただいたことに関してメモがわりにまとめました。なおこちらの記事はqiitaでも投稿しております。
MVCからDDDへ
railsでもサービス層を実装することでビジネスロジックの場所が明確になり、コントローラの肥大化を防ぎます。これから規模が少し大きいアプリケーションを作る場合、既存のMVCよりもサービス層をとりいれたものを使ってみましょう。
DDDの詳しい解説やrailsでの実装はこちらのサイトがとても参考になります。
Rails:Service層を運用して良かったところ、悪かったところ
設計の仕方
- 登場人物を書く。
- シーケンス図を書く。
- コントローラやバッチにロジックを落とし込む。(サービス層はあとから分離していく)
- このときコメントを書いていき、おおざっぱなコードを書いていく。
- 実装どうすればと手が止まればロジックを再考する。
まず登場人物を整理
例えばdddにでてくる登場人物
- db
- dao
- model
- service
- controller
- view
やサーバー単位での登場人物
- 外部api
- awsの各機能
- フロント
- apiを提供するエンド
などの登場人物を洗い出し、すぐに実装できるものであればモックでもいいのでとりあえず生成します。railsでいうところのとりあえずrails generate
する感じです。これらの登場人物は次のシーケンスで関連性を書いていきます。
シーケンス図を書く
シーケンス図を使って各登場人物の役回りを整理します。まず最初は手書きで大雑把に書いていきましょう。シーケンス図はこちらを参考に。
シーケンス図(Sequence Diagram) - UML入門 - IT専科
コントローラやバッチなどロジックにおとしこむ。
上で書いたシーケンス図を今度はコントローラもしくはバッチに書いていきます。サービス層はのちのち分離して行く想定です。
コメントを描き、おおざっぱなコードを描いていく。
詳細な関数やライブラリモジュールなどは後から実装していく。とりあえずあたかも存在するように書く。以下はあくまでも一例です。フラグ立っているかどうかはwhereで取得しろよとかのツッコミはなしで。
class HogeHoge
# data 全件取得
# data 加工
# フラグがたっていないデータは無視
# フラグが立っている場合、なにかする。
# data 保存
end
class HogeHoge
# dataを全件取得
hoges = Hoge.all
# dataを加工する
res_hoge = []
hoges.each do |h|
res_hoge << do_something(h)
end
# dataを保存する
ResHoge.import res_hoge
private
# 加工の中身
def do_something()
# フラグがたっていないデータは無視
# フラグが立っている場合、なにかする。
end
end
実装中に手が止まってしまった場合
コメントでロジックを先に書いた後に、手がとまるということはロジックが破綻している可能性がある。この場合は一旦エディターから手を止めてロジックを考え直したりするとよい。
設計にかんして
設計はまずは、ノートにざっと描いて登場人物が増えていった場合やドキュメントとして残したい場合は、draw.ioなどのものを使う。
テストめんどうだな、書いたことないっていう方へ
テスト書くときの心持ち。
テストコードちゃんと書くかどうかが、職業プログラマーと趣味プログラマーの分かれ道みたいです。製品としてちゃんとしたプログラムを書く場合、品質を担保しなければなりません。なるべく、メンテナンス性やバグの早期発見をするにはテストは必須です。
しかし、趣味プログラマーからプログラミングの世界に入ったひとなどは、テストコード書くのはめんどいですよね。そこでテストコード書くときの心持ちと、テストの意味に関して説明します。
テストコードはケアレスミスを防ぐもの
例えば割り算する関数をかいていて、このようにifの中で代入演算子を書いてしまうことも。この時この関数をテストするコードを書いておけば、ちゃんと動くかどうかの保証ができます。テストを書くことでこの関数に対して正しい実装であるという自信がもてるのです。プログラマー歴何年経ってもケアレスミスはなくならないらしいので、テストを書くことは身につけておいて損はないかも。
def devide(a, b)
# まちがって比較演算子を代入演算子にしてしまった。
if(b = 0)
return 0
end
return a / b
end
実装と同時平行で書く
ロジックを書いて関数化して行くと同時に、テストも生成してしまいます。こうするとテストとセットでコーディングする流れが身につきます。テストを書くのが面倒なのはテストがプラスαのものだと捉えてしまっているからかもしれません。
実装してすぐできた、ではなく見直しをする
実装が完了したらすぐに完成した、というのはよくありません。学校のテストでもそうであるように、一度自分のコード(解答)を見直します。この見直しを保証するのがテストコードのように思っていただいても構いません。
どこまでテストをするか
どこまでテストするかの答えは、自分たちのプロダクトの責任の及ぶ範囲です。たとえば外部で公開されているapiやライブラリは信頼できるものであればテストはやらなくても良いです。だからできる限りメンテされているライブラリなどを使うことが推薦されます。
テストの優先順位
テストの優先順位はサービス>モデル>Dao>コントローラの順です。コントローラはviewもからんでくる分、一般的にテストはしにくいです。しかしビジネスロジックの部分は、そのアプリの心臓そのもの。テストする必要があります。ここでサービスとコントローラを分離してあるおかげでテストがしやすくなってます。