貴方がある日突然、チンパンジーにドミニオンと将棋と囲碁を混ぜたようなゲームを教えてもらうことになったらどうしますか?
それも……
その猿はとびっきり凶暴で
とびっきりの指示厨で(内容は間違ってる)
とびっきりの陰キャ
しかも、そのうえ……その猿共はみんなみんな初心者狩りが大好きなんです!
今までの「理想の働き方」だったリモートワークと現在の状況の決定的な違いについて
私のように寝起きが絶望的に悪く、電車が死ぬほど嫌いで、自宅が大好きな人間にとって理想の制度であったリモートワークですが、COVID-19にまつわる社会の変革に伴ってある種(もちろん物理的に可能な業種に限られてしまいますが)標準の選択肢となった感があります。
とにかく変化を嫌い、天災に対して「耐える」という態度が染みついている日本の社会へ対してはすでに諦観の境地へと至っていたわけですが、この度の出来事において柔軟な対応をみせようとしてくれていることについては素直な驚きと喜びを感じます。
さて、このようにしてリモートワーク(テレワークでもいいですが)の導入が我が国でも急激に進行しているわけですが、いわゆるコロナ以前を含めてリモートワークのpros and consをしっかりと語っているような記事はみたことがなく、リモートワークを禁止している組織にしたところではっきりとした根拠をもってしていたわけではないのではないかと推測します。
前提としてリモートワークというのは、組織の動かし方として難易度が上がる施策だと私は考えてます。そのようなやり方を、このように社会が混乱している中で半ば不可抗力のように導入した組織や、そこに属する個々人がこの状況でリモートワークに対してネガティブな印象だけをもってしまうと悲しいのでこのエントリを書くことにしました。
今の状況はリモートワークではなくて在宅勤務である
数々のネガティブ要素を突き放して、リモートワークの圧倒的なポジティブとして君臨していた要素が働き方の自由度です。
(ネットワーク回線、時差という縛りはありつつ)基本的に場所に縛られずに、それぞれの好きな場所で働くことができたわけです。例えば地方や海外へ旅行や半移住しながら働いている人も何人か知っています。もちろん小さい子供の送迎をしてから普通に自宅で働く人もいますし、リモートワークできる会社だけど職場のほうが働きやすいから出勤するよ、という人もみました。
働く場所、働き方を選べるというのが今までのリモートワークの素晴らしさの中核にあったと僕は信じています。逆にこの「選べる」という状況そのものが今まで人や組織を選んでしまっていた要因なわけですが、現在の疫病による在宅勤務では働く場所を選ぶことはできず*1、非同期的労働環境に慣れていない組織では選択の余地も少なく……という形でみなさん疲弊して、最悪のケースだと職場を嫌うように自宅を嫌いになってしまっている方もいるんじゃないかとおもいます。
物理的に会うことの重要さ
私は比較的長い間インターネッツと共に過ごしてきたはずで、それこそMMOにハマっていた時期なんかは家族と会話するよりもギルメンとボイチャで話している時間のほうが長かったくらいの廃人でした。
当時のインターネットのコミュニティで、仲良し度が上がってきてから開催されるものといえばオフ会でした。
一日中MMOの中で集まって「暇だね~~」とかチャットしまくっている陰のオタクですら物理的に会って話すことを特別視していたわけです。うんうん、絆だね。
随分むかしに読んだっきりでうろ覚えなのが恐縮ですが、31signalsの書いた「強いチームはオフィスを捨てる」という本でも年に1回だか2回はチーム全員で集まって顔を合わせる日を作るというようなことを書かれていましたね。
強いチームはオフィスを捨てる: 37シグナルズが考える「働き方革命」
- 作者:ジェイソン・フリード,デイヴィッド・ハイネマイヤー・ハンソン
- 発売日: 2014/01/24
- メディア: 単行本
ひるがえって今の状況ですが、みだりに他人と顔を合わせることが推奨されていません。
「必要だったらお互いの中間地点のコワーキングスペースにでも行って一緒に作業すればよくねw」といったリモートワークがもたらすのフットワークの軽さも、ここでは生かすことができません。
それでもリモートワークはよいものだ
と、ここまでネガティブな要素を並べたてましたが、私自身はリモートワークの強い支持者です。
私は体質的に免疫力が弱く、とても風邪をひきやすいです。1シーズンに数回もらうようなことはザラで、だいたい病欠で有給休暇を使い切ります。COVID-19云々以前にもインフルエンザやノロウィルスが流行するたびに満員電車で嫌なおもいをしてきました。
出勤というイベントがなければこういった伝染病のリスクは自分でコントロールが可能になります。
また、僕は自宅の作業環境にかなりの投資をしているので基本的にどこのオフィスであっても、チームメンバーと会話しやすいという一点をのぞけば物理的なクオリティが劣っている場所で作業することになります。
等々……とにかく人生の幸福においてリモートワークが貢献する部分は大きいと信じています*2。
ワークライフバランスという言葉がありますが、あれは嘘です。詐欺師のダブルバインドに騙されてはいけません、人間に必要なのはまずライフです。ライフの中の比較的大きめな円がワークです。
リモートワークのコツは楽しむことです。在宅を強制されていても、ならではの楽しみ方とかはあるんじゃないかとおもいます。お昼にパン焼いたりとか。
なんにせよ好む、好まざるにかかわらず当面はこの働き方と付き合っていく必要がある人も多いはずです。
今の状況をリモートワーク矯正ギプスだと捉え、ここで筋力をあげていくことで本当のリモートワーク力が鍛えられる。そしてコロナ禍が去った後は真のリモートワークで自由と責任を堪能できる。わたくしはそういう気持ちでいる次第であります。
こちらからは以上です。
追伸:
リモートワークのコツは良いマイク、そして良いヘッドホンです。買いましょう。
いまさら解説する頭が良いとはどういうことなのかについて
はい。
みなさんはそれぞれ「頭が良い」ということについて一言持っているはずです。インターネッツでも定期的に言及されてあーでもないこーでもないと喧々諤々無益な自転車置き場的議論が発生しているのが観測できます。
というわけで今日ぼくも石を投げます。
結論から言うと頭の良さとは「認識の解像度の高さ」です。
例えば今流行のCOVID-19へどう対策するか、となったとき、解像度が高ければ
続きを読むFlutterでBLoCだChangeNotifierと振り回されて消耗するまえに
追記
providerとかfreezedの作者が作ってる state_notifier が当エントリとほぼほぼ同じことをやっているので依存が増えることを気にしない人はそっち使ってもいいんじゃないかとおもいます。
みんなの心はひとつでした。
まえがき
先のエントリ BLoCにおけるリモートデータの状態遷移のパターンをくくりだす方法 - タオルケット体操 の書き方からもわかるように、そもそも僕はBLoCが嫌いです。
というか10年前にC#がRXをはじめたときからわかっていたはずですが、ObservableStreamは超かっこいいけど使い道の少ない技術です。フレームワークの裏側で使う分には便利ですが、表に出てくるべきではないでしょう。普通のGUIアプリケーションであれば99%のユースケースはただのコールバックで満たせます。
しかもBLoCはViewModelのパターン*1です。ViewModelとViewの接続にStreamが必須になるようなケースをどれだけおもいつけますか? コナミコマンド? せめてFlutterのTextFieldやControllerなんかがStreamをストレートにサポートしていればいいのでしょうが、もちろんそんなものはありません。
さらにもうちょっと高度なことをやろうにも、Dartの貧弱な型システムでは安全性の担保が面倒です。
というわけで、 例によって界隈はBLoCだるくてかなわんしシンプルなChangeNotifier(要はEventEmitterです)つかおーぜww という空気になっているようです。
ただし、ChangeNotifierはある意味でBLoCよりも退化しているパターンです。公式を鵜呑みにすると消耗します。
*1:なのでいわゆるApplication Stateを管理する方法について、Flutter界隈にデファクトは存在しません
不要なクラス宣言、やめちゃおっか?
今回のエントリは特定の言語に向けて書いているわけではありませんが、関数をサポートしていない言語では必然的にクラスをベースに実装していくことになるのである程度は対象となる言語は絞られます*1。
また特に説明がなければサンプルはTypeScriptで書きます。
さて、あくまで傾向としてではありますが関数を作れる言語の経験が短い人(例えばJavaやRubyですと、関数ではなくクラスに対するメソッドという形で実装することになります)は、単機能の振る舞いを実装するためだけであっても以下のようなコードを実装しがちです
class DoSomethinger { constructor(private something: Domething) {} public doSomething() { return dooo(something); // do something } }
これは
const doSomething = (something: Domething) => { return dooo(something); // do something };
と書きましょう。
今回は以上です。 :+1:
で終わらせるのはあんまりなので理由について述べます。
理由
これにはいくつかの理由があります。代表的なものを以下で説明します。
0. 簡潔に書く
単純に、関数で済むものは関数で書いた方があらゆる意味で簡潔です。
1. 不要な状態を持ち込まない
例に挙げた DoSomethinger
のようなクラスは、すぐに setAnything
のようなメソッドを生やしはじめて管理不能に陥ります。
引数と結果のみが存在する関数と比べて、クラスのコンストラクターとメソッドという中間状態にmutabilityが残る手法は不確定要素が増えてしまい、その分保守性や利便性が下がります。
またこのようなクラスは往々にして責務が曖昧なため、1ヶ月後の自分や他のメンバーが無計画に新しいメソッドを増やしがちです。そしてそれに伴って新たな状態setterが追加されてしまい、初期化や特定のメソッド呼び出しに暗黙の順序が増えていってしまいます。
それを避けるための方法としてはBuilderPatternなどが存在しますが、全てのオブジェクトをそのパターンにのっとって実装してしまうとプロジェクトはenterprise fizzbuzz化してしまいます。
まとめ
色々と書こうとしたのですが、本稿に関してはとにかく「意味もなくクラスを使うのをやめろ」という以外にいうことがないことに気がつきました。
現代のプログラミング、特にGUIの中でも宣言的UIを採用しているもので最も重要な要素はimmutabilityです。クラス(そしてデータに振る舞いを持たせること)はあらゆる意味でそこと相性が悪いです。
上の理由では頑張ってクラスを「使わない理由」という形で文章をひり出しましたが、本来は逆で「クラスを使う理由」があるときに限ってクラスを使うべきです。
しかしほとんどのケースは関数の機能(クロージャーとか合成)でまかなえます。せいぜいメソッドチェーンでいい感じに書くインターフェース作りてぇなぁとかその程度のユースケースじゃないでしょうか。
特にReact Hooksがリリースされた今となっては、フロントエンドの実装でクラスが必要になることはほぼ皆無といっていいでしょう。悔い改めよ。
以前に書いた記事: https://hachibeechan.hateblo.jp/entry/pipeline-operator-will-be-good-friend-of-typescript ではまさにメソッドチェーンしたいという気持ちからクラスを使っています。
補足: Dart
Dartのように、関数をサポートしていてもクラスとメソッドで実装したほうがベターということになりがちな言語も存在しています。その辺は大人の判断力でどうかひとつ、よろしくお願いします。
補足: TypeScript
クラス使わないならどう書くんや的な疑問を持つ方への補足です。
こう書きます。
type User = Readonly<{ name: string; email: string; }>; const setName = (u: User, name: string) => ({...u, name}); const setEmail = (u: User, email: string) => ({...u, email}); >>> const userA = {name: 'user a', email: 'user-a@hoge.com'}; >>> userA2 = setEmail(setName(userA, 'user a2'), 'user-a2@hoge.com');
無限に括弧がネストされて辛い、メソッドチェインみたいに括弧よく書きたいという場合は先に紹介した記事を参考にすると上のコードをリファクタリングできます。
え、でもその書き方古臭くないですか?
察しの良いかたはお気づきかもしれませんが、上の書き方は古のコーディングスタイルを踏襲しています。
そう、C言語です。
C言語ではstructで宣言したデータに対して、それをレシーバにとる関数群を用意して振る舞いを表現していました。
本稿で僕が推奨してる書き方はほぼそのまんま、その書き方を踏襲する形をとっています。古き良きじゃん〜。
このスタイルはStoreをPOJOに保つことを強く推奨しているReduxと特に相性が良いです。
また、やってみるとわかりますが構造的部分型による型検査を行い、クラス宣言されたものをのぞいてはランタイムに型情報が消滅してしまうTypeScriptと非常に親和性が高いです。あと継承とかいう主に自分の両足を縛り付けてうまく歩けないようにするための機能が付属してきません。
ちなみにPythonもメソッドの第一引数は必ずthis(self)を宣言する必要があるということになっていますが、これも実質的に僕が推奨しているようなスタイルと同じことをやっているわけですね(強引な結論)。
実際、Pythonでメタプログラミングをしていると関数を動的にクラスに紐づけていくようなことをしょっちゅうするわけですが、そういうことしているとメソッド呼び出しはselfを第一引数にする関数呼び出しの糖衣構文なんだ*2なぁというのを強く感じたりします。
ちなみにモダンな言語でもこのようなスタイルを取り入れている言語がありますね、みんな大好きGo言語とRustとか。それぞれ実際の振る舞いや指向は微妙に違っている気がしますが?
そういえばDiscordがGo言語で書いてたマイクロサービスの一つをRustで書き換えたら最高にハッピーだった、みたいな記事でまた界隈がザワついていましたが、ざっくりとだけ記事を読んだ自分でもその焦点がGCであって、つまりGCがボトルネックになっちゃったからGCがない言語(C++とか)で書き直したらすごく速くなったよ、また光もらっちゃったね。
そういう今までよくあるストーリーだったんだけどその乗り換えた先がC++じゃなくてRustだった、つまりあの記事でなんらかのX vs Y要素を見出すならC++ vs Rustなんだよね。
そういえばPOJOってなんかジョジョっぽいですよね。
おしまい。