Qiitaのランキングの最初の設計者としての「いいね」の設計と、「LGTM」は下においてほしいという話

https://blog.qiita.com/like-to-lgtm/

これについては chokudai さんに完全に同意なのですが、その理由として、自分の在職時に企画したサービス設計意図が強くあって、退職者がそれについて今更どうこういうのはどうか思うところもあるのですが、当時の同僚がほぼ全員退職してしまっているため、ここでその意図を伝えます。

お前は誰 & 何

当時の Qiita の開発で、ストックといいねを分離して、いいねをベースにしたランキングの実装のを提案したのが自分です。社内の Qiita:Team にそのログは残っていると思います。3年前に退職しました。

いいね導入の際に、ユーザーの皆さんに混乱を招いたことは申し訳なく思っています。ただし、その時の「いいね」は自分の提案したものと、かけ離れた形で導入されており、その件についてこの記事で説明すると同時に、LGTM は末尾に置くべき、という主張をします。

自分が提案した総合ランキング/サブカテゴリランキング制度

5 年前、当時の Qiita は Google,はてブからの流入が多く(現在でも比率が高いはずです)、自力でユーザーの回遊を回せない、サービス内でエンゲージメントを高める動線が弱い、といった課題がありました。これは Google 側の SEO アルゴリズムの変更や、はてなドメイン フィルタリングなど、なんらかの事情で Qiita への流入が絶たれると、サービスとして致命的である、 といった危機感です。

また、Qiita のサービスリリースの初期は機能していたタグ購読機能、ユーザーフォロー機能が、タグの多様化やコミュニティの肥大化で、あまり機能しなくなっていました。

そこで、ユーザーのエンゲージメントを上げる、つまり記事を書くやる気を出してもらう方法として提案したのが、ストックや閲覧数をベースにしたランキングシステムの導入です。その上で、総合ランキングのみでは、ノンジャンルで読みやすい「ポエム」が上がりやすくなってしまう(某壁問題)ので、タグの共起の相関クラスターなどを元にしたカテゴリ分類での、サブカテゴリのランキングの導入を提案しました。これはユーザータイムラインの代替として機能するはずだ、という意図です。

結果として、実装工数などの問題で、総合ランキングのみが導入され(これをテストリリースした段階で退職)、その後、後者は実装されませんでした。

時は経ち、 トップページのメインの動線が機能しなくなったユーザータイムラインから総合ランキングに切り替わったとき、当初懸念したとおり、技術的な実体のない「ポエム」系統の記事で上位が埋め尽くされる問題が加速してしまいました。

自分としては、これは当初提案していたサブカテゴリのランキング/あるいはクラスターのフォローの実装をしていれば防げたかもしれない問題だと思っています。(が、ちょっと自信無いです…)

いいねとストックの分離について

まず、Qiita には最初にストックがありました。これは「後で読む」ということを意図した機能です。なので、ストックは記事トップにありました。ランキング機能を作るにあたって、読まずにストックする可能性が高い「あとで読む」を転用すると、タイトル詐欺が加速する懸念がありました。

そこで、個人的な記事のストックとは別に、読み終わったあとの評価を分離した「いいね」の導入を提案しました。

もっというと、自分はストックは完全に不要な機能だと思っていました。個人のブックマークやソーシャルブックマークなどによって、それらは別途個々人がもっていたはずです。ただし、これは既存のユーザー の体験を壊すことになってしまうという yaotti の強い反対で、ストックの廃止は見送られ、ストックといいねが共存することになりました。(自分は今でもストックの存在は不要だと思っています)

その折衷案として、ストックは記事冒頭に表示するが、読み終わった人しか「いいね」を押せなくする、するという形で、いいねが実装されました。そしてランキングのソースはいいねを使うこととする、といった形になりました。

なので、いいねか LGTM かはどうでもいいのですが、記事の評価に対するフィードバックなので、そのボタンは末尾に置くべきだと思っています。読まずに LGTM を押す人が増えるという懸念です。

今のサービス設計から邪推してしまうこと

Qiitaは、基本的にいいねを押されるのが記事を書くモチベーションになっているプラットフォームです。だから、書き手のエンゲージメントを上げるために押しやすくしたいのは、とても理解できますが、タイトルだけで中身がいまいちなものが押されるようになると、その価値が失われてしまうのではないか、ということを伝えたいです。

報告: 結婚しました

私事ですが(と個人ブログでいうのもなんですが)、syakejs:(blog) と結婚しました。彼女は Webエンジニアだったり、大学でセキュリティの研究をしてたりしています。競プロやCTFもやってるらしいです。 話を聞いてみると、昔から僕のブログやTwitterをみていたファン?だったらしいのですが、最近なんやかんやあってコンバージョンしました。

入籍いつしよっかーという話になって、西暦2020年(令和2年)2月22日というゴロがよかったので、この日に決めました。

なにかしたからと言って別段何かが変わるというわけではなく、これからも普段どおりやっていくので、みなさんよろしくおねがいします。

俺のテン年代を象徴するゲーム 9 本

2020年になり、先の10年のゲームを振り返るのが話題になってたので、自分も書く。

RPGが多く、洋ゲー寄り。あくまで自分がこう思っているというだけで、なにかの総意というわけではないのに注意。

jp.ign.com

anond.hatelabo.jp

追記: 最初は 8本だったが、 Bloodborne を追加して 9本になった

ウィッチャー 3 ワイルドハント

store.steampowered.com

Bethesda のゼロ年代の TES IV: Oblivion と Fallout3 という2つの傑作が、テン年代オープンワールドを方向性を決定づけた。テン年代オープンワールドからベストを一本選ぶなら、その続編の TES V: Skyrim も Fallout4 も、そしてもちろん任天堂ゼルダの伝説:BotW も素晴らしかったが、自分はウィッチャー 3 を選ぶ。

