Bought MacBook Pro 15 (2017 mid)

MacBook Pro 15 (2017mid)を6月に買った。Kaby Lake積んでるやつね。 macOSそのものはそこまでこだわりはなかった。けれどもLinux Desktopをlaptop PCで使う気にはなれなかったのと、物理4コアなノートPCが欲しかったのと、そろそろ2012mid/IvyBridgeなMacBook Airを更新する目的で新しいMacが一台欲しかったので。Winは何年か前にXPS13買って使ってたので、ちょっとMacに戻ることにした。

カスタマイズはほとんどしてないし、CPUも増してない。

キーボードとかtouchbarとか

touchbar無しを選ぶと旧筐体になってしまうので已む無くtouchbar付きを選択。 touchbarにせよキーボードにせよ、みんな使いにくい使いにくいと言うけど、言うほど使いにくいかな? どちらも噂ほど酷いもんでもないかなーと。

キーボードはもともと私はキーストローク浅めのものが好きなんで、そこまで苦労しなかった。とはいえ今までと同じように打ってると不満はたまる。ここは打ち方変えないとダメだろう。キートップ安定してるのとストローク含めて、MacBookみたいなサイズ感で鞄から取り出して使うには向いてるとは思う。が、Pro 15だと不満になりやすいとも思う。前の世代の筐体に慣れてる人は特に。

touchbarは、確かにエスケープキーの感覚は狂うけど、それ以外はそんなんでもなく。慣れれば音量調節とかは便利かな。

あと、そもそもガチでコード書くときは自分は外付けのキーボードを繋ぐんで、どちらもそんなに困らなかった。

touchbarそのものに対しては、便利といえば便利だけど、ロジックボードの発熱部品のほぼ真上に位置しているのと、そもそもとして故障しうる部品が増えるのは好きじゃないので、出来ればtouchbar無しモデルがあればそっちを買うとは思う。ただ、よく聞くような「このtouchbarというUIがクソだから買わない」みたいな理由ではないかな。

USB type C

Amazonでtype Aメス - type Cオスのコネクタをいくつか眺めてもどれもレビューがイマイチだったんで、Appleの純正アダプタを買うことに。今の所これ由来の不具合はない。USB type-Aな周辺機器は、このアダプタにUSBハブを経由して繋いでる。

電源アダプタもtype Cなのは、ちょっと不便だなーと。mag safeの時はうっかりケーブルに足を引っ掛けてもちゃんと抜けてくれる安心感があったけど、type Cだとそれはないので、間違えて引っ掛けてコネクタを破損してしまわないか心配だったりする。左右両方に電源ケーブルを刺せるのは便利なんだけど、ケーブルはmag safeにして欲しかったなあ。

液晶とかスピーカーとか

いいんじゃない

Benchmark

  • とりあえず参考までに
  • なお、macOS Sierra 10.12.6
  • rlsとfuture-rsは以下の条件でビルド
    • rustc 1.21.0-nightly (215e0b10e 2017-08-08)
    • cargo 0.22.0-nightly (305bc25d5 2017-07-28)
command time
future-rs, rev 3c067a7 cargo build 2.68 secs
rls, rev ecdbf0c cargo build 98.77 secs
servo, rev 8074c6a mach build –dev 1105.77 secs

総評

一昔前の14 inchノートPCのサイズ感とMacBook Pro 13の重量感で物理4コア15 inchノートが展開できるのは便利。電源確保もできれば憂いなくだいたいのソフトウェアはビルドできる。電源アダプタ入れても2.2kg弱だから、リュックサックに背負う分にはそんなに苦労しない。出先で確実に作業するのであれば普通に持ち運べる感じ。本体のキーボードも出先用と割り切れば十分。

ただ値段も結構いい値段するので、そこが結構ネックだったりする(それでも13 inch touchbarモデルを特盛にした場合と大差ないけど)。これで20万円代前半なら最高なんだけど…… 値段割り切れればいい買い物でしたよ。

/<role>/<domain>/DomainNameRoleみたいなディレクトリ階層よりも/<domain>/<role>/DomainNameRoleみたいな階層の方が素直だと思う

こんなの探せば10年とか20年前にも似た議論があって結論出てそうだし、ドメイン駆動設計系の人が実践論として言ってそうなものだけど。

アプリケーションフレームワークとかボイラープレートみたいなものをいくつか眺めていると、/Controller/SignIn/SignControllerみたいなディレクトリの組み方を薦めてるものが結構あるけれど、これは素直じゃないなと思った。

だいたいこんな階層になるやつ。

  • /
    • Action/
      • Signin/
      • Report/
      • Editor/
    • View/
      • Signin/
      • Report/
      • Editor/
    • Repository/
      • Signin/
      • Report/
      • Editor/
    • UseCase/
      • Signin/
      • Report/
      • Editor/

何が素直ではないと思ったかというと、

  1. 具体的な問題領域よりも先に教条主義的なコードの役割分担が優先されている
    • 問題領域に応じてHelper増えたりとか色々あるのが本当だよね
    • 例えばバージョン情報みたいな画面だと View だけに色々ベタに書いていいはずで(バージョン情報の他問題領域から再利用とか、普通そんなに起きねえよ)
  2. 結果, 同一の問題領域のコードなのに木構造的に再従兄弟みたいな位置にいるコードが多くて見通しが悪い
    • 凝集度悪くね?
  3. 問題領域に応じたコードの組み方がやりにくい
    • 例えば「ReportドメインのViewはReactじゃなくてVue使いたい!(そちらの方が技術的に向いている)」みたいな需要に合わない。この構成だと、例えばView/の下の一箇所を変えると、隣接するディレクトリに配置されたコード全てを同じように変えたくなってしまう。それが人情ってもんです。

な辺り。

あとで移行とかリファクタをしようと思った場合に一番面倒なのは 3 だし、普段コードをいじるときは 2 がストレスになるけど、何れにしても「問題領域に応じて最適な道具を用いる」という思想とは噛み合わせが悪いし、私はそういう思想なので、息苦しさとかデメリットばかりなように思う。なので、自分がゼロから組む場合はもっぱら:

  • /
    • Signin/
      • Action/
      • View/
      • Repository/
      • UseCase/
    • Report/
      • Action/
      • View/
      • Repository/
      • UseCase/
    • Editor/
      • Action/
      • View/
      • Repository/
      • UseCase/
      • Helper/

みたいに, 問題領域の方を階層の上に置くようになった。 こっちの方が問題に合わせてコードを書く、という場合は素直だと思う。

/<コードの役割>/<問題領域>/問題領域_コードの役割.拡張子 みたいなディレクトリ構成を採用してるフレームワークは、そのフレームワークが想定する・楽にできる問題領域が1つ〜2つ程度なんじゃないか、それ以上を単一のアプリケーションに入れ込むことを想定してないんじゃないかと思うし、用途としてはそんなに向かないだろう。

だからと言って「マイクロサービス最高!時代はマイクロサービス!マイクロサービスしない奴は何をやってもダメ!」とか言うつもりはないんだけど、そこらへんの射程の距離感は常に意識しておくべきで、それを忘れるとコードが無秩序に増え続けるのをウッカリ見過ごしてしまいそう。

rustcを通らないコードは間違っている

Rustを書いていると、慣れるまではrustcに頻繁に怒られる。慣れても結構怒られる。とにかくrustcに怒られる。きっと貴方はこう思うだろう、「Rustはなんて煩い言語なんだ!俺の愛する****(好きな言語の名前を入れてください)ならばこんなことはないのに!」

このように「rustcが煩くて俺のコードが通らない」場合、とりあえず自分のコードが間違っていると疑って問題はない。え、「俺のコードは正しい」? 違う違う、コードのロジックの話じゃない。「そのコードがRust wayではない」という点で「間違っている」。microなスタイルからmacroな設計まで、ありとあらゆる点でRust的なコードであることを暗黙的ではあるが極めて強く要求する。それがRustというプログラミング言語だ。時たまrustcが間違っていることもあるんだけど、体感値として97%はrustcの方が正しいと言っていい。

なぜこのように「不自由な」言語なのか? それはRustは「人間が考えなくても静的に解析できる情報を増やせば、コンパイルの時点でリソースの取り扱いに関するバグを減らせる」という世界観で構築されているからだ。それを実現する為に「言語仕様としてセマンティクスを強く定義し、rustcでそれを機械的に徹底検証する」というモデルを提供している。

こういう世界観で構築されているので、論理的に検証できない・すなわちコード内に自明ではない整合性はRustにおいては、しばしばrustcに禁止させている。パワーバランス的には人間よりもrustcの方が強い。コンパイルの通らないコードはそもそも動かないからだ。セマンティクスと相俟って人間はrustcが解釈できるようなコードを書く必要がある。GoとかTypeScriptよりは間違いなく圧が強い。見返りに、人間はRustの世界観を受け取る。Rustはコンパイルさえ通れば、(後述する例外はあるが)書かれたコードの通りに動く。書いたコードがバグっていればバグ通りに動く。 Noneunwrap()すればそこでクラッシュする。 { ... }でスコープを縮めてやればlockは縮めた分だけすぐに解放される。それがRustである。「〜っぽいコードを書こう」なんて、ゆるふわは無い。勧められるままに書かねば何も動かないか無駄に歪なコードが残るだけだ。

このように世界観の主張が強いので他言語のコードを安直に置き換えても上手く行くとは限らない。moveで済む場合はborrowせずmoveせよ、goroutineみたいにスレッドをたくさん建てずアクター的にせよ(これはownership制約と同時にカーネルスレッド使ってるのが理由だったりもするけど)、下手に高次の言語からportするよりも、スレッドも何も使ってないCやJavaScriptからportの方が簡単かもね。とにかくRustの世界に合わせてコードと設計を変えなければならない。さすればrustcはコンパイルを通してくれる。

この思想故、Rustは言語機能こそ多いが局所局所で取れるmicroなパターンは極端に多くない。syntax的には組み合わせられても、micro/macroでのownershipやlifetimeによって組めないパターンが幾つも現れる。

もちろんそんな理想論ばかりが通ることはない。C/C++の資産との接続、明らかに安全かつ性能のためのdirty hack。そんな時はコードをunsafeに括り出せばよい。ただし全てunsafeにしてはいけない。unsafe由来のコードはRustの世界を容易に侵食し、コンパイルが通ったコードがいきなりセグフォで落ちるようになりかねない。なので、必要最低限の分だけ括り出さねばrustcの加護は得られない。このため、FFIを用いるbinding crateは***-sysという薄いFFIするだけのwrapperと、それの上にRustの殻をかぶせたAPIの二段構成を取ることになる。 いくらrustcが全てを視てくれると言っても、そのために全ての変数の型やlifetimeを明記するのは怠い。故に推論による省略が出来る。

rustcに無制限の自由を差し出す代わりに、偉大なるrustcの監視の目を用いてコードの穴は塞がれる。代償とした自由は大きくも見えるが、現実的に取り得るコードのパターンに於いては概ねプログラマ側に自由があるので問題はない。発想が少々oxydizeされるだけだ。プログラマはロジックを書くのに専念すればよい。IDEに一定範囲の自由を売る代わりに、IDEによってコードやリポジトリに対する人間の認知力を拡張するのと発想は同じ。ScalaとかKotlinとかJavaとかC#とか、あの辺りの作法と大差はない。問題のレイヤーを低次に下げた結果、機械に売り渡す自由は増えたが、多くはレイヤー固有の事情なので問題にはならない。

(とはいえ今のRustはIDE支援が半端で色々片手落ちになってるので、Rust Projectの2017年のRoadmapに「IDEを頑張る」って入ってるんだけど)

言語に合わせて思考と設計を変える。今までの固定観念を捨ててRustに合わせて再構築し直す。これがRustでコードを書くということだ。

rust-bindgenのupstreamが変わった

cargo:bindgenのupstreamがYamakaky/rust-bindgenからservo/rust-bindgenに変わった。変わった結果どうなったかというと、C++のヘッダのパース機能が大幅に改善したりする。

rust-bindgenを知らなかった人に簡単に解説しておくと、clangを使ってC/C++のヘッダをパースして、それを元にRustのC FFI binding用途のglue codeを生成するcrateのこと。

元々rust-bindgenはRust ProjectではなくJyun-Yan Youが始めたらしい。らしいというのは「git logを辿った限りだとそうなっている」以上のことを言えないから。その後、メンテナー間での移譲があったのかどうかはよくわからないが、2015年末の時点ではYamakaky/rust-bindgenがupstreamとなっていた記憶がある。自信ないけど。

Mozillastylo(Quantum CSS)をやる関係でC++で書かれたGeckoとのglue codeを作る必要が出て、2015年の後半ぐらいからservo/rust-bindgenとしてforkしてMozillaのpaid staffが用が足りるようになるまでコードを書いていた(今も続いている)。元々のbindgenはC++サポートはそんなに強く無かったと記憶しているけど、Mozilla側で手を突っ込みまくった結果として改善され、たとえばleveldbのC++ヘッダが丸々パース可能だったりする(実体験)。

で、merge into upstream! · Issue #21 · servo/rust-bindgenというissueが立っていて、色々あったんだけど、最終的にservo側がupstreamを引き継ぐことになった。

RFC 1774で2017年のターゲットの一つにC/C++との相互運用を挙げているし、Servoがupstreamを引き継ぐのは間違っていないのではないかな。RFCを考えるとrust-lang-nurseryが引き継ぐのが一番いいけれども、Rust Project最大のパトロンであるMozillaの一門であるServo Projectの下に置いておくのは妥当なように思う。

生成されるコードは何も指定しないと大きい。依存先を含めてシンボルを再帰的に変換していくので当然といえば当然である。 実用上はpublic apiだけを変換対象のホワイトリストに指定することのほうが多いと思う。なんとか-sysを作るための道具なので、そこで生成したコードをそのままアプリケーションコードから呼ぶべきではない。

使い方?それはREADMEでも読めばいいんじゃないかな。

2016年やったこと

本業

  • 色々あった
  • 2016年も大変な一年だった

前半

後半

github:voyagegroup/eslint-config-fluct

  • internalに使ってるルールを、そのままpublicにした感じ
  • npm公開とかは検討中. 別にnpm publishしなくても再利用できるしね.

Open Source Development

facebook/react

ReactiveX/rxjs

rxjsのpull requestはrebaseが必要だとnetflixのメンテナーが適当にcherry-pickしてmasterにlandするので、ちゃんと取り込まれたものでも、closedとmergeが両方あったりする

Microsoft/TypeScript

karen-irc/option-t

  • 細々と必要に応じて更新してたり

karen-irc/karen

  • 趣味プロジェクト
  • 完全に自分用のビルド設定遊び場と化している……

servo/servo

  • 今年も殆どinactive(何やったか忘れたほどに……)
    • mailing listとかissueとかpull requestはだいたい見てるんで、何やってるかは知ってるんですが……
  • ちょっと手が空いた時に簡単なpatchを気晴らしに送る、みたいな関わり方だった.
  • もう少しやりたかったけど、そこまでの精神的余裕がなかった

総評

  • 色々あった
  • 何かを新しく学んだ、という印象は少ない一年だった
    • なんかアウトプットだけで終わった感はあるんだけど、その割にインパクトのあるアウトプット思ったよりも少ないですね……
  • 2017年は、インプットとアウトプットをもう少し増やしたい

備忘録: yarnpkgで依存パッケージのガーデニング作業を楽に行う

前提

How to

  1. yarn outdatedとかで更新が必要そうなものを眺める
    • いきなり2へすっ飛んでもいい
    • バージョンをstableとかdevとかnextで指定している場合は出てきたり出てこなかったりするけど
  2. yarn upgrade-interactiveする
    • バージョンをstableとかdevとかnextで指定している場合は出てきたり出てこなかったりするけど
  3. 2を繰り返す
  4. yarn upgradeで, 表に出てこない依存関係含めてyarn.lockを更新する
    • 今のところ, ./node_modules/を消して, yarn.lockを消して, yarn installしてyarn.lockを再生成した場合と同じ効果が得られる

Node学園#23で広告ジャバスクリプトの話をしてきました

スライドに書いてない詳細とか補足とかは, 勤務先のブログに書くかもしれないけど, もう少し私的な記録として.

Node学園#23で, 今年の始め〜夏ぐらいにやっていた話をしてきた 元々, 東京Node学園祭2016にCFP出してたんだけど, 甲斐なく落選してしまったので, お焚きあげということで発表させてもらった.

コアの実装だけで言えば2週間ちょいくらいで片付けられたし, これ以外にも細々とした色々をやっていたので, 実働時間としては大して多くは無いんだけど, 精神的には今年で一番手間暇をかけたような感じだった. 実装が難しいというよりも, とにかく面倒くさい. 原理的に何が出来て何が出来ないのかを各種specを元にちゃんと詰めて実装する面倒臭さ.

そんな感じでなので, どこかの勉強会で発表して締めということにしてみた. 締めとして勉強会とかブログを一本まとめを出せるように仕事するのは結構楽しいというかチャレンジしやすくていいね. なるべくこういうスタイルで仕事をこなしていきたいものである.

オンライン広告については, テクノロジ的に面白いことが多いんだけど, Webのユーザーとして見た場合にクソみたいな広告案件と接することも多くて, 総体としてあんまり印象が良くないのが寂しいね. 仕方ないが.(編注: 個人の感想であり, 勤務先とは関係のない意見です).

そろそろJavaScriptは飽きてきたので, RustとかScalaとかJavaとかC#とかGoとかC++とか何かで新しい何かを書いていきたいものだが, はたまた.