トップ «前の日(01-19) 最新 次の日(01-21)» 追記

2004-01-20

_ portforwarder 2 + unison

が synchro system として有望か? 理由は

  • Zebedee は自分で自由にいじれるサーバでない限りインストールやポートの開放が若干難しい
  • rsync は cygwin 依存になり、安心して使える条件が限られる(cygwin → unix はコケやすい。unix → cygwin はまだ問題が少ないが。)

実験が必要だな。

Tags: Tool Net

_ FreeBSD 5.2-RELEASE

うむ。

Tags: Unix

_ A5 リングファイルで再利用紙手帳計画

  • ミスプリントなどの紙を再利用したいが、そのまま裏に印刷するのはいやなので手書きのメモ用紙として再利用したい。(あくまでストック目的に使う気はない。メモはデジタライズ前提で。)
  • A4 のサイズは大きくて使いにくいので半分に切って A5 で利用したい。
  • 現状ではダブルクリックで止めているが、これは普段の利用には便利だが外部の人と接触する機会ではちょっと使いにくい。
  • そこで A5 のリングファイルがあれば手帳っぽくて問題解決なのでは?
  • 通常の事務用品としては A5 を縦に利用するリングファイルはない
    • 横にした分厚いファイルならある
  • 手帳としての利用を前提にしたミニ6穴のものはある(普通のファイルよりは高く 800円ほど。それか皮製の 8000円とか。)
    • しかしミニ6穴のパンチは KOKUYO 製 4000円、PLUS 製 2000円と値が張る

だめじゃん。

  • 雑貨屋に 2穴の A5 サイズのリングファイルがあったりするらしい

それでいこう。

てなことを模索中。

Tags: Tool 日々

2005-01-20

_ shebang

行末がCR+LFなスクリプト

へーへーへー。-- で終わらせろと。といっても cr + lf なスクリプトなんて書くことないけど。

Tags: Ruby Perl

_ つーか EUC だめですか > Thunderbird

Thunderbird の RSS reader に試しにここの RSS を読ませたら文字化けしまくり。euc の指定を無視して utf-8 で解釈しようとしている模様。なーんーだーかーなーあー。Thunderbird ダメじゃん。

でも Sage と違って pre の改行が生きるので Wiki の diff を表示させるととても見やすい。次のバージョンに期待ってことで。

Tags: Tool Net

_ レガシーデザインをやめさせるには?

いやそんなたいそうな話ではなくて、font size="-1" とかサイズ固定レイアウトがのさばるばかげた状態をいつになったら脱することができるのだろう、ということなのですが。

誰かクールなデザイナがイマドキ font size="-1" なの?だせーって言ってくれればいいのだろうか。それとも例によってキムタクが Firefox とか Opera とか Safari とか使いながらこのサイト見にくいなぁっておもむろにソース見てイマドキ font size="-1" かよ!って毒づくようなシーンが必要なんだろうか。(ってどんなシーンだ。)それともヨン様が微笑みながらみんなに優しい HTML はこうなんですって諭してくれるような、そんな感じがいいか。

あれ。これだと男のデザイナにはアピールできないな。ゆうこりんのユニバーサル XHTML とかどうだろう。こりん星の決まりです、みたいな。でも電波扱いされたら困るな。あーこの際あれだ、世界一のトラックバックを誇る眞鍋かをりに、みんな、2005年はユニバーサルな Web で RDF で FOAF だよ!って言ってもらおうか。

まだ明るい時間帯なのにこんなこと書いてて大丈夫か、オレ。

お笑いでも考えてみた

ヒロシで。

  • 「クライアントがトップページの Flash 以外まともに打ち合わせしてくれんとです。」
  • 「上司のアイディアでフレームでデザイン組まされました。」
  • 「『君のリニューアルのおかげで font size="-1" とレイアウト目的の table のないユニバーサルな Web サイトができあがったよ。ありがとう。』自分で録音して聞いてます。」
Tags: 日々 Web

2006-01-20

_ zsh + screen で最後に実行したコマンドを window title に

MM/Memo でハテナオヤの screen ネタがクリップされていたので、実は以前見ていたんだけどもう一度ちゃんと見てみた。

zsh も screen も Emacs もまったくヘビーに使いこなしていないんだけど、タイトルに書いた機能はいいなと思った。普段は window title 出してないから、window が 3つ以上になると何が何やら分からない。出しておけばいいんだけど、window title を手でいちいち設定するのが面倒なので使わないという判断をしていたのだ。

さて。ネタ元はここ。