ウィッチャー 3 の最も優れている点は、長時間のプレーに耐えうる世界感の強度だ。中世ヨーロッパの戦乱の時代に人々を脅かす怪物が実在したら、そこに住む人達はどんなことを考え、どんな出来事が発生するだろうか?怪物狩りの専門家は、どのように獲物を追い詰めるだろうか。

プレイヤーは主人公のゲラルトを通じて、それを追探検する。ときには野生動物の専門家のように、ときには探偵のように、その足跡をたどり、 怪物が怪物になった由来と、その背景にある人々の情念を知ることになる。依頼主に怪物退治の顛末を報告し、場合によっては問い詰めて反省を促したり、賄賂を受け取って、事件そのものをなかったことにする。更には戦間期の王侯貴族の陰謀に巻き込まれる。

ゲームプレーの緩急のデザインも素晴らしく、やや制限されたファストトラベルと、錬金素材を採取しながら野山を歩き回り、野生のモンスターの巣を潰すのは、それだけで楽しい。アイテムを集めて自分が強くなっていく感覚と、そのために次に何をやるべきかの PDCA がプレーヤー自身で自然と考えられるようになっている。

日本語版のウィッチャー 3 の一番の魅力は翻訳で、常時皮肉っぽいゲラルトの魅力を最大限引き出すような翻訳と、ゲラルトを演じる山路さんの演技が素晴らしい。正直なところ、自分がベセスダの RPG にハマりきれないのは翻訳の問題があると思っていて、ゼニマックス・アジアの常時直訳調で別撮りと思われる感情の欠けた会話劇にうんざりしているところがある。それがなければ、もしかしたら Skyrim の方が上に来ていたかもしれない。

今ならほぼすべてのプラットフォームに移植されているので、ホワイトオーチャードで野生のグリフィンを狩る序盤のイベントは、是非体験してもらいたい。

Bloodborne

www.jp.playstation.com

ソウルシリーズ、ソウルライクのうちソウルの名を冠さない Bloodborne は、しかし確かにソウルシリーズでありつつ、明確に差別化された傑作だった。

ヴィクトクリア朝時代のロンドンを舞台に、ヴァンパイアハンターをモチーフにして、獣達やクトゥルフ神話から飛び出てきたと思えない怪異に挑む。

初見のステージを物理カット率100%の盾を構えながら恐る恐る一歩ずつ進むダークソウルシリーズと違い、Bloodborne は意図的に盾や防御的なアクションすべてが弱めに設計されている。代わりに、全体的にアクションがスピーディで、殴られたら即座に殴り返すと体力の一部が回復するというシステムが採用されており、プレイヤーは文字通り、「血に狂って踊る」ことを要求される。

人間の衝動性、暴力性を象徴する「獣性」、ラブクラフトの宇宙的恐怖、知ってはいけないことを知ってしまう「啓蒙」を対比しつつ、その両方をシナリオと密接に絡めて、ゲーム体験に昇華する手際が見事だった。DLCの、大聖堂やら病院やら時計塔やらを通り抜けた先の最終ステージが「漁村」だったときは、もはや隠す気がないラブクラフト感に笑ってしまったが。

ダークソウル3ゼロ年代末のデモンズソウルの正当進化として役目を果たしたが、Bloodborne は確かにソウルシリーズでありながら確実にソウルシリーズから差別化された作品であり、よりスピード感とアクションを高めた Sekiro という後継作もあるが、個人的にフロム・ソフトウェアに期待しているのは Bloodborne 的なゴシックホラーで、エルデンリングのあとでも良いので、何卒。

Divinity Original Sin

store.steampowered.com

store.steampowered.com

日本ではメジャーではない言葉だが、JRPG との対比の一つに、WRPG(Western RPG, 欧米の RPG) という分類がある。さらにその狭義として、D&D を元にしたバルダーズゲートと、そのフォロワーを指すことがある。ダークファンタジー、アイソメトリック(斜め見下ろし), ターン制ではない RTS 的な戦闘システムといったものが共通している。

一部で熱狂的なファンを獲得したバルダーズゲートだが、ジャンルとしてはその後徐々に縮小していた。そこに再びスポットライトを当てたのが、Larian Studios の Divinity Original Sin だ。

同スタジオのよりバルダーズゲートの戦闘システムに近い Pillars of Eternity シリーズも良い出来なのだが、 Divinity Original Sin の一番面白いところは、伝統的な RTS ではなく XCOM シリーズの Action Point 性を採用したところにある。剣と魔法の世界で、かつハックアンドスラッシュ的な成分の強い XCOM という言い方もできるかもしれない。(それはたぶん XCOM ではないが)

Divinity Original Sin は英語圏で高評価を得て、続編も発売されている。元は Steam で発売された本作だが、Divinity Original Sin: Enhanced Edition と Divinity Original Sin 2: Definitive Edition はローカライズされていて、PS4 で 1 と 2, switch で 2 を日本語でプレーできる。テキスト量が膨大で翻訳の質もまちまちなので残念ながら日本ではあまり売れていないようだが、骨太な RPG をやりたいという方は、是非手にとってもらいたい。

Faster Than Light

https://store.steampowered.com/app/212680/FTL_Faster_Than_Light/?l=japanese

ゲームの本質的な面白さとはなんだろうか。グラフィックがキレイなこと、要素が多いこと、色々あるが、FTL の出した答えは「コアとなるメカニクスがいかに美しいか」だと思う。

