小物エンジニアの会でオブザーバーパターンのアンチパターンについて発表してきた


小物エンジニア年収780万円以下だそうです
小物エンジニアの会 : ATND http://atnd.org/events/41091

発表資料は面倒くさかったのでGistです

hanabi.md https://gist.github.com/mizchi/6081622

西新宿のありふれた公園で酒飲みながら屋外発表会、破滅的でした

JavaScriptで型が書けるDSLを提供するdeftypes.js作った


こじらせJavaScriptシリーズです。
mizchi/deftypes.js https://github.com/mizchi/deftypes.js

主にcoffee-script用のDSLです。以下すべてcoffee。

ブラウザ

<script src="https://raw.github.com/mizchi/deftypes.js/master/deftypes.js"></script>

Deftypes(); //provide DSL

Node

npm install deftypes

概要

型が書けます。残念ながら動的チェックです。

Point = {x: Number, y: Number}
p1 = def Point, {x:1, y:2} #=> {x: 1, y:2}
p2 = def Point, {x:1, z:2} #=> type error

defとTがDSLです。オプションで何もせずにインスタンスを返却するだけするモードもあります。これによってパフォーマンスを落とすことなく、型を明示的に宣言しながら開発することができます。(その際のオーバーヘッドは型情報の宣言のみで、ほぼ無視出来るでしょう)

Nullable型

NullableNumber = {n: T.Nullable(Number)}
p1 = def NullableNumber, n:1
p2 = def NullableNumber, n:null

配列

number_list = def [Number], [1,2,3]

関数型

f1 = def T.Func([Number, Number], String), (m, n) -> "#{m}, #{n}"
f1(1,2) #=> "1, 2"
f1("",2) #=> argument error

引数と返り値の型を動的にチェックします。違反が検出されたら例外をthrowします。


型宣言されたインスタンスを変更するとき、専用の高階関数の中で副作用をだすようにすれば、高階関数を抜けた時にも型チェックをすることができます。

p = def Point, {x:1, y:2}
def Point, p, ->
  @x = 3

# Type Error
def Point, p, -> @y = "not number"

やや面倒ですが、副作用を出すという危険な行為は面倒臭くしておきたいのです。
これを無視してブロック外で行われた変更は検出しません。実装上は検出できるけど、このライブラリ専用の挙動が増えすぎるのでまだ避けてます。


それ以上の詳しくはREADMEとテストコードをみてください。


用途

静的解析ではないので、テストコードを書いたりしてカバレッジあげないとあまり意味がありません。むしろテストコードでの型チェックに使うといいかもしれません。
型をコード中に定義して文芸的プログラミングな文脈で可読性をあげる目的もあります。これは個人的な目的です。

TODO

typescriptのd.tsから型情報を読み込めるようにする
実装例としてテトリスか何かをつくる
可能ならば型推論する(難度が高い…)

1つの流儀を持つこと

流儀を知らないということは、何者にも縛られていない、ということではない。自分の癖に振り回されていることに、無自覚なだけだ。


ってのは、中学時代の部活の恩師の受け売りなんだけど、大人になるにつれ、特にインターネットを眺めるにつれ、無自覚に自分の癖に振り回されている人を見る機会が増えている気がする。


インターネットには反知性主義・反権威主義の皮を被った「怠惰の言い訳」があまりにも多い。
わかり易い例として、2chの哲学系のまとめを見るといいと思う。必ず導入かオチにキャッチーでわかりやすい反知性主義の言い訳があるはずだ。


それはまとめ人の程度を示しているだけとも言えるが、傾向として2ch反知性主義が支配している場であると思う。2chは嫌いではないけど相手の弁をそれによって封殺している流れをみると、僕はイライラする。で、はてブにもそういうのが増えてきた。


何かの視点を獲得することは、自分自身を捉えていた檻を自覚するようになることだ。檻を破壊するも、あるいは居心地の良い檻の中の生活を志向するにも、必ずその檻を自覚することからはじまる。


反知性主義の弁は、ほとんどの人の耳に心地よく、また伝搬しやすい。それを理解するのに必要なものは、なにもないからだ。なにも知らないでいいことの根拠になる。


何かに熱くなることはかっこわるい、みたいな風潮は、真摯に向き合っている人に対して失礼だと思う。専門性の獲得はそこからは生まれない。僕は誰もが何かに精通していて、お互いに何らかの価値を交換しあえたら楽しいなと思っているし、そうであってほしい。

プログラミングはそれ自体が目的であっていい

これ読んで思ったこと。

プログラミングを勉強したい人が勉強する前にすべきこと - もとまか日記 http://d.hatena.ne.jp/moto_maka/20130512/1368308092