screen (ari's diary)

まずコピペ。テキストになっちゃってるコントロールコードを修正。(Emacs でコントロールコードを入力するには C-q に続けて何か。)

;&

;;

に直す。あれー動かない?と思ったら .zshrc や .screenrc で $TERM を rxvt にしていた。その記述を外したら動いた。おーこれは便利。

%w | %h

を活かすために screen を使っているときは prompt にカレントディレクトリを出さないことにする。リンク先の .zshrc の先頭の if 直後に

PROMPT='%n@%m%(!.#.$) '

を入れる。いやーいいな、これ。

[2006-12-30 追記] screen の windowlist にだけ hostname 出せないかな - あーありがち (2006-12-30) の設定で window title に hostname も出すようにしてみた。window title があんまり長いと邪魔でしょうがないけど、これくらいならギリギリ我慢できるレベルか。

Tags: Zsh Screen

2007-01-20

_ 正規表現の //、コメントの //

先を越されたがあえて書く - ときどきの雑記帖 リターンズ 2007年1月

せんせい。Ecmascript では // はコメントになります。

NOTE 正規表現リテラルは空にはならない; 空の正規表現リテラルをあらわす代わりに、文字 // は 1 行コメントを開始する。空の正規表現を指定するには、 /(?:)/ を用いる。

オリジナルは PDF なんで日本語訳の方で。

まぁ、だから何って話なんですが、ごくたまに自分が忘れます。あと PHP を書くときに <?php ?> を忘れるとかもよくやるな。動かしてみると全部ブラウザに出てて???ってなる。あれ面倒くさい。

Tags: Ecmascript

2009-01-20

_ OSX の ssh-agent を潰す

09:11:26 wtnabe< あれ。昨日潰した login.keychain が復活してる!
09:14:22 wtnabe< みんなこの keychain 全然疑問ないのかな。すっげー邪魔
なんだけど。
09:19:35 kinneko> も。
09:23:39 wtnabe< keychain の 「login」 はどこまでの範囲なんだろう
09:23:46 wtnabe< まぁ削除してみるか
09:25:51 wtnabe< あーやっぱ他(ブラウザ)のもみんな消えた。
09:26:15 wtnabe< ssh とか terminal 上の操作だけ keychain が出しゃばら
ない設定ってどうやるんだろう。
09:28:48 wtnabe< そして再度「ログインを作ったらファイルが日本語ででき
た。なんでや。
09:32:53 wtnabe< もう一ヶ月くらいこれでイライラしているが全然解決方法
が分からないオレのバカバカバカ
09:35:47 wtnabe< そしてこれだけつぶやいても誰も助けてくれない twitter
のバカバカバカ
09:36:01 wtnabe< まぁ twitter は助けてくれないが
09:46:34 kinneko> @wtnabe SSH_AUTH_SOCKは使えないの?
09:56:53 wtnabe< @kinneko ssh-agent も keychain も無効にしたいんですー
10:07:34 kinneko> @wtnabe 都度パスフレーズを入れたいってことね。
10:07:34 kinneko> @wtnabe それって、unset SSH_AUTH_SOCKだけじゃダメなの?
10:10:00 wtnabe< @kinneko で、できました。。。えー。でもこんなことやっ
たことないのに自宅の Mac はなぜだんまりなんだろう。
10:10:35 beckyco> .@kinneko unset SSH_AUTH_SOCKだけじゃダメダヨ♪
10:10:48 wtnabe< @kinneko .zshrc は共通なんだから、どっかでなんか別な
方法で off にしてるんじゃないかと思うんですが。
10:11:07 wtnabe< @kinneko それはもう分からないということにしてしまうの
がイチバンてことかしら。
10:12:45 wtnabe< というか .zshrc で設定できた方が同じ環境を再現しやす
いからその方がいいんだ。そうだ。
10:13:34 kinneko> @wtnabe 試してみたけど、ちゃんとダイアログじゃなくて、
Enter passphrase for key '/Users/kinneko/.ssh/id_rsa': がコンソールに
出て来たよ。
10:16:34 kinneko> @wtnabe 自宅のほうは、何かファイルが壊れているのかもね。
10:16:35 kinneko> @wtnabe ユーザー新規に作ってやってみても同じなら再イ
ンストールかな。ちゃんと動いたら、設定類を新しいユーザーと比較してみる。
10:19:34 kinneko> @wtnabe まぁ、そんなことはわかってるんだろうけど(^^;。
10:19:34 kinneko> twitterでつぶやくにしても、helpがほしい時は、希望と
現在の症状を明確にしないと、誰も助けられない。
10:20:52 wtnabe< @kinneko mjsk. 自宅でも文句は言ってたはずなんですけど、
なぜかその当時のつぶやきにはそんな記述ないんですよね。
10:21:58 wtnabe< @kinneko もしかすると自宅Macはあらゆるログイン情報を
keychain に残さない漢仕様なのかもしれません。そんな気もしてきました。
10:25:20 wtnabe< ハナからあり得ないと決め込んで可能性を狭めていた自分
の問題だったのかもしれない。やっぱりオレのバカバカバカ。
10:25:34 kinneko> @wtnabe まさか、まぢ独り言モードだったとか? Tw
10:26:14 wtnabe< @kinneko twitter のつぶやきと区別ついてない可能性はあ
りますwww
10:28:35 kinneko> @wtnabe twitterを馬鹿にしてはいけないのだ。けっこう
いろいろ助けられてる。

twitter をバカにはしていないけど、自分が気にかけてるほど周りは自分を気に掛けていない、というのが現実かな。まーだいたいいつもそう。そんなもんです…。ありがとうございます、kinneko さん。

まぁ要するに ssh-agent を無効にしたかったんです。使ってないんでこんな設定があることも知らなかった。

agent を使うのっていっとき流行ったように記憶してるんだけど、なんかメモリ内にやばい情報がずっと居座ってる感じがして気持ち悪くていやなんですよね。ハイバネーションしちゃうとディスクからもその情報が抜けるとか聞いたこともあるし、ControlMaster で session の使い回しをすれば最初の一回だけパスフレーズを入力するだけでオッケーなので、特に agent の必要性も感じないし。

というわけで .zshrc に

unset SSH_AUTH_SOCK

で解決しましたとさ。

21:16:11 wtnabe< うーん。やっぱ自宅 Mac との違いはよく分からん。もう面
倒なので zshrc で行くことにする。

ほんと、以前はどうやって無効にしたんだろ。

Tags: OSX

_ git bundle 初体験

ついでにこっちも twitter のログを貼ってみる。

19:45:30 wtnabe< bundle はそれ自身もまたサブコマンドを取るのか
20:05:52 wtnabe< 分散バージョン管理システムの bundle ファイルってどん
な拡張子にするもんなんだろう?
21:43:34 wtnabe< git bundle create したものを展開するのは git bundle
unbundle ではなく git pull か?
21:52:03 wtnabe< git clone でもなんでもいいのか。git pull なら事前に
git init が必要だし、clone なら何もしなくていい。パスの指定にだけ気を
つければ(たぶん相対パスはNG)

man によるとこのように書かれていて、

NAME
      git-bundle - Move objects and refs by archive

SYNOPSIS
          git bundle create <file> <git-rev-list args>
          git bundle verify <file>
          git bundle list-heads <file> [refname...]
          git bundle unbundle <file> [refname...]

すっかり bundle create で作ったファイルは unbundle するものと思っていたんだけど、どうも違ったらしいというか、自分の場合は以下の方法で目的を達成できた。

$ git bundle create /PATH/TO/BUNDLE_FILE HEAD

(bundleファイルを持ち運ぶ)

git リポジトリ内で

$ git pull /PATH/TO/BUNDLE_FILE

あるいはまっさらのディレクトリで

$ git clone /PATH/TO/BUNDLE_FILE

こんな感じで使うものなのかな?

※ pull がうまくいかないときは checkout も試してみるといいよ!

22日の twitter log より。

あと一気に git pull できなくても fetch すると FETCH_HEAD に保存されるっぽいので、これをもとに checkout -f や merge なんかがじっくり作業できるのはいいなと思った。

Tags: Git

2010-01-20

_ Godで簡単daemonize

今さらながら

なぜ daemontools を使うのか - kazuhoのメモ置き場

これを読んで、

通常のプログラムをそのままデーモン化できるから

という記述にうんうんと頷いていた。*1

今回は、daemontools もいいかもしれないけど God を使って daemon 作ろうぜって話。これは monit には真似できないよ。

cf. M/Monit | Wiki

Godでオレオレデーモンを作る

例えば以前作った Rswatch っていうログを監視するツールなんかも、一応 daemon のように動くけど、これ落ちたらどうすんのとか、システム起動時に自動的に起きるようにするのどうしよう、とかいろいろ管理しにくくて仕方なかった。デーモンを作ることは、実は 1)目的の動作を作り込むこと、2)デーモン化する処理を作り込むこと、の二つに分けられる。そう、2 は目的じゃない。期待する動作ではあるけれど。