今手に入るもののうち、砲台は何を採用すべきか、船のリアクター出力をどこまで優先するか。船員はどんな種族に砲座を担当させるか。船体の体力と相談して、どれだけ危険なルートを通ってリスクを負うか。敵の白兵戦にはどう対応するか。今足りない人員を補充するのにどの星系に向かうか。

FTL のグラフィックは自分の宇宙船と敵の宇宙船が映ってるだけで必要最小限だが、必要な情報はすべて収まっている、という点で美しい。

FTL のミニマルさとランダム性は、「ローグライク」を再定義したように思う。今の Steam でローグライクを名乗るゲームは、なんらかの形で必ず FTL に影響を受けているような気さえする。

Slay the Spire

store.steampowered.com

ec.nintendo.com

これ以前にもデッキ構築型のダンジョン RPG はあったが、少なくともこれをメジャーにしたのは Slay the Spire に間違いない。このゲームの完成度は凄まじく、このフォロワーだけでデッキ構築型ローグライクというジャンルの隆盛を生んでいる。

プレーヤーは山札からカードを引き、エナジー(マナ)の分だけ手札からアクションを行使できる。敵の行動は予告されており、防御やデバフで被害を最小限にしながらそのターンの被害を最小限にしつつダメージを与えなければならない。敵に勝つと、ランダムに選ばれた3枚からカードを一枚取得でき、それが自分の山札に入る。これを繰り返して、3 ステージあとのボスを倒す、というのがゲームの目的だ。

要は、ドミニオンのデッキ構築を軸に、シングルプレイのために敵のアクションを開示した非対称ゲームなのだが、適度なインフレ感とバランス調整の妙で、先発ながら未だにこれを超える体験のフォロワーは存在しない。

news.denfaminicogamer.jp

今なら Nintendo Switch でも買えるぞ!

Factorio

store.steampowered.com

プログラマなら怠惰を求めて日々の作業の自動化に勤勉になるべきである。プログラマでなくともこれを体験できるのが、Factorio だと思う。

Factorio のゲーム紹介をパッと見た感じは Minecraft の工業化 MOD を彷彿とさせるが、その本質は各生産物の自動化のための生産ライン構築、そして組み上げたラインのそのボトルネックの特定と改善のイテレーションにある。

Factorio をプレーしたプレイヤーは、「作ったライン(プログラム)の遅い箇所を特定して修正する」を自然と行うようになる。プレーが進むと、リファクタリングのためのバッファを持った設計と、障害に強い冗長化までも行おうとする。これは日々プログラマがやっていることに近い。

逆に、プログラマがこれをやると反応が2つに分かれる。「仕事の楽しい部分だけやれて楽しい」か、「なぜ仕事でやってることをゲームでもやらないといけないんだ」、この2つ。

以前、これをマルチプレーでやったことがあるが、「全体としては忙しいつもりなのに最適な人材配置になっていないので改善が追いつかない」とか「局所的に最適化しすぎて別のボトルネックを生んでる」という、まるで仕事でみたような光景を何度も目にした。これは全体を俯瞰できる優秀なリーダーがいると解決できるので、そういう意味でも体験するといいと思う。

自動化の快感を味あわせてくれる傑作。このトレイラーにビビッときたら購入

www.youtube.com

Path of Exile

www.pathofexile.com

store.steampowered.com

2010 年代はハクスラ不毛の年だった。とにかく不毛だった。期待された Diablo 3 は呪われた子だった。Diablo 3 の公式 RMT はゲーム体験を大幅にショートカットすることでスポイルし、公式 RMT が廃止されて以降も、結局エンドコンテンツのセット装備によるビルドの少なさはハクスラ廃人達を遠ざけた。 思うに、 Diablo3 はカジュアルすぎたのだと思う。一部の人々は Diablo2 に帰っていき、一部は Titan Quest や GrimDawn といったシングルプレイの模倣に流れた。

ハクスラローグライクという言葉のうち、ランダム性の高いトレジャーハントという成分だけを抽出されてローグライクという言葉が拡張されたが、俺達がやりたいのは結局、 Diablo2 だった。しかし Diablo2 も人が減り、耐用年数が過ぎようとしている。

このハクスラ冬の時代の「避難所」として選ばれたゲームの一つが、 Path of Exile だ。このニュージーランド産のやたらと画面が暗いこのゲームは、Diablo 3 よりも Diablo 2 にプレー体験が近く、大量のモンスターを自分が考えた最強のビルドでなぎ倒す体験はやはり爽快で、これを求めていた、という感がある。

ビルドシステムも奥深く、特徴的なのは FF10 のスフィア盤を彷彿とさせる巨大なスキルツリーだろう。ここでパッシブスキルを獲得し、アイテムに嵌め込んだスキルジェムのアクティブスキルを発動する。アイテムにはベースの品質、レアリティ、ランダムなマジックアイテムとしての prefix, affix, スキルスロット、スロットのリンクがあり、リンクするスロットにスキルジェムとサポートジェムを嵌め込んで、様々な効果を付与する、といったもの。

とはいえ、ハクスラの常として、同じキャラをやるのは、最終的に同じボタンを同じ順序で押すことになるので飽きてしまう。これらの対策として常設のリーグとは別に、Diablo2 のラダーシステムと同じくシーズン性を採用しており、およそ3ヶ月毎にキャラクターが常設リーグに移動させられ、全員が対等な条件で次のリーグが始まる。シーズンごとに前のシーズンの流行を反映して、ゲームバランスが再調整される。

ハクスラもののゲームの悪い癖として、異なる難易度で同じゲームを何周もさせられるといった点があるが、このゲームではそれも改善されていて、一周終わるとエンドコンテンツに突入する。そのため作業感も可能な限り廃されている。