僕がプログラミングをはじめたとき、何を思ってプログラミングをはじめたか思い出してみようとしたけど、よく思い出せなかった。
ただ漠然と感じていたのは、プログラミングは個人が現実的にこの世界に直接手を加えることができる手段の1つであり、それをやらないのは勿体無い、といったことだったと思う。たぶん。

というわけで、最初にやったのはFirefoxのユーザースクリプトを書くことだったし、それはそれでよい経験だった。なんとなくゲームとかウェブアプリとか作りてーなー、と思って色んなライブラリを動かすだけ動かして満足した。プログラミング覚えて初めて最初の一年で10以上の言語のHelloWorldだけやったと思う。その結果Unixの環境構築がうまくなった。

その後はひたすらいろんな言語のウェブフレームワークを触り、PythonとMongoDBで遊んでいた。グラフィック関係もやりたくなったのでJavaScriptのHTML5Canvasで迷路を書いて、A*のアルゴリズムで最短経路を解かせたりしていた。


自分が地力でそこに行き着くまでに覚えた環境構築、ライブラリごとの思想、言語の触り心地、出来上がったアプリの感触、そこに無駄だったものは何一つ無い。
半年でアプリが作れる!という謳い文句を僕は信じていない。そこに至る全てをオミットしているからだ。ちょっとパラダイムが変わると簡単にハマってしまうからだ。現実のアプリを作るレベルで、最短経路の知識で済むこと絶対に無い。

大事なのは、いくつ地雷を踏んだか、だ。地雷を踏んだ数だけ強く慣れる。真に必要なのは、独力での問題解決能力。Python2系でsjisのHTMLをlxmlでスクレーピングすると、地雷を7つぐらい同時に踏めるからおすすめだ。


話題になった技術は概要を読むだけでなく、自分の手で動かすことが大事だと思っている。サンプルを少しづつ変更して、この技術は、何を許して何を許さないかを知ること。それが欠けたプログラミング技術は、ネタなしの寿司である。

プラグマティズムと理想

これは業務としてプログラミングをするようになって気づいたんだけど、「動けばいい」というだけの指針で設計されたコードは、ほとんどにおいて糞コードである。

たとえばリファクターを嫌う創業者が、動けばいいというマインドを共有した技術者だけを集めて書かせたコードは、往々にして破綻する。(この業界で一番よくあるパターンだ)
「動けばいい」はプロジェクト初動においてはものすごいベロシティを発揮するが、それを継続するのは至難の技だ。そしてそれを難しいと伝えることは難しい。人は経験からしか学べず、しかもより直近の経験から学ぶから、直近の見た目上のベロシティにバイアスが引っ張られる。コードが書けない人はなおさらだ。