God を使えば 2 の部分はすべて God 任せにできる。

また自分の中では daemon と言うとサーバとかこういう監視ツールをすぐに思い浮かべちゃうんだけど、別にそんな役に立つものばかりが daemon というわけじゃない。ここでは

とりあえず終了しないもの

は全部 daemon と呼ぶことにする。例えば twitter の bot なんかは daemon である。

Godを使った基本的なdaemon化の流れ

実は Ruby だけの話であれば別に God を使わなくても Process.daemon でも daemons でもいいのだが、これは後述することにして God の話を進める。

スクリプトを用意

まずは終了しないプログラムを作る。こんなものでもいい。

#! /usr/bin/env ruby

require 'logger'
 
i = 0
l = Logger.new( File.dirname( __FILE__ ) + '/counter.log' )
loop do
  l.info( i )
  i += 1
  sleep 1
end

これを例えば counter.rb という名前で用意する。これを実行すると当然1秒ごとに延々と数字を数え上げていく動きをする。

tail -f counter.log

で、その様子を確認できる。わざわざ絶対パスにしているのは、

daemon 化したときにカレントディレクトリが変わってしまうから。

これはもうそういうものなので肝に命じておく。

godファイルを用意

同じディレクトリに以下の内容で God の設定ファイルを作る。