日本語化はないが、ハクスラのシナリオなんて大して重要ではないので、 Diablo 2 が恋しい人、Diablo 3 が物足りなかった人にプレーしてもらいたい。(中国語対応は終わっているので、マルチバイト対応は終わっているはずなので、ずっと待っているのだが…)

スプラトゥーン

www.nintendo.co.jp

自分のスプラトゥーンとの戦いは、酔いとの戦いだった。

TPS とはいえ、シューター慣れしていない自分には、スプラトゥーンのゲームスピードは速すぎた。まず WiiU のジャイロ操作をオフにして、エイムが比較的不要なローラーでゲームに慣れ、B+で行き詰まりを感じた頃に ジャイロ操作を有効にしてシューターを訓練して S まで上がり、その後プライベートな部屋で友人たちに立ち回りを詰められ甘い動きを反省して、そうしてようやく S+まで上がった。

ゲームシーンが固まっていない初期にやれたのが良かったのだと思う。自分は元々シングルプレイのゲームばかりやるタイプで、対人ゲームはあまりやらないのだが、スプラトゥーンはそういう人間を受け入れる間口の広さがあったように思う。

一番の問題は、S+ に辿り着くまでに 1400 時間掛かったこと。

ペルソナ 5

persona5.jp

自分が中学生の頃、FF10 をリアルタイムでやったときには、こんなゲームが PS2 でいっぱい出るものだと思っていた。残念ながら、PS2RPG は、FF10がピークだった。

JRPG は死んだ。少なくともゼロ年代末には一度死んでいる。オープンワールド全盛期に自由度が低い JRPG は批判のやり玉になりやすく、その批判はFF13で頂点に達した。

グラフィックも時代遅れだった。リアル志向な欧米のゲームと違い、漫画的演出に端を発するJRPGは次世代機の進化と噛み合わなくなった。むしろリアルな体と漫画的な演出のちぐはぐさが強調されてしまう結果になり、その不調和はPS2後期のゼノサーガや、PS3スターオーシャン5 でピークに達していたと思う。

過激なオープンワールドのムーブメントも一周し、そういった人々が冷静になった頃に出たJPRGがペルソナ5だった。ペルソナ5は、ティーン・エイジャーの大人への反発をメインテーマに据えた、JRPGらしいJRPGだが、ターン制、漫画的演出といったJRPG特有の古臭いと思われていた要素を消し去るのではなく、より洗練させることで、次のステージに達した。

https://www.famitsu.com/news/201711/13145540.html

ただし文句はあって、完全版であるところの P5R が、DLC でもなく追加差分がほとんどない状態でフルプライスで購入させられたのは、お布施にしても限度があると思う。アトラスは完全版商法が常態化しているが、せめて DLC にしてくれないと納得感がない。

おわり

みんなも自分だけのn本を書いてほしい

プログラミングを学ぶにあたって詰まったことと、そこから学んだこと

toyokeizai.net

satoru-takeuchi.hatenablog.com

全然レイヤーが違うが、自分が何に悩んで、どういう風に理解したか、思い出しながら書き出してみる。

プログラミング歴

20歳からなので、現時点で10年ぐらいだが、中学生の時ちょっと触ったことがあった。

学習過程で詰まったこと

VBA: 最初の体験

  • 変数の概念。同じシンボルの中身が、代入が実行されたときの時系列で変化する、という概念が掴めなかった。後に再代入禁止の関数型言語を知って、やっぱそっちのが自然に感じる人もいるよね、と腑に落ちた。
  • 関数と引数の概念。プログラムは上から下に流れるものと理解していたので、その上下の外に処理を追い出す必要性がわからなかった。関数呼び出し側と関数定義側の引数の名前が違っていいことに混乱した。一定以上の規模のコードを書くことで理解できたと思う。

ループや if はすんなり理解できたが関数に手こずった。

Java: 大学の授業

  • ジェネリクスの概念: そもそも <T> の構文が難しく、構文上どこで何のスコープが何の型に有効になってるのか、まるでわからなかった。最初はたぶんデータ構造とアルゴリズムの教本の、ソートアルゴリズムジェネリクス対応しましょう、というやつだったと思うが、自分で書いたコードでジェネリクスが必要になるまで、ジェネリクスの必要性を理解できなかったように思う。
  • 標準ライブラリのデザインパターン: 特に Java の標準ライブラリで頻出するファクトリーパターンで、なぜこんなややこしい手続きが必要なのか理解できないものが多かった。
  • リスナー: Java6 の時代なので、Lambda や高階関数がなく、関数参照の扱いが難しかった

動くがAPIデザインが理解できない。こんな複雑な必要はないだろ、と思っていた気がする。

Python (2 系) 半年〜

  • 文字列のエンコーディングの概念: 主に python 2 系が悪いのだが、 ascii, sjis, unicode, utf8 の変換が、かなりややこしかった。今でも python の文字列の扱いは苦手意識がある。
  • パッケージマネージャの概念: 標準ライブラリ以外にライブラリがある、という発想が最初なかった。当時使われていた easy_install の出来が悪いのもあり、ポータブルな開発環境を作れなかった。そして今でも python のポータブルな環境構築は難しい。(自分は pyenv/pipenv を使ってるが、どうも主流になりそうにない…)

Python でプログラミングの基礎を覚えて、基本的な処理を不自由なくかけるようになったが、就職活動をやる必要があった当時、仕事がまったくなかったので、 JavaScript というか当時出たばかりの Node.js に手を出した。

