2019-01-13

Clean ArchitectureとHanamiですっきりしてきた

デザインパターンのよさが分からない人は設計に自信が持てるようになるのか問題

自分語りを少々。1

目の前にあった HTML と JavaScript と PHP と SQL が渾然一体となったコードと戦うことから始め、テスタブルなコードを自分が死なないように習得していった自分にとって、鬼門の一つは

再利用のためのデザインパターン

だった。

何しろ再利用可能なコードなんてほとんど何もなかったのだ。そんなもの分かるわけがない。

ところが世の中の「ためになる本」はオブジェクト指向やデザインパターンの知識が前提になってしまっているところが結構あって、歯がゆい思いをすることもそれなりに多かった。

そんなところに、少ない設定、少ない知識でもプロダクティブな開発ができる Ruby on Rails というフレームワークが登場したことで、自分にできることが広がった。2

Rails の支援していないもののうち、RDBMS, SQL については『楽々ERDレッスン』や『Webエンジニアのための データベース技術[実践]入門』など前提となる知識を数多く要求せずに済ませていてかつしっかりした内容のよい本がいくつもあった。JavaScript については jQuery の前に Ecma 262 を把握し、jsUnit で TDD を回すところから書き始めているので、おかしなクセがつく前にそこそこメンテナブルなコードを書けるようになっていたように思う。

それ以外の設計部分は Rails MVC の外に道を踏み外すべきと決断することはなかなかできないので「より良い」を実現できるように ActiveDecorator や Cells のような gem を足すことで避けてきたようなところがある。

それでも自分が書く分には Fat Controller や気ままな Helper はある程度避けることができ、満足しているが、しかし事前に「こう設計すべき」という明確な根拠があって避けることができているわけではないので、レビューや検収の段になって「なんでこんなことになる?」といったコードを受け取ってしまうことがままあった。3実装のレビューは「せっかく実装したし、もう時間もない」というプレッシャーとの戦いになりがちで、勢い「今回だけは」みたいなことで破綻が始まりやすい。

物理的な距離の近いレビューについては、

  • コードの前に設計をレビューをする

ことである程度防ぐことはできるようになったが、それでもいざ実装となると「うぉ、そうきたか」みたいなコードを受け取ってしまうことはやはりある。

テストを書いてリファクタリングすることはできるが、理想は最初から大規模なリファクタリングは発生しない方がよいに決まっている。しかしそれには高い設計力とそれを事前に共有するための表現力が必要だ。

そんなことが可能とは、なかなか思うことができなかった。最近で言うと DDD なんかも苦手意識がある。そこまで開発開発していないというか、もっとライトに早く、という要請に応えることが多かったので、じっくり腰をすえて勉強しなきゃと思いつつ、(その感覚を得るまでは)難しいだろうなぁみたいな気がしている。

Clean Architectureを読んだ

冬休みの宿題で Clean Architecture を読んでいた。これについてはいくつか段階があって、

  1. ブログエントリとそれを受けての感想を読んだ状態
  2. Hanami を触りながらドキュメントを読んだ状態
  3. 書籍を半分くらい読んだ状態

で、今は3段階め。

Clean Architecture には以前から興味はあるにはあったんだけど、実は Uncle Bob 本て似たようなタイトルでそこそこ厚めの本がたくさんあって苦手意識を持っていた。どちらかというと

  • Dart 2 面白そう
  • クライアントサイド(Web フロントエンドやモバイルアプリ)の世界では最近 Clean Architecture が話題っぽい

みたいな流れと、それとは別にこれも以前から興味のあった Hanami について「マイクロサービス指向と言われるとなんか嘘くさいけど、Clean Architecture 意識してるとかいうものも見かけたような?」と思い直して

  • Hanami 触って読んでみよう

となり、Controller と View と Template の巧みさが、

  • 「あれ? これおれが欲しかったやつなのでは?」になり、
  • じゃあやっぱちゃんと Clean Architecture 読んでみるか

