トップ 最新 追記

2019-01-01 [長年日記]

_ 今さらImageOptim-CLIでPNG最適化

スクリーンショットを使う機会ってあるじゃないですか。でも mac のスクリーンショットをそのまま貼ろうとすると 24bit ででかいので、さすがにファイルサイズを節約したいわけです。

で、Photoshop のある環境では「Web用に保存」を使ってたんだけど、さすがにおおげさだし、ない場合にどうしてたかというと以下のような感じだった。

  • GIMP で PNG-8 を作ろうと画像のモードを Indexed にすると色が大きく変わってしまう
  • Preview.app で PNG-8 を作る方法が分からない
  • ImageMagick は option 調べるのが面倒
  • sips は調べたけどよく分からず

ということで

JamieMason/ImageOptim-CLI: Make optimisation of images part of your automated build process

を入れた。24bit のままでも半分くらいになったりするので、もう減色とかいいや。

Windows だと

Pngyu この辺を使えばいいのかな。


2019-01-07 [長年日記]

_ Amazon Certificate Managerで完全自動更新を設定する際に気をつけること

ちょっとハマったのでメモ。

まとめ

  • ACM で手作業を完全に廃して自動更新するには DNS でドメインの検証を行う必要がある
  • その場合、指定ドメインか www で HTTPS 接続を受け付け、対象の ACM 発行証明書でレスポンスを返す必要あり
  • この証明書に矛盾があると自動更新は適用できない

参考

ハマったのはワイルドカードと更新時の検証と www の関係

ハマった環境の状態

  1. 人間向けドメインである www はフルマネージドホスティングで SSL 証明書の自動更新を設定している、つまり非 ACM の証明書
  2. その他のドメインは丸ごと ACM でワイルドカード証明書を発行

ここで 1 と 2 の証明書の発行元が食い違っている。食い違っていても発行自体はできる。DNS で CNAME 設定が正しくできればよいだけ。

問題は更新時。更新の際には

に従って ワイルドカード証明書の検証のために www にアクセスがくる。例えば

*.example.com

の証明書を発行していたとして、その検証のために

www.example.com

に HTTPS のリクエストがくる。

ここで www が ACM の証明書を返さないと「自動更新資格が使用不可」という状態になる。ACM 管轄外の証明書に対して自動更新を適用することはできないと判断される。

※ ちなみに、今回はワイルドカード証明書をやめることで矛盾を解消して自動更新の方を優先した。

Tags: AWS Security
本日のツッコミ(全2件) [ツッコミを入れる]

_ test [ドキュメントにある通り、*.example.comの検証のために、example.comとwww.example.c..]

_ wtnabe [合ってると思います。 厳密に言うと example.com に ACM 発行の証明書を持たせて www.exa..]


2019-01-08 [長年日記]

_ Vue CLI 3マジすごい

Vue CLI 3 の用意する設定は現時点では確かにベストの形に近く、かつカスタマイズもそこそこしやすいのでとても助かる。生で Webpack と戦う気はなく、かつ Vue.js に振るのは決定しているという状況なら間違いなく Vue CLI 3 から始めるのがよいと思う。以前 v2 を試してみた時とは比べものにならない。

  • Webpack 4 の zero config は「command line option で賄える、そこにある程度 default が用意された」程度の意味であって、信じてはいけない
  • Vue CLI 3 の言う Webpack 設定の抽象化は Nuxt.js v1 よりもスジがよい感じ
  • 大変なのは loader 設定であって、そこから解放されるだけでも十分価値がある
  • よく使われてる plugin や webpack-merge, webpack-chain の知識が手に入るのはありがたい
  • vue ui マジ神
  • vue-cli-service inspect マジ便利

特に最後の inspect は隠されていた情報がちゃんと見えるようになって、今の挙動に何の設定が関与しているのか、を追えるようになるのがとてもよい。Nuxt 1 を使っていた時はここに苦しめられた記憶があるので。

Webpack が 3 から 4 になって良くなったことは分かってないけど、Vue CLI が 2 から 3 になったのはマジライフチェンジング。

※ 個人的には CopyWebpackPlugin お前勝手に何しやがるという気持ちが芽生えました。そういうのは見えるように vue.config.js に置いておくべき。


2019-01-09 [長年日記]

_ サーバサイドフレームワークのUrlHelperとフロントエンドアセットバンドラの組み合わせの考え方

具体的に言うと Rails と Webpack などの組み合わせ方の話だけど、ツールではなく考え方の方を整理しておくことで、それぞれ変わった時にも再利用できるノウハウにしたいと考えていて、現時点で分かっていることをダンプしておこうと思う。

うまくいくかどうかは分からないけど。

なお、アセットバンドラの設定方法、依存解決時に考えなければいけないこと、同じくトランスパイラの設定などについては無視している。あくまでサーバサイドフレームワークと組み合わせる際に、特に cache buster を考えた際のアセット管理についてのメモになっている。

cache busterとasset digest (hash name)

Railsだけで完結していた時代のアセット管理

Rails 3.1 以降を使っていて助かるなぁと思ったことの一つに Asset 管理がある。Rails を使っているとたいして何も考えることなく img や script などの cache buster が有効になり、それもコンテンツの digest を基本にファイル名の書き換えで実現され、CDN も簡単に設定できた。

これは当時かなり先進的な機能だったように思う。自分がよく関わるのは他に PHP 系のサイトだったんだけど、PHP の世界ではこの辺はまだ手動でバージョンを打つか、せいぜい timestamp ベースの revision を打つところまでだったように思う。*1