JavaScript (Node.js) 2年目〜

  • 非同期の概念: この時点でもまだコードは上から下に読み下すもの、という意識があったので、読み下した順に上から時系列に実行されない非同期コールバックという概念を掴むのに時間が掛かった。
  • 名前空間の概念: window に紐づくグローバル変数と、レキシカルなスコープで宣言されたものにアクセスできる、というのに時間が掛かった。上の非同期のスコープの概念と合わさって、かなり理解に時間を要した記憶がある。
  • Promise: 非同期コールバックのプログラミングパターンが「処理の継続」なら、 Promise のは「いずれ解決される値のチェーン」と言えるが、そこで生まれるプログラミングの仕方の変化に対応するのに時間が掛かった。 また、 Promise は遅延以外に暗に例外も扱ってるのが話をややこしくしていると思う。 他の言語で言う Either と Future が混ざっている。

学んだこと

常に小さいプロジェクトを作って素振りする

仕事で書くコードは、いつだって現実と戦わねばならない。どんなに理想的な目標を掲げるエンジニアが設計していても、必ず経年劣化や、止むに止まれぬ事情で、技術的な負債がある。

そのような環境では、既存のコードの「重み」がノイズになってしまう。だから、新しいライブラリを試すときは、ノイズが少ない小さな環境で素振りをする。そしてライブラリが達成する本質的な課題や、その上で発生する別の課題を理解する。

自分はGitHubで気になったライブラリは必ず小さなリポジトリで素振りして評価するように心がけている。いきなり仕事のプロダクトに突っ込むことはしない。

仕事と同じスタックで、趣味のプロダクトを作るのは、とても勉強になるので、誰にとってもおすすめ。

静的型付け・オブジェクト指向の必要性

Java の過剰な抽象度とそれによる手数の多さから、自分はうんざりして Python にいったのだが、そのときに自分が書いたプログラムが自分の手足のように動く感覚、万能感を感じた。そしてパッケージマネージャからのインストールを覚えたあたりで、自分の能力が無限に拡張されるような感覚を覚えた。

しかし一定以上の規模のコードを書くには、何かしらルールが必要なのもわかってきた。自分でわかってるつもりになって書いたコードですら、5000行書いたあたりからいつも破綻しはじめる。

静的型付けが常に必須というわけではないが、静的型付けがない大規模環境には、その分テストコードを書く文化だったり、手動テストを多めに要求されたり、ドキュメントを書く文化だったりがある。あるいは、お行儀が良いコードパターンが決まっていて、それをレビューで要求されたりする。その経験を経て、自分は静的型付けってのは非常にコスパがよいドキュメント兼リンターなのだと理解した。(ので自分は TypeScript を使っている)

オブジェクト指向、というかその言語におけるオブジェクト指向デザパタは、デザパタをわかってる人同士のプロトコル伝達のためのツールであって、ゼロからAPIの体系を構築するより、効率的、ということを学んだ。

個人的な持論だが、初学者が Java や C の言語制約を乗り越えながらプログラミングの面白さを感じるのは難しいと思う。どうしてもプログラミングのためのプログラミングに終始しがちなので…

良いコードを書く必要性

良いコードを書くのは自己満足ではない。コード品質は、他のゴールに変換可能なバッファだ。

汚いコードを拡張しながら別の目的を達する汚いコードにするのは困難だが、綺麗なコードを元に汚いコードで目的を実現するのは比較的容易だ。汚いコードを高速化するには困難で、というか必ずリファクタして綺麗なコードを経由してからではないと、高速化というのは困難なことが多い。曲芸的なチューニングは基本的に品質を悪化させる。パフォーマンス目的で汚いコードを書くことはある(とくに数式をコードに落とすケース)が、その場合はコメントでその旨を記述して、かつ他に影響が出ないように影響を局所的に書かないといけない。

そして、自分が書いた経験の中で、良いコードの定義を持たないといけない。自分にとって良いコードとは、可読性があり、モジュール境界が明確で、テストしやすく、ツールによる静的な検査が可能で、拡張性があること。なので、非可逆な操作で名前空間をハックするタイプの DSL は一番やってはいけないこと、と認識している。

そして誤解されがちなのは、良いコードを書く条件は、「そのコードを書くのに掛けた時間とトレードオフ」、ではない。そういう側面も確かにあるが、支配的なのは「今までにコードを書いてきた総時間とのトレードオフ」で、いかによいパターンを事前に知っているか、が決め手になる。

時間があれば三回同じものを実装すると良いものになる、とはそういうことだと思う。

「ハック」の副作用

OSSのライブラリにパッチを当てて運用したり、グローバルなオブジェクトを書き換えたり、そういう所作を「ハッカー的でかっこいい」という見方もある。

しかし、それらの多くのケースで、ライブラリの責務を誤解していたり、単なる無理解でそのようなハックに手を出す人が多い。ハックは目先の問題を解決するが、それがどれぐらい重大な副作用が発生しうるか、想像できる必要がある。

例えば、ある言語のコミッタがある問題を解決するのにGCを止めて処理させていたりしたのを見たが、それはその言語のGCに対して深い理解がないとできないし、おそらく知識があったとしても推奨される解決策ではないだろう。

ライブラリ選定

OSS の時代、最新の流行についていかないことはリスクだと認識している。セキュリティの問題もあるが、ドキュメントの問題が大きい。誰も使ってないライブラリや、古すぎるバージョンで発生した解決策は、誰も知らないし、ドキュメントにも残ってない(ドキュメントは最新版以外残りづらい)。そして自分でコードを読んで、最悪パッチを当てて解決するが、そうするとよりメインラインと乖離してしまう。

フロントエンドの場合は、デザインのトレンドや、デバイスのライフサイクルの問題で、5~10年でUIを作り直すことが多いと思う。しかし技術的な大きなパラダイムが5年おきに変わる。これがフロントエンドの疲弊の原因であると理解している。

しかし、ライブラリが死んで、次のライブラリが出たとき、前のライブラリで発生した問題を踏まないように設計されたものが次のトレンドになる。ので、前世代を知らないと次世代のものを評価できない。エコシステムの変化は連続的であるので、自分がその道のプロを名乗るなら、連続的な変化を学ぶために常に追い続けなければならい。

ライブラリを使わないことも意識すべきだ。あるライブラリを自分の環境に入れたとしても、そのコードの一部しか使わない。その一部のために、全体として負債となる可能性があるライブラリなら、可能なら避けたほうが良い。「確かに目的に沿うが解決のアプローチがそもそも間違っていて他に誰も使ってないマイナーなライブラリを採用して後に負債になってしまう」のが初心者が陥りやすいアンチパターンだと思う。

DRY の守破離

「同じような処理は関数でまとめましょう」と最初は習う。そのとおりだと思う。

しかし同じ関数で異なる目的のものが混ざっていたり、実は無関係なものが一緒になってしまったり、するぐらいなら、DRY にしないほうがいいケースもある。

DRYのアンチパターンは、コードをグルーピングして抽出する際に、モジュール境界を破壊してしまうことだ。例えば、 Model の関数が View を引数にとって、 Model と View 双方に副作用を起こす関数は、確かに処理としてはまとまるかもしれないが、責務としては適切ではない。

モジュール境界面を意識することは、以下にテストしやすいコードを書いてるかというのと同義なので、「今書いてるコードにテストを書くならどうなるだろう」というのは常に意識すると、良いコードを目指しやすい。

クリーンアーキテクチャや DDD の戦略を知ることは、モジュール境界を意識させてくれる。それらを常に採用するべきとは言わないが、知っておくことは価値がある。

おわり

みんなも何に詰まったか、書いてみてください

十三機兵防衛圏感想 - ネタバレあり

とてもよかった。とにかくSFオタクが好きそうなものが全部入りで、満足感が高い。

以下ネタバレ込み。


全体として性善説のストーリーで、人は後天的にどんな人間にでもなれる、ということを描いていたように思う。主人公たち(のオリジナル)はそれぞれに難があり、人類を滅ぼした上に探査船内部で自滅したが、自分たちのオリジナルの思考やDNAに縛られず、自分たちの決断によって物語を解決に導いた、という風に自分は受け取った。解釈は色々ありそう。

森村千尋、東雲涼子、井田は物語的には大戦犯だが、結局生まれ直した彼らは罪はないわけで、誰もその罪を問おうともしない。そこが今までのループものと比べて「宿命」感が薄く、新鮮に感じた。

こういう教訓的な解釈とは別に、単に惑星探査、宇宙植民、疑似ループ、ロボットと、やりたいことをやっただけ、という感じも強く、非常にSF的なフェティシズムを感じた。

核心

作中で表現されないものもあるが(主に2188井田が不明)、ほぼ解決する。

ややこしいのは、起点となる2188年、ループ軸、セクター軸、そしてセクター0による模擬人格によるループの、何周目の誰が、何を目指していたか、という部分。

最終的なゴールは、植民船のテラフォーミング完了後の、新人類の人格育成プログラムに悪意あるプログラムが仕込まれ、人格育成プログラムが完了しないようにループするようになってしまった世界から脱出。

森村千尋が計画し、沖野が脆弱性を仕込み、東雲涼子が悪意を持って改造し、最終的に和泉(二週前)がそのバグを利用して、ユニバーサルコントロールを危機回避プログラムを強制起動するイージス作戦は成功する。

結果的に作中の大部分が沖野の自作自演で、自分で脆弱性を仕込んで、自分でそれをハッキングして物語を解決に導いた。

非常に複雑に見える割に、物語のコアとなる設定は非常にシンプル。それが良い。

ゲームパート

面白くないわけではないのだが、物語パートが面白すぎて、それをブロックする要素に見えなくなってしまった。結局物語を先にすすめることを優先して、最低難易度でクリアしてしまった。

しかし、戦闘があることで、物語の重みが出たのも事実で、時間に余裕があったなら最高難易度で苦しんで没入したかったと思う。

お気に入り

主に沖野くん。

東雲涼子のメンヘラ具合も中々いい…。周囲が悪意をもって東雲涼子を騙そうとしてるのではなく、東雲涼子が真実を受け入れられずに記憶を失ってしまう、というのがとてもよい。悪意がない。

それと焼きそばパン

最後に

この手の作品がたくさん出てほしいので売れてほしい!!!!!!!!!

vscode の web build を netlify にデプロイする + ファイルシステムを永続化する

年末年始の時間を使って実験していたこと。

https://i.gyazo.com/eb57785057b3d998ac2aa59a7904a009.png

tl;dr

vscode をカスタマイズして静的サイトとしてデプロイしたい。やった。公式にない永続化層も作った。

できた。ここで試せる。 https://mizchi-vscode-playground.netlify.com/

やりたかったこと

フロントエンドにまつわるものはフロントエンドで作業を完結したい。なので vscode がブラウザで動いてほしい。

vscode をカスタマイズしたものを各自が自由にデプロイできると、様々な可能性がある。インストールの手間を省いたプログラミング教育用のツールだったり、専用の開発環境だったり、その他諸々。

問題

この用途で期待していた vscode online が使いづらかった。MS のアカウントを要求されたり、Docker コンテナの Enviroment を作ったりする必要があり、面倒だった。そもそもリモートにサーバーがある以上、応答性に難があり、使いづらい。

monaco-editor や vscode web(vscode をクローンして yarn web でビルドできる版)を読む限り、サーバーがなくともほぼフロントエンドで完結することがわかった。

やったこと

vscode を fork して web-standalon ディレクトリを切ってそこで作業している。本体のコードに手を入れてないので、本体への追従は容易なはず。

https://github.com/mizchi/vscode/pull/1 で永続化層を実装した。

というわけで、ここで試せる。 https://mizchi-vscode-playground.netlify.com/

注意: 初回起動に 3 分ぐらいかかる。二回目以降は ServiceWorker でキャッシュしてるので、10 秒ぐらい。

vscode の本家に PR を出したいが、vscode の一般的なユースケースが外れるので、出すだけ出して、こういう路線はありなのか、お伺いを立てたい。

自分で試したい人は https://github.com/mizchi/vscode/tree/master/web-standalone を参考にガチャガチャやれば動くと思う。動かなかったら PR 送ってください。

実装できたもの

  • js, ts, css, json, html, markdown のハイライト
  • ブラウザストレージへの永続化

課題: 今後やりたいこと

  • 初期化が遅い。 理由はわかっていて、vscode は electron で起動すること前提に、細かなファイルを 1500~3000 個ほど AMD でロードする。それぞれは数kbだが、依存の依存の…深い依存があり、その深さだけネットワークを往復するので、時間がかかる。
    • webpack でバンドルしようとしたが、vscode-loader はかなり特殊なローダーになっていて、webpack でそれを再現するのが困難
    • 今度ブラウザに採用されるという webbundle を試せないか考えている。ネットワークを仮想化して束ねて、単一ファイルにできるので。 https://web.dev/web-bundles/
  • 永続化層の実装が雑で効率的でない。とりあえず全部インメモリに乗せて、ファイル読み込みにフックしている。
  • まだ各言語の補完サーバーが動いていない。ここは単に自分がエクステンション読み込みの相対パス解決をうまく動かせてないだけなので、すぐできるはず。

2020 年、 React 軸で学ぶべき技術

なぜ仮想 DOM という概念が俺達の魂を震えさせるのか - Qiita から 5 年経ち、 仮想 DOM を備えた React やそれを採用した Vue や他のライブラリも市民権を得たように思います。

有用な技術が市民権を得る、というのはエコシステムが花開くことでもあります。新しいプロダクトを作る際の技術選定において、 TypeScript + React が常に正解というわけではないですが、このスタックはかなり強力だという手応えがあります。

このスタックは得意のウェブフロントエンドは勿論、それ以外もとりあえず 80 点ぐらいの品質でプロトタイピングできる、というようなエコシステムになってきたような肌感があります。

モダンフロントエンドだと TypeScript と Webpack は採用しているのを前提として、本記事では React を軸にその技術を活かすために、次の 6 個の技術を紹介します。

  • Next.js
  • Preact
  • Workbox
  • Firebase
  • Netlify
  • ReactNative

Next.js

https://nextjs.org/

当初は SSR が可能なウェブアプリケーションフレームワークという触れ込みでしたが、静的サイト生成が後に追加されました。これによって、パフォーマンス要件によって「柔軟性のある SSR フレームワーク」もしくは「運用が容易な静的サイト」を柔軟に切り替えられるようになりました。

去年ついにパラメータ付きのダイナミックルーティングの対応が追加されたことで、プロダクション品質のアプリケーションを現実的に開発可能になったように思います。経験上、フレームワークの選定過程で、ここがブロッキングになることが多かったので…

https://github.com/zeit/next.js#dynamic-routes-support

実際には Next.js を使って本気で開発すると、SSR する技術スタック(style-components/apollo等) に合わせてプロジェクトごとにかなりのカスタマイズが必要なのですが、現状かなり投資対効果が高いフレームワークだと思います。

Preact

https://github.com/preactjs/preact

3kb の React サブセットのフレームワークです。React 自体はやや富豪的なサイズのライブラリで、それが基幹となってる SPA や Next.js のような環境以外では採用をためらってしまうところがあるのですが、 preact は軽量でバンドルサイズに悪影響を及ぼすことなく、どんな環境でも採用可能です。 React エンジニアなら選択肢として持っておきたい技術ですね。

作者の @developit 氏が Google の DevRel で、 PWA のパフォーマンスの文脈でよく採用されており、 Google の支援が厚いのも特長です。

軽量な分、細かい最適化や、 React の Dev Mode のような丁寧な Warning はないのですが、 「React はこう動くから preact もこう動くはず」という期待にほぼ応えてくれます。

preact 10 系になってから hooks 対応が進み、自分はほぼ不満なく使えています。最近ついに Suspense に対応しました。

Workbox

https://developers.google.com/web/tools/workbox

ServiceWorker のキャッシュを扱うスクリプトを生成してくれるツールです。 Service Worker は合法 MITM のような技術なので、無限の可能性があるのですが、 IE が死ぬまでは透過的にキャッシュを効率よく管理するもの、といった位置づけを変えることは難しいです。

現状の ServiceWorker のベストプラクティスを Google が実装したのが、 Workbox です。現実には workbox-webpack-plugin を使うことになると思います。

https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin

ただ、それがどのように動いているかを知らないと、思わぬミスをやらかすことがあるかもしれません。Workbox のキャッシュの取り扱いについてのストラテジー、とくにデフォルトの stale-while-revalidate については知っておいたほうがいいです。

https://developers.google.com/web/tools/workbox/modules/workbox-strategies

(つまりはキャッシュを優先して裏で取りに行くから、一回は必ず古いキャッシュを見ちゃうよ、ということです)

Firebase

https://firebase.google.com/docs?hl=ja

Firebase 、といってもオリジナルの Realtime Database しかなかった時代から時間が経ち、パッケージの詰め合わせといった様を呈しています。ここでは Hosting, Authentication, Firestore, Firebase Function を紹介します。

Firebase Hosting

静的サイトホスティング機能です。CDN 上に静的アセットが展開され、 firebase rules の rewrite ルールでリダイレクトしたり、リソースのアクセスのセキュリティ保護を書けたりできます。ドメインを紐付けることもできます。

自分は素朴なサイトは netlify を使うことが多いのですが、ドメインに基づいた認証系の機能を使うなら、Firebase Hosting を検討します。

Firebase Authentication

Google, Facebook, Twitter, Github などの各種トークンを渡すことで OAuth の認証系をさっくり実装できます。(普通の email + password の認証の実装もできます)

ウェブアプリケーションの開発において初心者上級者問わず認証系は手こずるところですが、Firebase Authentication の開発体験は最高で、とりあえず何か新規サービスを作る際はこれだけ体験してほしいところです。ロジックが少なく、ログインさせるのが主のサイトなら、ほぼこれだけで実装が終わります。

Firestore

Firebase 環境の主流なデータベースです。が、かなりピーキーな性能です。MongoDB のような ドキュメント指向 DB に、 Websocket 経由の Subscription が付属している、というものです。このリアルタイム特性を活かせるアプリケーションは限られていて、そして雑に使うとお高く…といった感じで、扱いが難しいです。

フル Read & Write 権限のテストモードで本番デプロイする人が後を立たず、過去何度も重大なセキュリティインシデントを引き起こしており、正直なところ、セキュリティ意識が足りないプログラミング初心者は、Firestore の使用を避けたほうがいい、と自分は思います。 最初は Cloud Function 経由で普通の RDBMSCRUD を実装したほうがいいでしょう。

Firebase Function (on CloudRun)

Firebase 用の FaaS です。中身は GCP Cloud Function です。Node, Python, Go などのコンテナを選べます。

で、最近追加された機能なのですが(厳密には Firebase Function ではないのですが) GCP CloudRun に対応しました。任意なコンテナをデプロイしてスケールさせることができます。

https://firebase.google.com/docs/hosting/cloud-run

GCP CloudRun は要は GCP Managed Knative、つまり k8s なので、可用性を求められたら 将来的に GKE に載せ替えることができます。

将来的に、と書いたのは「現時点で、Firebase Hosting は Cloud Run on GKE との統合をサポートしていません。」という但し書きがあるからです…

Netlify

https://www.netlify.com/

Firebase は何でも揃っていて便利なのですが、それがちょっと鬱陶しいこともあります。

静的サイトのデプロイ先として、小さな静的ウェブサイトを作った時に便利なのが netlify で、npm i -g netlify-cli して netlify deploy -d public --prod で指定したディレクトリを netlify にアップロードすることができます。(要 netlify へのログイン)

デプロイした静的サイトは CDN 上に展開されるので、高速です。また、ビルド毎にハッシュ付きの URL が生成され、デプロイ ID がわかっていれば、その時点のものにアクセスできます。

本格的なものではないのですが、 Firebase Function のような FaaS もついています。中身は AWS Lambda で、無料枠でも次のコンテナが使えます。

us-east-1 AWS Lambda region
1024MB of memory
10 second execution limit

https://docs.netlify.com/functions/overview/

単機能なので、取り回しがよく、自分はプロトタイプや実験作を netlify で実装してしまうことが多いです。本格的なものはその後 firabase に移すことを検討する、といった感じですね。

ReactNative

https://facebook.github.io/react-native/

React Native が常に優秀な選択肢であるとは限りません。それでも React が書ける人間ならば、自分の手持ちの弾でモバイルアプリケーションを作れる、というのを意識しておいたほうがいいでしょう。

プラットフォームごとの最新の API を使いたい、デバイス固有 API を使いたい、限界までパフォーマンスを絞りきって UX に還元したい、専用のネイティブプラグインを使いたい、そういう場合は ReactNative を選ぶべきではないです。逆に言えば、それ以外の状況では常に選択肢となります。

ReactNative と Firebase と合わせて、「貧者の選択肢」であって、開発リソースが潤沢な場合は、あえて選ぶ必要はありません。ただ、自分が作りたいものが Firebase + ReactNative + Expo の技術制約を満たすとき、小さな開発リソースで大手プレーヤーと張り合える、数少ない技術的な選択肢の一つです。

https://expo.io/

個人的に ReactNative を採用できるかどうかは、 Expo のネイティブプラグインを使わない、という技術制約を満たすかどうかだと思っています。 Expo を使う限り、 ReactNative で高い生産性を享受できます。

近年、日本国内においては、 Vue と React が同じようなポジションになったように感じているのですが、両者を比べたとき、 React の優位は ReactNative があることだと思っています。個人的な願望として、ReactNative Web がもっと使い心地が良ければこちらにスキルを振っていいと思っていたのですが、そこに関しては現状厳しいものがあります…。

おわり

僕がフロントエンドをやり始めた 2013 年はまだフロントエンドエンジニアという職種が言葉として認知されてるかどうか怪しい、というレベルだったのですが、今のウェブ業界はフロントエンド技術は花形で、誰も彼もがフロントエンドのフレームワークなにか一つ、もしくはAWSかGKE、そうじゃない場合はMLやってる、というような時代になった気がします。

フロントエンドはインフラと違って独習にお金があまり掛からないので、入門に適したジャンルであり、プログラミングスクールなどでも最初に教わるテーマに選ばれやすいのですが、そこから一歩踏み出して自分の技術を差別化するのに Firebase からの GCP や ReactNative + Firebase からのモバイルアプリケーションは良いテーマになるんじゃないでしょうか。

かなり個人の主観によった選定なのですが、次に何の技術を選ぶか助けになれば幸いです。