God.watch do |w|
  w.name = 'counter'
  w.interval = 5.seconds
  w.start = "ruby #{File.dirname( __FILE__ ) + '/counter.rb'}"
  w.behavior( :clean_pid_file )

  w.start_if do |start|
    start.condition( :process_running ) do |c|
      c.running = false
    end
  end
end

これを counter.god のような名前で保存する。スクリプトのパスを絶対パスにしているのはさっきと同じ理由。あるいは実行するプラグラムを PATH の通ったところに置けばもう少し話は簡単。

xig_installer を作ったのは実はこのためである。

実行ファイルの場所が変わってしまったら God の設定ファイルをいちいち書き換えなくてはならない。これは面倒くさいし、まず忘れる。

※ ここでは ruby に PATH が通っていることを期待した書き方になっているが、FreeBSD + ports のようにデフォルトの PATH が /usr/bin で追加するプログラムがすべて /usr/local/bin に入る環境は、この部分もフルパスにしておくべき。

god 経由で起こす

まず -D を付けて起こす。

god -D -c counter.god

するとスクリプトを daemon 化する様子、状態を監視している様子がそのままターミナルに表示される。正常に daemon 化できて監視できていれば ^C で終了する。

このとき、daemon 化したスクリプトはそのまま動き続ける

が、慌てず

god -c counter.god

と打って god プロセスの daemon 化を行う。すると

今動いているプロセスをそのまま監視対象にできる

ので、この状態で

god stop counter

と打てば止められる。あるいは

god terminate

とすれば丸ごと全部終了できる。

どうだろう。

単に終了しないプログラムを作っただけなのに God を噛ませることでちゃんと daemon 化できている。*2

また、ここまでの例はすべて Ruby で書いているが、daemon 化したいプログラムは何で書かれていても関係ない。Godにプロセスの起動順序を教えたい などで触れている tiarra は Perl 製だし、なんでもよい。

おまけ - Rubyでdaemonを作って管理するその他の方法

死活監視やリソース消費を監視して自動的に再起動、などの機能が要らない場合は以下のリンク先も参考になる。

ただしこれらの情報だけでは作った daemon をコントロールすることができない。Rubyスクリプト限定でいいなら以下を使うと God より楽に管理できる。

これを使えば基本的には

Daemons.run(デーモン化したいスクリプトのファイル名)

だけで済む。

ま、もちろん監視はできないけど。

*1 本当に理解できているか自信がなかったのでブログのコメントでその確認もさせてもらった

*2 細かい daemon の定義は調べるといろいろ出てくるよ!


2011-01-20

_ Chromeが問答無用で閉じちゃうのがちょっと困る

Firefox から Chrome に移行してほとんどの機能は標準のものや拡張でどうにかなってるんだけど、一つだけ解決してなかった要望が

複数のタブ、ウィンドウを開いてる場合だけ終了時に確認を入れてほしい

だった。どうやって探したらいいかもよく分かってなかったんだけど、見つけた。

Confirm Close - Google Chrome 拡張機能ギャラリー

入れた。

快適。

Tags: Web Google

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 から見える変数も減っていない。何も解決できていない。