に至った次第。

ブログエントリとその感想みたいなものを読んでいた時は正直「詳細から抽象に依存する? なにそれ?」みたいな感じだったんだけど、今は「あぁ、なるほど。これは一つの大きな指針になるなぁ」と感じている。

Clean Architectureは全体的には現実との戦い方の示唆に富む良書

ただし、読み手は選ぶような気がする。4

自分の場合、まず「緊急」と「重要」の違いの説明から鷲掴みであった。首がもげるほど頷いた。

また中途半端に知っていたり分かった気になっていた

  • プログラミングパラダイム
  • モジュール設計の原則
  • コンポーネント設計の原則

についてまとまっていたのはとても助かった。併せてこれらがより良い「制約」をもたらすものという考え方にとても共感を覚えた。

何かができるようになるための考え方ではなく、何をやったらいけないか、やらないようにすべきかを考えるというのはこれまでの自分の考え方ととてもマッチしている。これは恐らく最初に刷り込まれた「他人が自由気ままに書いたコードと対峙し続けるのは人間の精神を破壊するのに十分な威力を持つ」という恐怖からきているんだと思う。Rails を始めとする「よいレール」に強くこだわっていたのはまさにそのためだ。「やればできちゃうけど、やらない」という選択だ。

そんな自分に最も沁みたのは以下の言葉。

速く進む唯一の方法は、うまく進むことである。

そして

アーキテクチャの形状の目的は、そこに含まれるソフトウェアシステムの開発・デプロイ・運用・保守を容易にすることである。

それらを容易にするための戦略は、できるだけ長い期間、できるだけ多く選択肢を残すことである。

どうしてお前はおれの大事な言葉を知っているんだい? まさかまったく同じ考えだとは思わなかった。もちろん、恐らくすでに Uncle Bob 大好きな人の言動を見聞きしていて影響を受けている可能性はある。でも「選択肢」の考え方は自分が開発を生業として学ぶに至る前から重きを置いている言葉であり、迷いが消えていく感じがした。

いま自分の欲しいものはよいInteractorのプラクティス

Hanami の Controller と View と Template の割り切りは見事だなぁと思った。Model では command の分離がよいと思った。同時にここに当てはまらない部分、そして Entity でも Repository でも表現し切れない部分に強い関心が残った。

例の図 の右下の Use Case Interactor である。

これまでもユースケースという言葉は知っていたが、抽象的な設計のための言葉だと思っていた。しかし Use Case Intercator を起こすことができれば設計から実装を地続きに考えることができる。これはとても大きい。これまで URI 設計とデータベース設計の間にもやもやを抱えていたが、Interactor を意識し、

などで習作を作っていくことでよりクリアに頭を整理できそうな気がしている。

※ Rails では Trailblazer::Operation でもよいかもしれない。

手離れを加速できそう

上の修練によって設計の言語化がよりスムーズにできるようになれば、これまで目の前で動くコードを見せながら一緒に触りながらでなければ伝えにくいと感じていたキモの部分について、もっと非同期に伝えることができるようになるのではないかという期待がある。

これができれば、どうしても目の前で動くものを先に見せないといけないという制約を外せる。これが外せれば、実装のレビューも設計のレビューもしやすくなるだろうし、事前に方針を伝えることもやりやすくなるはずだ。

楽しみが増えた。

あと参考

  1. よさが分からないは大げさだけど、それによってとても多くの救いを得られたかというとそうではないという程度の意味。 

  2. Release It ! のおかげでピンときていた DevOps については自分は Rails のおかげで実現の弾みがついたと言ってよい。 

  3. おかげでアンチレガシーや対FatControllerのスキルは勝手に上がって行ったわけだが、これは望んでこうなっているわけではない。 

  4. 個人的には依存性逆転の原則が Interface 一辺倒で、うーんと思わなくもないんだけど、「コンパイラ言語でコンパイルが不要になるように」という明快な考え方はとても参考になった。 

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm