エンジニア立ち居振舞い: 発言にブレーキをかけない
僕自身が普段から意識的にやっているのは発言にブレーキをかけないことだ。
具体的にはslackのpublicな部屋で騒ぐ。 作業中にハマってしまっていかんともし難い時や、クソコードを見つけて怒りが湧いてきた時、などなど。
ハマってる内容を呟いておくと、以前にも同じような経験をした人が反応してくれて一瞬で解決に導かれるかもしれない。
クソコードに対して怒りをぶつけていると、同じように共感した人が現れてやっていきをお互い高められて、いい感じにタスク化できるかもしれない。クソコードは見ているだけでイライラしてくるので、吐き出すだけでも気持ちが宥められる効果がある。
時には実は騒いでいた対象はクソコードではなくて、僕の実力が足りていないがゆえにそう見えてしまっていただけのこともある。それはそれで良くて、一時僕は恥をかくかもしれないけど、引き換えによって得られる学びは比較にならない。
発言にブレーキをかけない、と言うと他人への配慮を欠く発言をしても良い、みたいな印象を受けてしまうかもしれないけど、それは全く違う。ここで大事なのは遠慮しないということと、publicな場で発言しにくい空気を作らないということだ。
人間のパターン認識力はめちゃめちゃ高度なので、内容だけ見ればある程度攻撃性を伴ってしまう発言でも、思いやりを含んだコンテキストや言葉尻であれば、受け手はそれを感じ取ることができる。 コードを憎んで人を憎まずというのと似ている。
人じゃなくてコードを憎みたい気持ちなんだけど、言い方と聞き方次第で人を攻撃してるみたいになりそうで言葉に出せない気持ちに行き場がない
— じょう (@joe_re) 2016年7月6日
じっさいのところ、プロダクションに入ってるコードは最低限レビューされてるはずだし、そのコードを書かなければならなかった当時の状況とか、既存のコードに引きづられたりすることもあるだろうし、書いた人は悪くない
— じょう (@joe_re) 2016年7月6日
という気持ちを持っていて、人は憎みたくないんだけど、悪いコードは悪いと言っていかないとお互いの成長は望めないと思う。
こういう自分の発言に反応があると嬉しいので、他の人の発言もなるべく反応するようにしている。なんでもかんでも反応していると作業時間がなくなってしまうので、なかなか線引きは難しい。自分がある程度近しいコンテキストを持てる内容ならば、という感じ。線引きを迷っているな??と自覚した場合には、ブレーキをかけずに発言するようにしている。分からなければ分からないと発言する。無視してしまうよりは良い。議論が盛り上がっていると、自然と人が集まってきて、そのうち有識者が現れるみたいなことも期待できる。
もしチームに入ったばかりの人が困惑しているようなら、詳しそうな人にメンションしたりもする。チームに入ったばかりの人は、誰がどこに詳しいかが分からないので、そういうフォローが大事だと思う。
こういうものはpublicな場でやることが大事だと思っていて、closedな場でやってしまうとせっかく得られたハマりポイントの知見やクソコードに対する怒りが共有されない。勿体無い。
とはいえTPOは大事で、サポートやセールスも含めた全体連絡用の部屋でクソコードの話題を振るのは違う。
いろいろなコンテキストごとに部屋があるとすごくやりやすくて、今の会社はslackの部屋を誰もが好きに作れるので恵まれてるなー、と思う。(部屋が大量に生まれすぎる問題もあるので、バランスは難しいですね。)
思いやりのあるマサカリを投げ合っていきましょう。
Frontend Meetup vol.1 で革命と秩序とSPAという発表をしてきた
FiNCさん主催のFrontend Meetupというイベントで革命と秩序とSPAという発表をしてきた。
有志の方がまとめを書いてくださっているので、そちらもぜひ。
僕の発表資料はこちら。
主催のFiNCさん、ありがとうございました。
内容
フロントエンドのパラダイムシフトとfreeeの関わり方と、今のスタックであるReact + FluxUtils + Frowtypeについてのお話。 どちらかといえば後半のFlowtypeの適用についての方に力を入れてお話しした。
個人的な感覚もあるけど、Flowtypeはここ1年で大分扱いやすくなっている。当初はReactのAPIの型定義が揃っていなかったりしたけど、現状では型定義のないAPIは見当たらない。 意味のわからないエラーに遭遇することもほとんど無くなった。個人的な慣れもあるかもしれない。
なぜTypeScriptでなくてFlowtypeなのか、という点については単純にbabelでトランスパイルする環境がすでにあるので、それを刷新してまでTypeScriptに寄せるよりも導入が楽だからというのが一番大きい。 当初からデフォルトがnon-nullableであったとか、個人的な好みもあるけれど、TypeScriptにも2.0から--strictNullChecksが入ったし、そういう部分での優位性は失われつつある。
Flowtypeの世界はあくまで型アノテーションであり、TypeScriptは言語であるという根本的な違いはあるけれど、少なくとも静的型を提供するという目的においては両者とも同じ方向を向いている。
資料でも触れているけど、僕はjsには絶対に型が必要だ!という強硬派ではない。だけどチーム開発においては型があることの利点が大きいと感じている。
Fluxなりのアーキテクチャによりレイヤーを設けられたフロントエンドの世界において、Flowtypeを導入するだけで型安全を手に入れられるのか、というとそんな訳はなくて、それなりに書き方を工夫する必要がある。(具体例は資料に書いています)
発表は試行錯誤した結果だけど、もっといい書き方もあるかもしれない。知見のある方と是非意見交換したい。よろしくお願いします。
宣伝
というわけで、freeeでは革命と秩序に積極的なフロントエンドエンジニアを鋭意募集しています。
共に世界をぶっ壊して再構成して秩序を取り戻しましょう。よろしくお願いします。
flowtype v0.32.0 changes
flowtype v0.32.0がリリースされました
Release v0.32.0 · facebook/flow · GitHub
この変更では待望のgen-flow-filesコマンドが追加されています。 これはflowtypeのシンタックスで書いたjsファイルから、型定義情報を生成するコマンドです。
これまではライブラリ作者が型定義情報を提供しようとした時に、外部提供用の.js.flowを別途用意する必要がありましたが、これによってその必要がなくなります。 まだalpha-levelなので、安心して使うにはもう少し待つ必要がありそうですが、これは非常に捗りますね。
その他何点か機能追加があったので試してみます。
gen-flow-files コマンドの追加
先ほども書きましたが、待望の機能です。 flowtypeのシンタックスで書いたjsファイルから、型定義情報を生成することができます。
- calcRectArea.js
// @flow type Rect = { x: number, y: number }; export default function calcArea(rect: Rect) { return rect.x * rect.y; }
このjsファイルに対して、flow gen-flow-files [filename]
を実行します。
$ flow gen-flow-files calcRectArea.js // @flow declare export default function(rect: {x: number, y: number}): number;
declare export default function(rect: {x: number, y: number}): number;
という型定義情報が出力がされてますね。
便利。
exact object types シンタックスの追加
これまでflowにおいて、オブジェクトの型定義は{ hoge: type}
のみでしたが、より正確なオブジェクトを定義するためのシンタックスとして{| hoge: type |}
が追加されました。
{ hoge: string}
と記述した場合には、「少なくともstring型であるhogeプロパティが含まれること」という検証がされます。
{hoge: 'hoge', bar: 'bar'}
というオブジェクトは、この型定義に当てはめた時にbarが余計に含まれていますが、上記の条件は満たしているため検証が通ります。
{| hoge: string |}
と記述した場合には、「string型であるhogeプロパティのみを持つこと」という検証がされます。
{hoge: 'hoge', bar: 'bar'}
というオブジェクトは、barプロパティを余計に持ってしまっているためエラーとなります。
従来の型定義
// @flow type Rect = { x: number, y: number }; function calcArea(rect: Rect) { return rect.x * rect.y; } console.log(calcArea({ x: 2, y: 3, z: 4 }));
$ flow No errors!
exact object types
// @flow type Rect = {| x: number, y: number |}; function calcArea(rect: Rect) { return rect.x * rect.y; } console.log(calcArea({ x: 2, y: 3, z: 4 }));
$ flow exact.js:8 8: console.log(calcArea({ x: 2, y: 3, z: 4 })); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function call 8: console.log(calcArea({ x: 2, y: 3, z: 4 })); ^^^^^^^^^^^^^^^^^^^^ property `z`. Property not found in 3: type Rect = {| x: number, y: number |}; ^^^^^^^^^^^^^^^^^^^^^^^^^^ object type Found 1 error
resource filesのデフォルト型定義情報の追加
.css, .jpg, .png, .gif, .eot, .svg, .ttf, .woff, .woff2, .mp4, .webm のファイルをrequireしたときにデフォルトで型定義情報が付与されるようになりました。 .cssはObjectとなり、他のリソースファイルはstringとなります。
(this list is not configurable at the moment).
だそうなので、そのうち設定ができるようになりそうです。
自分で型定義を与えたい場合には、これまでどおりmodule.name_mapper
で設定する必要があります。
参考: Flow | Advanced Configuration
flowはtype-at-posコマンドで、指定した位置の変数の型定義を出力することができるので、これを使って試してみます。
- requireResource.js
// @flow import css from './test.css'; import gif from './test.gif'; console.log(css); console.log(gif);
$ flow type-at-pos requireResource.js 6 13 Object /Users/joe-re/src/try-flow-032/requireResource.js:6:13,6:15 See the following locations: /Users/joe-re/src/try-flow-032/requireResource.js:6:13-15: Flow assumes requiring a .css file returns an Object
6 13という引数は6行目の13列という指定です。css変数を指定しています。 想定どおりオブジェクトが返ってます。
[~/src/try-flow-032]$ flow type-at-pos requireResource.js 7 13 string /Users/joe-re/src/try-flow-032/requireResource.js:7:13,7:15 See the following locations: /Users/joe-re/src/try-flow-032/requireResource.js:7:13-15: string
こちらはgif変数を指定しています。 こちらも想定どおりstringが返ってます。