Node.jsツールチェインの充実とESの進化とサーバサイドフレームワークとの齟齬

しかしこの Rails の asset digest の機能は CoffeeScript や Sass のコンパイルの機能と一体になってしまっているので、Node.js ツールチェインの充実と EcmaScript の進化とともに「悪しき習慣」の一つとして捉えられるようになった。

変換系は確かにサーバサイドで持つ必要はない。当初は CoffeeScript も Sass も Ruby 実装が先行したわけだが、これらのニーズを持つ人たちがみんな Ruby の必要なプロジェクトに関わっているわけではない。*2

しかしではその成果物をサーバサイドフレームワークの View で取り込みつつ cache busting が有効に機能しないといけない。ここのすり合わせが難しさの一つだと考えている。

モダンフロントエンドを加えるために考えなければいけないこと

フロントエンドの世界はサーバサイドと違ってそれだけで完結せず、様々な環境に対応せざるを得ないために考えなければいけないことが多い。いつ、どこで、何を実行するのかをプロジェクトに合わせて全部設定する必要がある。

  • アセットバンドラ管理のアセットをどこに置くのか
  • サーバサイドフレームワークが配信するアセットはどこに置く必要があるのか
    • アセットバンドラはどこに成果物を出力すべきか
  • フロントエンド側の CI/CD
    • アセットバンドラをいつどこで動かすのか
  • cache buster

アセットバンドラやトランスパイラ自体の設定方法などについてはここでは無視する。

まずモダンフロントエンドのアセットはサーバサイドフレームワーク管轄外に置く

これは間違いなく基本になるだろう。

app/assets/    <- サーバサイドフレームワーク管轄
app/frontends/ <- サーバサイド管轄外

みたいなものでもよいし、

app/         <- サーバサイドフレームワーク管轄
    assets/
frontend/    <- フロントエンドフレーム管轄

みたいなものでもなんでもよいと思う。

そのうえであとの行程に選択肢が一応ある。

あえて既存のサーバサイドフレームワークの仕組みに乗せる

AssetPipelineに無理やり乗せる方法

一つの考え方は AssetPipeline の仕組みの上に無理やり乗せる方法である。数が少ないうちは一応可能。

これのメリットは「(枯れている)サーバサイドのアセット管理の仕組みから漏れるものがない」という点に尽きる。

しかしやはり無理があり、例えば Rails だと

  • sprockets が依存関係解決で呼び出していない、entry point として機能するアセットは precompile 指定が必要
  • かつ sprockets が依存解決しないように stub 指定が必要
  • stub 指定するためにはその成果物が存在する必要がある
  • うっかり git add されてもいけない

など、ハマりどころは多い。

それでも例えばデザイナが関与しない JavaScript を一つだけ Browserify で出力できればよい、みたいな場合は選択できなくもない。

AssetManifestだけ共有してあとは知らん顔

AssetManifestだけ共有してAssetPipelineを使わない方法

実は Webpacker が実現しようとしていることも、最近の「脱Webpacker」が実現しようとしているのもこれなんだなということが分かってきた。

Webpacker は

  1. Webpack を利用した Asset 管理
  2. AssetPipeline を利用した Asset 管理

の二つを並列で動くようにしており、それぞれ Helper も別々なので、

  1. javascript_pack_tag
  2. javascript_include_tag

の両方を使う必要がある。*3

この時、 javascript_include_tag は AssetPipeline の生成した manifest を参照しており、javascript_pack_tag は Webpack の生成した manifest を参照している。

ということはモダンフロントエンドを組みわせるために本当に大事なことは

  • アセットバンドラの生成した manifest をサーバサイドから利用するための何か
  • 成果物を適切にサーバサイドで利用できるための(public URLなどの)設定

になる。

ここの解決がモダンフロントエンド導入の際に、フロントエンドフレームワーク選定とは関係なく避けて通れないポイントの正体と言ってよさそうだ。

※ くどいようだが、アセットバンドラの依存解決やトランスパイラの設定などに関してはここで無視している。そこが面倒くさいのは承知のうえ。

参考
Tags: Webpack Rails

*1 timestamp ベースの revision を付加するのは今もほとんどの Web サイトでお手軽に利用できて確実に cache busting できるので、何もないサバンナに降り立ってしまったのなら最初にやるとよい

*2 逆に今ならみんながみんな Node.js を必要としているわけではないと言えるのだが、エコシステムが圧倒的に強くなったので、そこにはもう選択の余地はないだろう。

*3 逆に、上で紹介した AssetPipline を利用した方法ではこれがすべて一つに集約されるので、Rails の View を触る部分に関して新しいノウハウを必要としないのがメリットの一つである。


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 一辺倒で、うーんと思わなくもないんだけど、「コンパイラ言語でコンパイルが不要になるように」という明快な考え方はとても参考になった。


2019-01-20 [長年日記]

_ 伝統的なサーバサイドWeb開発アンチパターンとその対策 - C, V編 -

ざざっとメモ。当たり前ですが網羅はしてません。いわゆる After Rails な Web MVC を想定しています。紹介するコードは Ruby か PHP だけです。システムの規模などに依存しない内容です。悪しからず。

続くかどうかも分かりません。

まず基本のベストプラクティス

1. 名前重要

それを表す最もよい名前を探すこと。

よい名前が付けられない場合はそのことについて十分よく知っているとは言えない。よくない名前、嘘をついている名前*1はそれを後から読んだ時に混乱を生み、理解を妨げ、変更時に問題の温床となる。