このようなことを起こさないために、そこで必要になるのはある種の言語マニアのような人の存在だと思っている。数万行のコードベース、大規模なアーキテクチャを成立させるためのスキルは、偏執的なデザインパターンや設計に対する執着、言語仕様に対する深い理解から生まれると僕は思っている。(さらに言うと仕様理解度もだが、ここでは割愛する


モデルとビューの分離の指針、デザインパターンの準拠、インスタンスを握るスコープの最小化や、組み込みメソッドによるコードの単純化、そういうのにこだわりを持つ人のレビューがあって、はじめてまともなコードが成立する。継承地獄やシングルトンという名のグローバル変数が検知されず、使用しているライブラリのデザインパターンを無知ゆえに独自の解釈でねじ曲げた場合、糞コード一直線だろう。


僕がよく個人的によくやるリファクタリングは、糞コードに至るプログラムのフローだけ整えておいて、どうしようもなく出来上がった糞コードを一箇所に押し込める。「副作用が0」もしくは「副作用しか無い」ようなメソッドに抽出しておく。その際はメソッド名で、副作用があるかないかわかりやすくしておく。
ここのリファクタリングは、思いついたらやる。だいたい他の箇所のコード書いてるとこう書けばよかったんだって気づく。

言語にしか興味が無い人

たとえば、Rubyist達はRubyで書くこと自体を目的にしているケースをよくみる。一般的に、コミュニティが小さい言語ほどコードの質は高い。美しいコードに囲まれて生活するということは、それだけが彼らの転職目的になりえるわけだ(Rubyを書きたいから転職、もこの業界でよくみるものの1つだ。

プログラミング自体を目的にした人達は、基本的にHaskellLisp関数型言語に手を出す印象がある。それはもちろん小さいコミュニティで、コードの品質が高く、言語そのものに対する研究に興味がむくからだろう。

僕もまあそれなりに手を出しているのだけど、他の人も抑えるべきだと思った概念は、次のものだ。

それほど敷居が高くないのを選んだので(Haskellの非同期IOはちょっときついが)、興味がある人は調べるといいと思う。

最後に

この記事は昼間からLeague of Legends を飲酒プレーしながらはてブ眺めてたら意識が高まりウッってなったので書いた

最近買った本

ニンジャスレイヤー ネオサイタマ炎上 (1)

ニンジャスレイヤー ネオサイタマ炎上 (1)

七王国の玉座〔改訂新版〕 (上) (氷と炎の歌1)

七王国の玉座〔改訂新版〕 (上) (氷と炎の歌1)

機龍警察(ハヤカワ文庫JA)

機龍警察(ハヤカワ文庫JA)

言語実装パターン ―コンパイラ技術によるテキスト処理から言語実装まで

言語実装パターン ―コンパイラ技術によるテキスト処理から言語実装まで

型システム入門 −プログラミング言語と型の理論−

型システム入門 −プログラミング言語と型の理論−

  • 作者: Benjamin C. Pierce,住井英二郎,遠藤侑介,酒井政裕,今井敬吾,黒木裕介,今井宜洋,才川隆文,今井健男
  • 出版社/メーカー: オーム社
  • 発売日: 2013/03/26
  • メディア: 単行本(ソフトカバー)
  • クリック: 68回
  • この商品を含むブログ (11件) を見る
Land of Lisp

Land of Lisp

JavaScriptでDIできる Injector.js つくった

仕事でRobotlegsというAS3のフレームワークを使っているのだけど、DI機構がかっこよかったので、Injectorだけ真似て作ってみた。

mizchi/injector.js · GitHub https://github.com/mizchi/injector.js

Robotlegs AS3 Micro-Architecture - Home http://www.robotlegs.org/

使い方

ConstructorClass.inject に {key:InjectedClass} で実体化するインスタンス名と実体化するクラスを登録する。
CoffeeScriptで違和感無いような記法でチューニングしてある。

class UserModel

class X_View
  Injector.register(@)
  @inject:
    model: UserModel

Injector.mapSingleton UserModel, new UserModel
x = new X_View
console.log x.model


JSだとこうなる

function UserModel(){};

function X_View(){};
X_View.inject = {
  model:UserModel
}
Injector.register(X_View);

Injector.mapSingleton(UserModel, new UserModel);
var x = new X_View;
console.log(x.model);

JSだとあんまりかっこよくないですね…


子のInjectorも作れる

childInjector = new Injector()

他、明示的に呼ぶ必要があるが、Injector.ensureProperties(hoge)を使えば、hogeHogeプロトタイプに登録されたすべてのinject対象をみたしていることを確認できる(そうでない場合は例外を吐く)

詳細はREADMEにて。bower にも登録したので bower install injectorでもいい。node.jsでもnpm installすれば使えるんじゃないかな。(使いたいかはともかく)

仕組み

Injector.mapSingletonでは、Injector.register(Hoge) でHogeクラスのprototypeに登録している。
Injector.mapValueでは、インスタンスごとにgetterで返すクラスをシングルトン化して、実体を this._...に保存している。

現時点での欠点として、mapValueはそのプロパティを最初に参照した時の遅延評価になってしまう。インスタンスをInjectorに通知したり、Injectされる専用のコンストラクタ処理を持つクラスを用意したくなかったので、このような形になった。

思想

mapValueはどちらかというとオマケで、mapSingletonが主役。
DIを使ってUIを構築してきた経験上、Viewはリスト構造以外ほとんどシングルトンであり、DIがない環境だとシングルトンやグローバル変数で取得せざるを得なくなり、どこから取得されているかわからなくなる。これはコードをスパゲティ化させる要因になりうる。

そのクラス内の名前空間において、injectされるインスタンスその場所を明示的に設定すると、見通しがよくなる。
だいたいregisterするのはそのクラスの宣言の中だが、map するのはメインの処理がはじまって以降なので、動的にinjectすることはあまり想定していない。そのようなケースは既に破綻している。

酷使するとメモリが若干程度は漏れそうな気がするが、パフォーマンスセンシティブな箇所よりはアーキテクチャを破綻させないようピンポイントで使うといいと思う。サンプルにUserModelとか書いているのは、もっともシングルトン化されそうなクラスだから。

いろいろ粗いので PullRequestください。以上。

Web系新卒っていうかゲーム開発者一年目が去年読んだ技術書 & ライブラリ

カタ氏(@hotchemi)が意識高い記事書いてたので、自分もまとめてみる。
文系学部生がSIerに入社してから読んだ本メモ - ギークに憧れて http://hotchemi.hateblo.jp/entry/2013/04/01/000844

自分Web系っていうかHTML5+Unity+AS3 のゲームガッツリ系+Webもやるって感じなので、最近の自己認識としてWebっていうよりはゲームプログラマな気がしている。
JSが多いのはHTML5ゲームの技術調査とかしてたからです。

書籍

7つの言語 7つの世界

7つの言語 7つの世界

一部情報が古いが、ClojureやIoについて書かれた貴重な本。自分が使ってる言語のパラダイムプログラミング言語全体で言えばほんの一部にすぎないということを、身を持って感じることができ、言語パラダイムの文脈で相対的に考えられるようになる。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

たぶんいちばんやさしいHaskell入門本。ちゃんとまだ読み切れていない。
正確には、会社で最初のプロジェクトでHaskellを部分的に使ったため、これの原著の方を必死こいて読んでた。
Haskellをやると副作用についての考え方が変わる。今までの触ってきた言語がいかに危険なことをやれていたかわかって、胃が痛くなる。

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

鉄板。どの章を読んでも心を打ち、そして今日書いた糞コードを思い出して胃が痛くなりますね?(胃が痛くならない奴は鉄人か自省が足りないかどっちか)
胃が痛くならないようになりたい。
とくにコメントについての章は賛否あるが一読して自分の中で考える余地を持っておくことを薦める。

入門Git

入門Git

Git力はプログラマとしてのコミュニケーション力である。エンジニアに限っては、口頭の連絡よりもよりコミットメッセージの方が遥かに意味がある。コミットメッセージはプログラマ文学。

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

中規模以上のJS書く人は読まないとだめ。それぐらい大事な本。内容については一部賛否両論があるが、JSerとして他のJSerに一番読んで欲しいのは末尾の Bad Parts の章。

ハイパフォーマンスJavaScript

ハイパフォーマンスJavaScript

主にJavaScriptのDOMのチューニングについて考えるの役だった。HTML5ゲーム開発者は読むといいと思う。便利な黒魔術も多いので心してかかるべし。

ステートフルJavaScript ―MVCアーキテクチャに基づくWebアプリケーションの状態管理

ステートフルJavaScript ―MVCアーキテクチャに基づくWebアプリケーションの状態管理

MVC構成について考える本。この本の著者がSpine.jsの作者。

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptのTIPSみたいに適当に欲しい機能を目次から引っ張るといいと思う。

Unityもやってたけど、Unityっていうよりかは既に組み上げられた巨大なC#ライブラリをがっつり書いてた。C#自体はJava+αのノリでなんとなく書ける。Javaのダサい面を拡張しまくって解決してて、良い言語だとおもう。

ActionScript Developer's Guide to Robotlegs: Building Flexible Rich Internet Applications

ActionScript Developer's Guide to Robotlegs: Building Flexible Rich Internet Applications

最近の仕事で使ってるAS3のライブラリ。妙に格好いいDCI機構がある。他のMVCライブラリも参考にしたらいいと思うんだけど、AS3自体が斜陽なので陽が当たらない…

ルールズ・オブ・プレイ(上) ゲームデザインの基礎

ルールズ・オブ・プレイ(上) ゲームデザインの基礎

遊びとは何か。ゲームデザインとは何か。その定義をアカデミックな資料を引用しつつも、ゲームについて豊富な例を引きながら解説する。
ゲームのコアのメカニクスメカニクスの上に生まれるゲーム性、そしてユーザーの背後にある文化をからめて考察する章がとてもよかった。下巻が未翻訳で出そうにないのが辛い。

読んだコード

あくまで「使った」、ではなく、「読んだ」。でもヘヴィに使うライブラリを必然的に読んでた感じ。

wise9/enchant.js · GitHub https://github.com/wise9/enchant.js
HTML5ゲームフレームワーク。イベントディスパッチやアセットのロード周りは参考にさせてもらった。

documentcloud/backbone · GitHub https://github.com/documentcloud/backbone
JSのMVCフレームワーク。オブザーバーの実装とViewのイベントバインディングが渋い。


documentcloud/underscore · GitHub https://github.com/documentcloud/underscore
関数型的な関数群。関数型言語を知ってるとすごい楽しく読める。最近だったら軽量版のlodash読むほうがいいらしい。


jquery/jquery · GitHub https://github.com/jquery/jquery
ふざけんなと思いながらJSの黒歴史を知ることになる。正直キレそうになるコードが多々あるが、歴史の重みを感じるとしょうがなくも感じる。綺麗な実装読みたけりゃzeptoだったのでは、とr7kamura に言われた。そうかも。


fastladder/fastladder · GitHub https://github.com/fastladder/fastladder
Livedoor ReaderOSS実装。絶賛リファクタリング中。polyfillが大量でmalaさんのテクニックと思考を追う感じになってる。


jashkenas/coffee-script · GitHub https://github.com/jashkenas/coffee-script
ご存知CoffeeScript。パーサジェネレータからAST、構文木から意味解析でノード実装とクロージャ判定の実装までだいたい読みきった。辛いのでもっとモダンな実装(CoffeeScriptRedux)読むといいとおもう。src/rewriter.coffeeの関数適用パターンマッチに暗黒面を感じた。


たぶん自分は Jeremy Ashkenas 信者なんじゃないかなっていうのは感じる。(coffee, underscore, backbone)