2. KISS ( Keep It Simple, Stupid )

いろんな業界、いろんなシーンで言われるのでよく分かると思う。プログラミングにおいては

  • 変数を多くしすぎない
  • functionを長くしすぎない
  • (classに対して)functionを多くしすぎない

とかそんな意味で考えるとよい。

人間がパッと理解できるのはせいぜい3つ。それ以上になるなら何かがおかしい。

3. DRY ( Don't Repeat Yourself )
  • 同じことを何回も書いてるならそれはやばい兆候
  • その後変更が入った際にそれらすべてを「正しく変更できるか?」常に問い直そう。

ただし、一切のコピペを禁止するのは「早すぎる最適化」でよろしくない。目安は3回。

テスト書け

「伝統的な」と書いている通り Web MVC のフレームに対するテストの自動化は今や十分こなれていると言ってよい。まず書け。話はそれからだ。

テストの書きやすさ書きにくさ、ユニットテストなのかe2eなのかみたいな話はここでは省略する。

想定する構成

伝統的なサーバサイド Web MVC を想定している。伝統的な Web MVC には

  • (router)
  • Controller ( HTTP request / response を担う )
  • View ( response 内の詳細を担う )
  • Model ( アプリとして重要なロジックを担う )

がある。

アンチパターン1 - Loudness View

※ 一般的な呼称ではありません。自分で勝手に名前を付けました。

個人的にはサーバサイド Web でプログラマ / エンジニアが関わるものには大別して「Webアプリ」と「Webサイト」があると思っていて、業務アプリとかなんらかのソリューションを提供するものは全般的に「アプリ」と呼んでよいと思うけど、いわゆるブログ、CMSではないかもしれないけど結局「読まれる情報」を提供するためのものは「サイト」と呼んだ方がよいと思っている。

「サイト」の場合、非常に強い要求がない限りはフロントエンドヘビーにする必要はない。非常に強い要求とは尋常じゃなく大きなトラフィックをめちゃくちゃ高速に捌くために PWA 化したいとか細かく分析したいとか、モバイルで無限スクロールを実現しつつ非モバイルと共有したいとかそういう要求。

逆に「アプリ」に関してはユーザーの操作は「サイト」よりもやや複雑であり、URI 設計は改めて考えなければいけないが、API + リッチクライアントな方向に倒してしまうのも一つの手なので、イマドキは View が肥大してしまうことを悩む必要性は減ってきているのではないかと考えている。(もちろんその分フロントエンドの開発の方に難しさがシフトしている。)

そのうえで。

「読まれる」ものを動的に生成するということはそもそもそれなりに変数は多い。変数が多いのはよくない。View で扱う変数が増えるままにすると素朴な実装では Action の変数が増えてしまう。

対策
  • 変数を連想配列やオブジェクトでまとめられないか考える
  • オブジェクトでまとめられるなら「役割」がまとめられるはずなので Cells などを利用できないか考える
    • Cells は HTTP と直接結びつかないアプリ内 micro MVC を実現するもの

trailblazer/cells: View components for Ruby and Rails.

上の Cells は Ruby 用で PHP の世界にはやや馴染みが薄いものらしいが、CakePHP 3 にはあるようだ。

CakePHP3新機能 View Cellの使いどころ - Qiita

残念ながら Laravel 用のものでまともに動作する Cells は見つけることができなかった。というか Laravel には標準で View Helper を簡単に定義できる機能がないので、どうも構造的に V と C が汚れやすい問題があるように見える。代わりに

この辺が使えそう。

Ruby の Cells は以前は Rails 依存だったが今は独立しているので、うまく整理すると汎用のものを PHP でも作れるかもしれない。

Cells にまとまればテストは HTTP request に依存せず行える。(逆に HTTP request をそのまま渡す、params をそのまま渡すのはよくない兆候と言える。)

とにかく View から見える変数が多すぎると人間の手には負えない。コンポーネント分割の話はデザインの文脈やフロントエンドの文脈でも語られている。最終的にはこの辺とすり合わせながら役割を整理する必要がある。まったく整理されておらず、変数が増えすぎることだけが分かっている場合はちゃんとアラートを上げること。

アンチパターン2 - Fat Controller

Controller の Action は routing に紐づいている。1 Action : 1 function がだいたい基本である。 Action で担う責務が多い場合、KISS の原則を守れなくなる。

具体的には以下のように破ってしまう。

  • 変数が多すぎる
  • function が長すぎる
アンチパターン2-1 Actionの変数が多すぎる

これには複数の理由がある。だいたい以下のどちらかあるいは両方。

  1. View で表示する変数が多い
  2. Model が多い、あるいは Model に渡す変数、Model から受け取る変数が多い

変数の代入が増えてきた class ベースの Action の場合、super class に持たせたり、Action の lifecycle を使って Action に処理が渡ってくる前に「初期化」したりすることが多いけど、これは誤り。Action と View が気にしなくてはいけない変数が減っていないのなら意味がない。

View の変数の数の話はアンチパターン1 の話と同じなので省略。*2

対策 - Viewの値の取得、決定ロジックはViewModelあるいはPresenterへ

View で表示する変数がそれなりに多く、かつその準備のためのロジックが Action の中に散らばっているのであれば ViewModel あるいは Presenter が使える。ViewModel という言葉は文脈によっていろんな意味を持ち得るし、View と Presenter の分離と呼ばれたりもする。Rails の世界ではどちらかいうと Presenter と呼ばれ、Laravel の世界では Presenter がほぼ Decorator と同義なので ViewModel と呼ばれたりするようだ。

変数が多すぎるアンチパターンは、Rails の場合、インスタンス変数が View から丸見えなのでインスタンス変数が増えすぎるという兆候で現れる。Laravel の場合は変数の binding を書く部分が膨らむ形で現れる。いずれにせよそれらの変数が増える部分をすべて Action の中に書くと Action の責務が分かりにくくなる。そこで ViewModel あるいは Presenter を入れる。

分かりやすいのは Hanami の View で、Template から参照できる変数をメソッドで定義する というものだ。Cells は View そのものを含めての分割になるが、ViewModel あるいは Presenter は View 向けの値の取得、生成の際のロジックを分離、隠蔽するためのものになる。これは HTTP からも HTML からも独立しているのでテストしやすい。

多くの場合はこの方法でロジックも変数も減らせるはず。

Model も Presenter から呼べばその前処理ごと隠蔽できるはずだ。

アンチパターン2-2 Actionが長すぎる

まず大前提なのだが、変数を扱う部分が減れば Action の長さはもうだいぶ縮んでいるはずである。

にも関わらずまだ Action が長い場合は View に直接結びつかないロジックが Action を膨らませていることになる。恐らくは Model とのやりとり、それも複数の Model とのやりとりでなんらかのロジックを組み立てているはずである。

対策 - ロジックを担うのはModel

複数の Model にまたがるロジックがどうしても Action を長くしてしまう場合は新たにそれを担う Model を作ればよい。まずこれ。Model は別にデータベーステーブルに紐づいていなくてよい。迷わなくてよい。ロジックを担うのは Model の責務。そして複数の Model 間をまたぐロジックは恐らく HTTP request と直接紐づけることなく書けるはずだ。

まず Controller, HTTP request と分離すること。そしてそのロジックのテストが十分に書きやすくなっていること。そこをスタート地点とするのでよい。

どうしても Model を作るのが気持ち悪い場合、扱いやすいのは例のサービスクラス、サービスオブジェクトだ。ただしサービスは難しい。サービスは雑に言うと「呼べる処理を一つにする」程度の意味でしか機能しないことが多い。

「サービスを作ればよい」という認識が生まれてしまう可能性があるとしたらそれはまた別なアンチパターンと呼んでよい。

アンチパターン2-3 Actionの中で条件分岐が多い

ここまでで View に渡す変数は減っていて、Model に押し付けるべきロジックも減っている前提で、それでも条件分岐が多いのはたぶん View を使い分けたいとかパラメータによって表示される内容を増減させたいと思っている。

対策

これも ViewModel あるいは Presenter でよいはず。

アンチパターン2-4 Actionが多すぎる

これは最悪のパターン。Controller が分かれていない。何に関する request を受け取っているのかまったく整理できていない。

これは頑張って分けるしかないが、順番としてまず Action を短くしていくのを先にやった方がよい。Controller class がでかいということは恐らくコンストラクタでかなり頑張って何かを準備していたり、大量のフィルタがあって「なんとかして共通化できるものを共通化して少しでも事態をよくしようと」したコードが入っているはずだ。

これは単純に OOP の失敗パターンである。Web MVC 独自の問題ではないので、そういう知見を普通に活かしていけばよい。

アンチパターン3 - Logicful View

よくあるのは

  1. if で分岐しまくっている
  2. Helper 関数などを使っていてもその引数が多い
  3. 値をそのまま見るのではなく変換の処理が挟まっている

など。

単純な boolean 分岐、単純な変換でも数が多くなれば十分にあぶないコードである。View ではその数が多くなりやすい。

対策
  • partial に分ける
  • cells に分ける

要は分岐、変換ごと分離しちゃう。

多くの変数も View 側で渡さなきゃいけないのかを吟味して不要なら Cells など別なレイヤーで処理してしまう。

アンチパターン4 - Controller Filter

Controller の Action の記述を短く抑えるために、Action ではなくその前後に動作する Filter(Rails だと before_action とか)に書きたくなる場合がある。

しかし例えば Action のバグを直すために Action に注目しているような場合に Filter の動作は目に入って来にくいので、複雑な動作が Filter に含まれるとか、Filter の数が多すぎるのはメンテナンス性が低いと言ってよい。

あと独立した function になってなくて HTTP request と切り離してテストできないとしたらそれは完全に誤り。

対策

特に Action の中で参照する値を扱っている、下手すると書き換えているような場合は Action から明示的に呼び出す形にしておくべき。params の validation なんかもそれが繊細であればあるほど Action の中から明示的に呼んだ方がよい。

対策

アンチパターン5 - JS in View

JavaScript リテラルを View の中に書いちゃうやつ。これをやると

  • サーバサイドの状態を簡単に JavaScript に渡せる

代わりに

  • ESLint でチェックできない
  • テストコードも書けない
  • cache も効かない
  • サーバサイドの状態がリテラルで渡されるので、nil とか JavaScript で扱えない状態が発生する
    • 最悪 SyntaxError とかリカバリ不能な状態になり、すべての JavaScript の実行が止まる
対策

絶対にやるな。

絶対だ。絶対に許すな。

お前も 2016年に設計なんてない、そこそこの量のJavaScriptのエラーを監視して対策し始め たいか?

いいか。絶対に許すな。

サーバから何も渡さず、何のロジックもない十分に短いコードだけは例外的に許可しろ。それ以外は全部ダメ。

*1 名前と異なる機能を含んでいるとか

*2 稀に Action の変数が多すぎるのを気にしてなのか、View の layout 辺りから共通の変数を取得する処理を書きまくる人がいることだけ書いておく。絶対にやめろ。View で気にする変数が減っていないから間違えている。Action から渡した変数を上書きする可能性もあるし View から見える変数も減っていない。何も解決できていない。


2019-01-22 [長年日記]

_ RubyのCellsのv4以降の使い方メモ

trailblazer/cells: View components for Ruby and Rails.

主に v2 以前から使っていた人向け。なんかずーっと ViewModel という言葉に引っかかっていたんだけど、ちょっと分かったかも。

まずは基本の使い方から。

定義

class SampleCell < Cell::ViewModel
  ..
end

呼び方

micro MVC 的な呼び方
cell(:<name>[, :<model>]).(:<state>[, options])

これで Cell の中のメソッドを読んだ結果を String として(to_sして)出力できる。View の中で micro MVC として使う Cells v2 以前の render_cell() 時代の使い方のイメージ。

ただのCellオブジェクトを取得する呼び方
cell(:<name>[, :<model>])

これで文字列になる前のただの初期化済み Cell オブジェクトが取得できる。

Cellの実体は.()でcallさせると安全にto_sできるオブジェクト

Cells は定義の部分よりは呼ぶ部分の方がちょっと気持ち悪い。まずマジカルさの一つは

cell().()

という見慣れない書き方なのだが、この .() は call() の syntax sugar だった。

Ruby | 「call」メソッド の Syntax Sugar 「.()」 について - Qiita

では call はどうなっているかというと、以下のようになっている。

     def call(state=:show, *args, &block)
       content = render_state(state, *args, &block)
       content.to_s
     end

call すると render して to_s している。*1

さらに

   def to_s
     call
   end

が定義されているので、 String として評価される context ではマジカルに #show が呼ばれ、view を render して何かが出力されるという算段になっている。

これを意図して rails generator で cell を作ると、まず

def show
  render
end

だけを持つ class ができる。

ということで、「なんかいい具合に to_s するための仕組みの入っているオブジェクト」というのが Cells の実体と言ってよさそう。

一つ気をつけなきゃいけないのが、Cells は View ではなく Controller の context で実行されているということ。もう一つ、v4 以降の Cells は Rails 非依存なので、Controller を継承していない。cells-rails gem では関連 module はいろいろ include しているが、Controller を継承していることは前提にしてはいけない。

で、ViewModelとして扱うってどうよ?

Controller から View 向けのロジックを追い出すために Cells を使うとよいと「伝統的なサーバサイドWeb開発アンチパターンとその対策 - C, V編 - - あーありがち(2019-01-20)」に書いたが、Cells で本当によいのだろうか?という疑問は感じるかもしれない。むしろ PORO ( Plain Old Ruby Object ) の方がよいという意見もあるのではないかと思う。

結論から言うと PORO でもよいと思う。

ただ View 側に渡しやすい何かにするための ViewModel なはずなので、最初からそういう仕組みの用意されている Cells にしておけば自動的に置き場所も決まるし、安全に to_s されるし、独自の template を追加することもできるし、Helper も呼べるし、testability も考慮されてるし、まーだいたいよいことづくめだと思う。どうせ何らかの支援は欲しくなるはずだ。

個人的には Cell という名前だけが非常に引っかかっていて、どうしても micro MVC を用意するイメージが強いので、いっそのこと

app/cells/*_view_model.rb

みたいな名前付けで置いといて*2、呼び方も

FooViewModel.new

みたいにしておくと、呼ぶ側からは明らかに render_cell の頃のアレとは違う使い方をしている感 が出るのでよいかもしれない。

これなら micro MVC 的な Cells と ViewModel を使い分けている感じをさせつつ、使っているツールは一つに絞れる。

Tags: Ruby

*1 cells-rails ではこれをさらに html_safe している

*2 app/view_models/ でもよいが


2019-01-23 [長年日記]

_ JSONでデータを返すAPIは構造の意味を持たせつつArrayを返そう

すっげー初歩的な話。初歩的すぎて『Web API: The Good Parts』にもたぶん載ってない。

あと envelop の話はあえて無視してます。envelop を付けるべきか否かはこのエントリでは扱いません。あくまでデータの話に限定しています。

まとめ

自分でお手軽に作る時に key-value のデータをそのまま返しちゃう場合があるけど、これはやめた方がよい。

つい

{
  "key1": "val1",
  "key2": "val2",
  ..
}

こういうことしたくなる。楽だけどこれはやめた方がよい。

[
  {
    "key": "key1",
    "val": "val1",
  },
  {
    "key": "key2",
    "val": "val2"
  },
  ..
]

この方がよい。

例えば id と name を持つデータなら

{
  1234: "alice",
  2345: "bob"
}

ではなく

[
  {
    "id":   1234,
    "name": "alice"
  },
  {
    "id":   2345,
    "name": "bob"
  }
]

の方がよい。

理由1 - 順番が意図せず変わる

まず Object や Hash, Map などの構造をそのまま JSON に serialize する際に順番がどうなるか分からない。

本来順番に依存しない構造なのだから当たり前なのだが、例えば PHP の場合は

  • array は順番の維持される map のような何か
  • json_encode は key が数値だと array の順番を並べ直して encode する

というコンボが発生して、結果として json_encode する前と後で順番が変わってしまう。これでバグが生まれると割ときついですね。盲点。あくまで PHP の array や Ruby 1.9 以降の Hash がたまたま順番を維持してくれるだけという簡単な事実を忘れてはいけない。

で、これが大事なところなのだが、

本当に順番に依存しないかどうかはそのデータを serialize/deserialize する部分だけでは分からない。それは UI や他の DBMS などの「インターフェイス」の部分で何を期待するかで決まる。

だから本当は元のデータ構造の段階から順番に期待する処理は順番が確実に維持される構造にしておくべき。つまり

{}

ではなく

[
  {},
  {}
]

の方がよい。こうしておけばサーバ側とクライアント側で扱うデータ構造が変わってしまうことがないし、処理がブレることもない。

理由2 - なんの項目を扱っているのか分からない

ただし、上のように Ruby で言う Hash の Array みたいな構造にしただけではまだデータを扱いにくい。2項目しかないとつい

[
  {
    "key1": "val1"
  },
  {
    "key2": "val2"
  },
  ..
]

みたいにしたくなるが、これはデータを作るのも利用するのも同じコードの中ならまだいいけど、距離が離れると意味が分からなくなるのでやめた方がよい。

「この key はどういう意味なのか? value は何か?」がデータの中に存在しないし、だいたいの言語で key を取り出す方法も value を取り出す方法もない。*1

で、結局 record[0], record[1] みたいなものをベタ書きすることになる。

これはつらいのでやめるべき。

理由3 - 変更に弱い

理由2 で挙げた「避けた方がよい形式」だが、項目が3つ以上になったらこの形式は通用しない。つまり何かあったら

  • データ構造をやや大きく変更せざるを得ない
  • データ構造が変わるとクライアント側のコードへの影響が大きい

だったら最初から全部同じ方法で扱うようにした方がよい。

Tags: JSON Web

*1 keys や values は取り出せるが、一つしかないのは分かっているのにいったん Array が手に入ってどんな構造を扱っているかも分かりにくくなる。

本日のツッコミ(全4件) [ツッコミを入れる]

_ mather [オブジェクトの属性としてのkeyやidと、任意項目としてのデータの話がごっちゃになっている気がしました。 単に「複..]

_ wtnabe [ありがとうございます。 仰る通りなんですけど「本当に順番に依存していないと断言できる?」って場合が稀によくある..]

_ mather [いや、なんかちょっと言いたいこととずれてる気がします。 端的にいうと、Userという単一のオブジェクトを表現するJ..]

_ wtnabe [あーなるほど。それも仰る通りですが、そもそもの構造の話と今回の話は独立して考えることができると思っています。本来の構..]


2019-01-26 [長年日記]

_ Laraval Bladeの機能で擬似Layout

知ってる人には当たり前の話。After Rais の世界の View の Layout という考え方はどれも同じようなものかと思っていたのだが、意外とそうでもなかったというメモ。

LaravelはController側でLayoutの制御を支援してない

Layout を Controller の property で指定する機能はあるが、Rails の view のように render の際に layout を指定する機能はないため、Action 側でコントロールするのはやや難しい。

abstract class Controller
{
  ..
  protected $layout;
  ..

  protected function setupLayout() {}
  ..

  public function callAction($method, $parameters)
  {
    $this->setupLayout();

    $response = call_user_func_array(array($this, $method), $parameters);
    ..
  }
}

こんな感じ。Action に渡ってくる際にはもう layout の解決は済んでしまっている。

むしろこの辺は Blade 自体が柔軟というか強力すぎる機能を提供している。

Bladeはdirectiveで@extendsする

@extends, @section, @yield を利用して特定の view の特定の領域にコンテンツを inject することを global に許可しているので、layout というか自身の container になる view を view の中から指定することができる。

例えば以下のような感じになる。

in layout.blade.php

@yield('content') // <-- ここに @extends した側の @section のコンテンツが入る

in contents.blade.php

@extends('path.to.layout') // <-- ここで container になる blade の名前を指定

@section('content')
  ..  <-- この中身が @yield に置換される
@stop

ポイントは以下の2つ。

  1. @extends で送る先の View を指定する
  2. @yield と @section のセットでコンテンツを送り込む

1 がめちゃくちゃ強力。

Controller や Renderer 側で View の階層、機能を管理するという考え方じゃなくて blade 自体が Blade 全体の管理しているものをすべて知ることができる という考え方。

まー確かに実に PHP っぽい。ちょっと怖いけど。

これを利用して「名前空間を整理すると」layout というか container となる view をまとめておくことができそうだ。

app/views/containers/

みたいな。

参考

Tags: Laravel PHP

2019-01-27 [長年日記]

_ CellsはLayoutを持っているか

RubyのCellsには独自のlayoutがある

trailblazer/cells: View components for Ruby and Rails.

使い方は以下のような感じ。

class FooCell < Cell::ViewModel
  layout :simple

  def bar  # state
  end
end

※ Rails の Controller 的にはメソッドは action なんだけど Cell::ViewModel 的には state になる。

レイアウトはどこに置くかというと、cell 用の view を置く場所にそのまま。名前付けに何かルールがあった方がよさそう。

cells/foo_cell.rb
cells/foo/bar.erb    <-- state用template
cells/foo/simple.erb <-- layout

Laravelのtorann/cellsにはlayoutはない

※ 上の Laravel 4 用の torann/cells は fork 版です。オリジナル版は type hint が邪魔して実際には使えないので。

この Cells にはそもそも独自の view object というものは存在しない。あくまで Blade の中に一つの記法(directive)を用意して、その中で独自に template を読んで render した結果を返すだけ。CellBaseController はあるが Laravel の Controller のようには layout を指定する機能はない。

というか Laraval の Controller は Layout 制御を積極的に支援していない ので、考え方が違う。@extends, @section, @yield と、Ruby 版の Cells と同じように名前付けのルールがあればよい。


2019-01-28 [長年日記]

_ サーバサイドViewModelのボキャブラリをクライアントサイドに寄せながら整理してみる

サーバサイドで ViewModel と呼ばれるもののボキャブラリがあまり整理されていないように見えるので、あれこれ調べたり書いたりしていた。そこでちょっと見えてきたものを挙げていきつつ、最終的には近年概念が大幅に整理されたクライアントサイドの ViewModel に寄せていくことで、荒れがちな View 由来のコード周りに秩序を与えられないか考えたメモ。

雑にパターン出し

サーバサイドの ViewModel という概念は以下のパターンで適用できそう。

  1. 変数の binding を担うもの
    • Hanami::Viewlaravel-view-models に相当
    • Rails では locals 縛りとかにしなければ不要なもの
    • View の直前でかつ Model としての複雑さはあまり考慮しなくてよいのでいわゆる Presenter と呼びたい
  2. 変数のセットまでの処理が複雑なもの
    • Fat Controllerの原因の一つを取り除く
    • たぶんこれは本来やったらダメなもの(正しく View 側の設計ができていない)
  3. state の複雑なコンポーネントを扱うもの

このうち 3 がクライアントサイドの ViewModel に近く、最も ViewModel っぽく機能しそう。これまで自分は View Objects という名前が全然しっくり来なくて馴染めなかったんだけど ViewModel と呼ばれるとよいかも。*1

ちなみに単なるデータ構造を ViewModel というパターンもあるにはあるようだが、個人的にはそれは Model の Presentation (serialize)に相当すると思っているので、除外している。

サーバサイドViewModelはクライアントサイドのコンポーネントに対応できるのか?

Cells を例にとると、定義側は

cells/foo_cell.rb

class FooCell < Cell::ViewModel
  def bar
  end
end

cells/foo/bar.erb

<div class="cell">
</div>

みたいな感じになる。

これを呼び出す側が

@cell(:foo).(:bar)

こんな感じ。これで、呼び出すメソッドに応じて View も中の処理も切り替えることができる。

ここで疑問を覚えるのが、メソッド単位で View が変わるだけでは Component として複雑な状態を保持するには機能が足りないのではないか、ということである。

クライアントサイドの ViewModel Component は nest させることができ、悪名高き「propsバケツリレー」を使って state を受け渡す形を守ることで個々の Component のシンプルさを維持しつつ、複雑、大規模な機能、システムまでスケールすることを目指している。

サーバサイド ViewModel にクライアント ViewModel のその考え方を援用できるのだろうか。

RubyのCellsはnestできるしlayoutもある

trailblazer/cells: View components for Ruby and Rails.

Ruby の Cells については nest もできるし、layout もあり、またメソッドを state と(内部では)呼んでいるので、概ねクライアントサイドの ViewModel の考え方を援用できそうに見える。

例えば状態を3つ持つ Cell を作り、以下のように layout も用意してあげれば

layout

<div class="layout">
 <ul>
   <%= yield %>
 </ul>
</div>

cell の view

<li><%= complex_logic_results %></li>

最終的には

<div class="layout">
 <ul>
   <li></li>
   <li></li>
   <li></li>
 </ul>
</div>

こういう形のタブ構造などを簡単に実現できる。

このような形にできることが分かれば、Component の役割とどのような State を持つのかをモデリングすることで自ずと Cell の形が決まるし、形状、表現に変更が入ってもロジックやデータ構造にそこまでのダメージがないようにすることもできそうである。

Laravelのtorann/cellsの場合

ドキュメントにはそういう話はないので中のコードを読んだり実際に試してみると、

  • Layout の機能は CellBaseController にはないが、blade テンプレートの置き場所と名前付けにルールを設けることで layout のようなものは可能(layout の利用は @extends)
  • @cell の nest は @include の nest と同義なので特に問題ない

ということで やれば できそう。

cf. CellsはLayoutを持っているか - あーありがち(2019-01-27)

課題はロジックの分離とテスト

ViewModel として見た時にこれまで意識して来なかった課題が見えてくる。それは

  • ロジックを処理するメソッドと View を render するメソッドの区別がない

ことである。

例えば Vue.js を例に取ると、ViewModel コンポーネントは以下のような構造になっている。

{
  data:       <-- binding 用の data
  extends:    <-- 継承元
  components: <-- View で custom element として利用する component
  computed:   <-- メソッドベースの binding 用の data
  methods:    <-- event handler
}

このうち、 だいたい computed に判定用のメソッドを置く感じになる。*2ということは computed をテストすると View のことを気にしなくてもロジックはテストできる。

しかし Cells の場合はメソッドと property しかなく、state / action はメソッドであり、これらを call すると render するのが基本である。これだとうっかりロジックを呼んだらそれが View に露出してしまう。幸い Ruby の Cells はまだテストも考慮されているが、torann/cells にはそれもない。

よくあるのは外から呼べないようにロジックの部分を private とかにしてしまう方法だが、それをやると今度はテストコードでテストできなくなる。

ではどうするか。

案1 - ロジックの結果を変数に放り込む

実際に torann/cells で書いてみた感じだと、property / attribute の方に「ロジックの結果を保持」するのがやりやすそうな気がした。すべてを state / data として扱って、初期化時にその前処理を終わらせる。template 側にロジックを書く際にも attribute はそのまま参照できるし、それっぽい名前の attribute であれば自然に読める。

「コンストラクタ頑張りすぎ問題」のようなにおいはするが、基本的にサーバサイドの ViewModel は副作用を扱う必要がないのでわざわざ階層を深くしなくても、メソッドの名前空間が render 処理に予約されているのであればメソッド以外を利用する、という考え方は一応、理には適っている。ような気がする。

案2 - 名前空間を独自に切る

例えば簡単な例だと

  • ロジックを扱うメソッドを _ で始める

というような形。

torann/cells の内部的にも $__env という名前で「頑張っている部分はある」し、_ や __ で始まるものに特別な意味を持たせるのは LL 界隈ではポピュラーな考え方だ。prefix を付けてよいというルールにすれば _ だけに限る必要もない。

案3 - ロジックをdelegateする新しいModelを作る

Ruby の Cells の場合は Model を一つ与えてそいつで delegate しつつ render するのが基本スタイルなので、その Model にロジックも Collection も全部押し付けることで ViewModel の名前空間で困らないようにすることはできる。

その場合、

app/cells/models/

みたいな階層を適当に掘ってみるのもアリなのではないだろうか。こうすれば間違いなくロジックはテストしやすくなる。

torann/cells の場合は Model object ではなく attributes array を受け取る設計なのでやや勝手が異なる。恐らく array の中に Model を押し込むことで似たようなことはできると思う。案2 とのハイブリッドのような形で、そこに Model を押し込んだことが分かる名前のルールがあれば可能そうだ。

とは言えコンポーネントの概念だけで全部解決することはなさそう

目的の明確なアプリを作るのであれば、できるだけ分かりやすくシンプルにすればよいと考えることができるし、「ユーザーは何らかの操作をしてくれる」という前提で補足的な説明は全部ポップアップなどに寄せてしまうということもできる。

しかしいわゆる Web サイトの場合は「提示しなければいけないデータ」の他に「事前に促しておくべき注意事項」などもあるはずで、アプリを構築する際に扱いやすい ViewModel の考え方に寄せるだけではやや解決の難しいものも出てきそうではある。

その場合は state / action という言葉にこだわらず View を提供しやすいという柔軟性に頼るとか、どうしても複数の Model の情報を渡したいという要求にどう応えるかを考えるなど、やはりフレームワークの提供してくれない解決策を探る必要はあるだろう。

*1 という気になるんだから自分はどこまで名前重要信者なんだろうか。

*2 methods に置く場合もあるが、原則的に methods には副作用のあるものを置くはず。


2019-01-29 [長年日記]

_ Laravelのtorann/cellsの使い方メモ

完全に順番が前後しちゃってるけど。

呼び出し方

@cell(name, template, attributes, action)

内部の動作の抜粋

class Cells
{
  ..
  public function get($className,
                      $template = 'display',
                      $attributes = array() ,
                      $action = 'display' )
  {
    ..
    $instance = $this->app->make($className);
    $instance->setDisableCache($this->caching_disabled);

    array_set($cells, $className, $instance);
    ..
    $instance->setAttributes($attributes);
    $instance->initCell( $template , $action );

    return $instance->displayView();
  }
}
  • Cellxxx のインスタンスを作り
  • initCell() を呼ぶ
class CellBaseController
{
  public function initCell( $template = 'display' , $action = 'display' )
  {
    $this->template = $template;

    $this->init();

    $data = (array) $this->$action();
    $this->data = array_merge($this->attributes, $data);
  }

  public function displayView()
  {
    $path = "$this->name.$this->template";
    ..
    return $this->renderView( $path );
  }

  public function renderView( $path )
  {
    return View::make('cells' . DIRECTORY_SEPARATOR . $path,$this->data);
  }
}

initCell() の中では

  • init()
  • action() を呼んで、そこでセットされた結果を View に渡すデータとして保存
  • displayView() を呼ぶ

displayView() の中では

  • template の path をセットして
  • renderView() に渡して renderView() が View::make する
実装時の注意点
  • View で利用できる attributes に特定の値をセットするのは CellBaseController#setAttibute()
  • init() に渡ってくる前に @cell() を呼ぶ際に渡した attributes には getAttribute / getAttributes でアクセスできる
  • 個々の action は最終的に render の際に利用できる attributes に追加すべきデータの array を返す
    • action 固有のものはこの部分だけを見ることでテストできそう
  • 最終的に renderView() から View::make する際に template の存在チェックはしていないので、必ず対応する template を用意する*1

コードで示すとこう

class CellFoo extends CellBaseController
{
  function init()
  {
    // 共通の前処理はここ
    // abstractなので実装しないといけない

    // View から利用できる attribute のセットは原則こう
    $this->setAttribute('key', 'value')
  }

  function action()
  {
    // attributes に追加あるいは attributes を上書きしたい値を返す
    return array('action_key' => 'action_value')

    // setAttribute してもよいが、自動で追加されるし、
    // return する方がテストしやすいはず
  }
}

Action に対応する View は絶対に必要。

views/cells/foo/action.blade.php
Tags: Laravel PHP

*1 どうしてもイヤなら CellBaseController を override しておいて挙動を変えちゃった方がよさそう