Diary of a Perpetual Student

Perpetual Student: A person who remains at university far beyond the normal period

技術的なアウトプットに疲弊したので振り返る

2022年は技術的なエントリをそれなりの数書いてきた。特に12月は計10本のエントリを出し、まだ世に出せていないネタもたくさんあるという状況である。

ところが、当人の感覚としては暖簾に腕押しだなあと思っている。ということでちゃんと振り返ってみることにする。

stats

2022年で一番ブクマが多かった記事はblog.arthur1.devである。

他の記事はこの半数にも満たない、というか、片手で数えられるブクマ数でさえありがたい、という状況である。

書くという行為によって自分自身の理解が確かなものになることに意義は感じているものの、せっかく書いているのだから多くの人に読んでほしいし、それが読者のためになればなお良いと思っている。

もっとシビアに言ってしまうと、書いても読んでもらえない状況がずっと続くならいつか自分は筆を取るのをやめてしまうだろうという懸念がある。モチベーション維持のために今のうちに何とかしたい。

この現況についてはいろんな仮説を立てている。

仮説

ボトムアップで描かれた記事はとっつきにくい?

自分は普段何かを説明するときに、全てを理解してもらうために0から話し始めることが多い。これは論文書きの仕草から来ている。論理の飛躍があった瞬間にその論述の信頼性は大きく下がってしまう。

どんどん事実が提示され最終的に主題に辿り着いていくスタイルだと、文章が長くなり、読み物として読みづらいものになるのかなと思う。

小学生のうちは円周率を魔法の数字 3.14 として考えるように、fundamental な部分の厳密性をあえて欠く、という選択肢も考えるべきである。一番伝えたいメッセージを決めた上でメリハリをつけて説明量を調節したい。他の文献に譲る、記事を複数に分ける、という素朴な工夫ももっとできるはずだ。

ネタがニッチすぎる?

選んでいるネタがニッチすぎて需要がないのかなとも思う。前項と関連して、細かすぎるネタを選んでいるからこそその説明にかかる時間が長くなってしまい、ボトムアップで説明されたむやみに重厚な、でも需要に乏しい記事ができてしまうのかもしれない。

逆に、自分が当たり前のように知っていた知識を他の人がエントリにするとバズっている、という経験が何度かあった。哺乳類の自分にとっては「陸上での呼吸の仕方」を共有してもしょうがないと思っているのだが、実は地球には魚類もたくさんいて「知らなかった、すごい!」という反応をする、といった具合である。

現在あるセミナーへの登壇準備を進めていて話す内容を考えているところなのだが、こういう仮説を立てている自分として一般受けしそうなソフトスキル寄りの話に逃げたい、というバイアスが掛かるようになってしまった。

掴みが弱い?

エントリを読む/読まないを選択するときに、以下の情報を参考にするだろう:

  • タイトル
  • ogp 画像
  • 本文の最初の数行

ここでのアピール力が足りないのではと思っている。

タイトルに関してはここ最近ある程度気を使っていて、人間の感性に添った表現を心がけている。もちろん、昨今の YouTube のようなサムネ詐欺はやりたくないという美学はある。

存在感がない?

自分の Web エンジニアリング界隈での存在感は 0 に近い。社のエンジニアたちを見ているとそのあたりすごいなと思う。

現在の Web というプラットフォームはスケールフリーなネットワーク(次数の分布が指数関数)になっていて、ごく少数のノードが大きな影響力を持っている。これが Memex 構想を提唱した Vannever Bush が望んだ未来であろうか(反語)と思うこともある。Web が好きだからこそ、 hypertext の一実装でありながら、文書自体の関連性(つまりエッジの中身)よりもネットワークの構造自体が支配的に働いたり、メディアの持ち主が消してしまうと有益な情報が失われてしまったりする Web を憎んでいる。

愚痴はさておき、世の中を変えるほどの力はないのでなんとか順応して食い込んでいくしかない。今のアウトプットを地道に続けたらうまくいく、という単純なものではないことだけはわかっている。

2023年のアウトプット

ということで、2023年は以下のアクションを取ってみることにする。

  • もっと他人の記事を読む
    • 内容だけでなく、自分が面白いと思った記事の伝え方を観察する
  • 全てを自分が説明せず、適切に他の記事に譲る
    • このエントリが役に立った、という情報自体が有益であるはずだ

続き:

blog.arthur1.dev

ent + gqlgen で怠惰に GraphQL API を作る

この記事ははてなエンジニア Advent Calendar 2022 の 2023年1月4日の記事です。


Go 言語の ORM である ent をご存知でしょうか? ent はコード生成を用いて型安全に RDB のクエリを記述できる ORM です。エンティティ間の関係を Edge として定義するのが特色となっており、その結果、簡単にグラフ構造データのスキーマモデリングができます。

entgo.io

そんな ent には GraphQL インテグレーションという機能があります。これを使うと、ent のスキーマ定義を用いて簡単に RDB をデータストアとした GraphQL API サーバを作れるのでご紹介します。

ent GraphQL インテグレーションの仕組み

Go 言語で GraphQL API を開発するとき、最初に名前が上がるのが gqlgen というライブラリでしょう。GraphQL のスキーマファイルを食わせてやると、あとは resolver を手で書くだけの状態になった GraphQL API のコードが生成される、というものです。

gqlgen.com

ent によるコード生成時に SchemaGenerator というものを用いると、同時に GraphQL の スキーマファイル(データやクエリの型情報が入っている)を書き出すことができます。このファイルを gqlgen に食わせてやると、 resolver の雛形が生成されます。この未実装部分に ent で生成した CRUD API を利用して実装を埋め込んでいきます。すると、あっという間に GraphQL API の出来上がりです。

// Decks is the resolver for the decks field.
func (r *queryResolver) Decks(ctx context.Context) ([]*ent.Deck, error) {
    panic(fmt.Errorf("not implemented: Decks - decks"))
    // ここの panic を消して、代わりに ent で生成される ORM Client を使った実装を書く
    // return r.Client.Deck.Query().All(ctx)
}

雑多な説明になってしまいましたが、簡単にいうと以下のコーディングだけで GraphQL API が作れます。便利

  • ent のスキーマ定義ファイル
  • ent が吐き出した CRUD API を利用した Resolver の実装(関数を呼び出して return するだけ)

登場人物と関係図

以下のように generate.go を用意すると、この一連のコード生成を go generate . 一発で行えます。

//go:generate go run -mod=mod ./ent/entc.go
//go:generate go run -mod=mod github.com/99designs/gqlgen

参考

詳しい説明は今回はしません。気が向いたら手順をエントリにまとめていこうと思います。

自分が参考にしたのは以下のドキュメントです。

entgo.io

entgo.io

感想

id:arthur-1 の個人開発プロジェクトに活用してみたので、使ってみた感想を述べていきます。

github.com

よかったこと

レールに従っているだけで、DB のスキーマ、ORM のクライアント、そして GraphQL API が簡単に作れるのはとてもよかったです。

GraphQL API が手軽にできてしまうと、フロントエンドの実装に集中することができます。もともとこのアーキテクチャが「面倒な実装は全部サーバサイドにやらせよう」という雰囲気のものですが、その面倒な部分を ent に丸投げできてしまいます。

さらに、できた GraphQL API がオモチャではないのも良いです。Cursor 形式のページネーションにも対応していたり、dataloader を自前で実装しなくても n+1 問題を自然と回避できたりするので、production として使う上で気になるパフォーマンス上の懸念もあまりなさそうです。

0 からサービスを作り上げたいときに GraphQL を活用したいと考えている場合、手早くスタートする方法としてピッタリではないかと思います。

よくなかったこと

これは ent の GraphQL インテグデーションというより ent 本体の問題なのですが、生成されるデータベースのテーブル定義が「マジかよ」という感じでした。

同じ型のエンティティ間の多対多の関係を定義した時に、その関係を保持する中間テーブルのカラム名が、本来想定されたものと入れ替わってしまうという不具合があります。

ent が生成する CRUD API を通してやりとりする場合には問題ありませんが、データベースに初期データを入れてテストしたいときなどに、カラム名が入れ替わっていることに気をつけなければなりません。

この問題は既知ですが、今だに解決されていません。

github.com

migration に atlas を使うと直るかも?

まとめ

GraphQL のエコシステムに乗っかっていくと、リクエストの数やサイズを減らしたり、決まった型がついた状態でデータを fetch できたりと、嬉しいことが多いと思います。一方で、自由に投げられるクエリを処理しなければならないため、サーバの実装はかなり難解なものになっています。

ent の GraphQL インテグレーションを利用すると、すでに定義したエンティティとその間の関係の情報を生かし、自然な形で GraphQL の API サーバを作ることができます。

ささっと GraphQL API を作り、その嬉しさを手早く体感しませんか?というお話でした。


prev: 2023年1月3日分は id:ikesyo さんの 『Production Ready GraphQL』の「Anemic GraphQL」 - いけだや技術ノート でした

next: 2023年1月5日分は id:hogashi さんの aタグで#topにリンクするとページ先頭にスクロールするのは仕様 - hogashi.* です

GitHub Actions の workflow の lint を Github Actions で動かす

GitHub Actions で色々なコードの test や lint を動かしていると思います。

その際に workflow を yml で定義するのですが、この workflow ファイルはちゃんとチェックしてますか?

  • 「見よう見まねで yml を書いて push したけど、キー名が間違っていて動かなかった」
  • ::set-output などの deprecated な機能を今更使ってしまった」

こんな経験はありませんか?

Github Actions に関するその問題、Github Actions を使えば解決できます!

解決策

actionlint という Github Actions の workflow ファイルをチェックしてくれる lint ツールがあります。

github.com

こいつを Github Actions 上で動かすだけです。

動作させてみた例を以下に載せておきます。

github.com

deprecated な機能を利用して怒られた例

やり方

以下のように 2 つのファイルを用意して push しましょう。

.github/workflows/ci-actions.yml

on:
  push:
    paths:
      - .github/workflows/*.yml
      - .github/actionlint.yml
      - .github/actionlint-matcher.json

name: actionlint
jobs:
  actionlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install actionlint
        shell: bash
        run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
      - name: Add problem matcher
        run: echo "::add-matcher::.github/actionlint-matcher.json"
      - name: run actionlint
        run: ./actionlint
        shell: bash

.github/actionlint-matcher.json

以下からコピーして配置してください。

github.com

{
  "problemMatcher": [
    {
      "owner": "actionlint",
      "pattern": [
        {
          "regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$",
          "file": 1,
          "line": 2,
          "column": 3,
          "message": 4,
          "code": 5
        }
      ]
    }
  ]
}

解説

この workflow は以下のような流れで実行されます。

  1. github から actionlint を install するコマンドを実行
  2. actionlint の出力から annotation (この行がエラーだよという表示)を作るためのテンプレートを設定する
  3. actionlint を実行する

上級 Tips

手元では検出されないエラーが GHA 上で動かすと検出される

actionlint は手元でもインストール実行できるコマンドで、VSCode の拡張として使っている人たちもいるでしょう。このとき、手元環境だとエラーが検出されないのに、Github Actions 上で動かすとエラーが表示されることがあります。

この原因は、shellcheck というコマンドがインストールされているかどうかの差異にあります。

actionlint は、shellcheck がインストールされているなら、run: などで yml 上に書いているシェルスクリプトに対して shellcheck を適用した結果を教えてくれます。

shellcheck は Github Actions の ubuntu-latest runner にデフォルトでインストールされているのに対し、手元環境ではインストールしてない人もいるでしょう。

If you want to enable shellcheck integration, install shellcheck command. Note that shellcheck is pre-installed on Ubuntu worker.

actionlint/usage.md at main · rhysd/actionlint · GitHub より引用)

custom runner や self-hosted runner の名前がエラー扱いになる

基本 runs-on: ubuntu-latest として用意された runner を用いて動かすことが多いですが、大規模なプロジェクトでは custom runner や self-hosted runner を利用している場合もあるでしょう。

このとき、runs-on: hoge のように、デフォルトで用意されていない runner を指定すると、以下のように怒られます。

label "hoge" is unknown. available labels are "windows-latest", "windows-2022", ...

これをエラーとして検出しないようにするには、actionlint の設定ファイルを以下のように設置する必要があります。

.github/actionlint.yml

self-hosted-runner:
  labels:
    - hoge

cf.) actionlint/config.md at main · rhysd/actionlint · GitHub

まとめ

GitHub Actions のチェックが GitHub Actions でできました!!


余談

このエントリは社内でやっている技術勉強会「忘年LT大会」向けのものですが、せっかくなので public な場で書き留めておきました。

id:arthur-1ウロボロス的なものが好きで、はてなエンジニア Advent Calendar に「Advent Calendar の監視をする」というネタで投稿したのですが全くウケませんでした。今回もまた懲りずに同じ過ちを繰り返したわけであります。

blog.arthur1.dev

Mackerel Advent Calendar 2022 完走したので全部読む

Mackerel Advent Calendar 2022 の運営をしておりました、 id:arthur-1 です。この度は、Advent Calendar にご参加いただき、もしくは閲覧していただき、ありがとうございました。

qiita.com

25日分の記事が集まり、最後まで完走することができました。自分が設定したエントリ数の監視もちゃんと動いていました。

blog.arthur1.dev

総括というには素朴なのですが、書いていただいたエントリを読み、個人の感想としてコメントさせていただきます。

※社内・外関係なく統一して敬称をつけさせていただいております

全部読む

Day 1

blog.arthur1.dev

自分のエントリです。単位追加は細かい改修を除けば新卒初仕事だったのですが、自分が想像していた以上に社内外で反響があってよかったです。

Day 2

blog.stenyan.jp

id:stefafafan さんのエントリです。Mackerel はドッグフーディングを売りにしている割には、はてな社内での使い方を最近あまり発信できていないように思うので、ありがたい記事でした。

Day 3

yseto.github.io

yseto さんのエントリです。自分も snmp を喋れるルータを持っているので試してみました。システムメトリックとして投稿されている様子が確認できます。connectivity 監視応用は面白いアイデアですね。

Day 4

tech.buty4649.net

id:buty4649 さんのエントリです。こちらも手元に常時稼働している Raspberry Pi 4 があったので試してみました。残念ながら Mackerel には ℃ 単位がないのですが、メトリックはバッチリ見えてます。

Day 5

k1low.hatenablog.com

id:k1LoW さんのエントリです。コードメトリクス収集ツールのデータストアに Mackerel を追加していただきました。テスト実行時間は徐々に伸びていきがち。それが妥当か判断できるように自分の個人開発でも可視化してみようかなと Todo に加えました。

Day 6

qiita.com

tomotomobooks さんのエントリです。Meraki は持ってないので試せませんでした。書き出しが大変良い話だと Mackerel チームで話題になっていました。メトリックを集めやすい・とっつき易いという面は引き続き伸ばしていきたい!

Day 7

techblog.kayac.com

id:ikeda-masashi さんのエントリです。アラートの重要度は固定されずエラーバジェットによって変動する、確かに!と思いました。アラートのメモを API から編集できる機能は最近のリリースですのでぜひご活用ください。

Day 8

hktngch.hatenablog.com

Mackerel 開発チームのディレクター id:HKtngch さんのエントリです。Mackerel チームの現状の暮らし方が、アジャイルスクラムと違う路線を歩みつつあるのは自分も感じていて、色々な機会で啓蒙していただいています。

Day 9

ryuichi1208.hateblo.jp

id:ryuichi1208 さんのエントリです。自分の個人開発も MySQL を自前で立てて運用しているものがあるので、 MySQLで使用しているメモリが徐々に増え続けているので調べたメモ - 地方エンジニアの学習日記 と合わせて読ませていただきました。バグ修正の contribute もありがとうございました(私がやりとりさせていただきました)。

Day 10

blog.3qe.us

id:Windymelt さんのエントリです。Page Speed Insights 満点取りたい人間としてはぜひ監視したいメトリックです。Scala Native よくわからなくて手元の Apple Silicon Mac で build できなかったので宿題に……

Day 11

c4se.hatenablog.com

id:Kureduki_Maari さんのエントリです。mackerel-agent の plugin を作るための最低要件はこれだけですよという紹介と、例として「生命、宇宙、そして万物についての究極の疑問の答え」をメトリックとして投稿するシェルスクリプトプラグインの作り方を掲載していただきました。

Day 12

techblog.forgevision.com

id:matsuo1017 さんのエントリです。Mackerel の機能のうち、Web コンソールからできることに絞って最新のスクリーンショット付きで紹介していただきました。organization の分け方が色々あるよというのは Mackerel を始める上でとても大切なポイントですね。

Day 13

inommm.hatenablog.com

id:inommm さんのエントリです。画面の解像度が上がるに従ってリニアに負荷が大きくなると思っていたので、面白い情報でした。オーガニゼーションに対して標準でついてくるサービスメトリック数の範囲であれば料金を気にせず色々なものを手軽に可視化できるので、ちょっとした実験にもぜひご活用ください。

Day 14

isekatsukun.hatenablog.com

Mackerel セールスチームのディレクター id:isekatsun さんのエントリです。MSP セールスをやっていた時代の経験から、オンプレ→クラウドへの移行が進み始めた時代に、構築や監視運用のあり方が大きく変わってきた話を語っています。変化を恐れないために Mackerel を選んでもらえるようになりたいし、そのためには Mackerel が変化に対してフィットするプロダクトでなければならないですね。

Day 15

wafuwafu13.hatenadiary.com

id:wafuwafu13 さんのエントリです。mackerel-agent の configtest を機能拡張し、「もしかして、このキーと間違って typo してませんか?」という情報を出すようにしていただきました。その実装の解説をしてくださっています。レーベンシュタイン距離を用いた suggestion では Terraform でも同様にやっているんですね。

Day 16

blog.arthur1.dev

再び自分のエントリです。Telemetry API でログも取得できるので、Lambda 関数で定型のログを出して extension 側で取得することで、実行環境ごとに分かれたカスタムメトリック集計・投稿機能を作れたな〜と今更思っています。

Day 17

dev.classmethod.jp

kidapan さんのエントリです。インターン生に取り組んでもらったホスト一括退役機能をはじめとする Mackerel の 2022 年の主なアップデートを紹介していただきました。来年は、あれもこれも紹介したくなって困ってしまうぐらいにアップデートしていきたいですね。

Day 18

zenn.dev

sogaoh さんのエントリです。CIOps 的な内容で、デプロイと、それに伴って Mackerel による監視にダウンタイムを設定するのを CircleCI 上で同時にやってしまおう、というものでした。デプロイフロー改善に取り組んでいる我々にとって参考になりました。

Day 19

dev.classmethod.jp

cm-watanabeseigo さんのエントリです。カヤックさんが公開している OSS ツール shimesaba を使って、外形監視を SLO モニタリングする、という内容でした。Mackerel 単体で SLO 運用しにくいのも個人的には結構気になりポイントで、まずは我々の運用をアップデートさせないとな、と思っています。

Day 20

blog.stenyan.jp

id:stefafafan さんのエントリです。Github Actions から Mackerel を利用したい時のメジャーなケースがサービスメトリック投稿だと思うので、それだけの機能を持つシンプルな action は使いやすくて良いですね。action のメンテがされず朽ちていくのはあるあるなので、mackerelio の organization でこういったものも維持できると良いのかもしれない。

Day 21

tech.buty4649.net

id:buty4649 さんのエントリです。年末といえば大掃除・棚卸し、ということで、Mackerel に蓄積した情報を用いてインベントリ管理するというネタは 12月にピッタリですね。mackerel-agent を mipsel で動かすのも面白かったです。変わった OS や プロセッサ向けにも簡単に build できるのは Go 製の大きな強みです。

Day 22

genkiroid.github.io

genkiroid さんのエントリです。自分も TOML あんまり知らなくてヘルプ読みながら見よう見まねで書いていたので、なるほどと思いました。実装を知っていると TOML の Parser に渡してるだけなので等価なら大丈夫、となるのですが、それをユーザ全員が知るのは無茶な話ですし……

Day 23

kmuto.hatenablog.com

id:kmuto さんのエントリです。Mackerel CRE として入社して1ヶ月の様子をまとめていただきました。特に、Mackerel の開発合宿に飛び入り参加して作っていただいたデモは発表会で大好評でした。今後ともよろしくお願いします。

Day 24

tukaelu.hatenablog.jp

id:tukaelu さんのエントリです。カスタムダッシュボードにアラート一覧のウィジェットを力技で出すやり方を紹介していただきました。ダッシュボードが「この画面 1ページみたら良い」という存在になるために、公式として提供が必要な機能なのかもしれませんね。

Day 25

mackerel.io

id:wtatsuru さんのエントリです。見られるメトリックはたくさんありますが、パフォーマンスに影響しない下位レイヤーのメトリックに過度に敏感になったり、年々とシステムの利用状況が変化するにも関わらず監視ルールをそのままにしたり、といった悪い例を避け、監視の原則を守っていきたいものです。この思想は RDS だけでなく一般に役立つはずです。

最後に

改めて、Mackerel Advent Calendar 2022 にご参加いただきありがとうございました。

来年もより一層価値提供できるよう頑張りますので、id:arthur-1 と Mackerel をどうぞよろしくお願いします。

買って良かったものランキング 2022

ランキングと銘打っていますが特に順位はつけていません。悪しからず。

ガジェット編

YAMAHA のヘッドセット

軽い!聴こえる音が良い!マイクの音質も良好!ということでおすすめです。長時間つけていてもあまり苦ではないのでリモートワークにピッタリ。廃盤になると嫌なので予備も買っておきたいです。

DellKVM 機能つき 4K モニタ

私物の Windows と業務用の Macbook で USB 機器をいちいち繋ぎかえる必要がなく、入力切り替えに連動して繋ぎ変わるのは最高に便利です。

あと 4K に目が慣れきっていて、フル HD の PC モニタだと文字が読めなくなってしまっています。

家電編

スマートスポットライト

ダクトレールにつけるタイプのやつ。見た目がシンプルで部屋をスタイリッシュに照らせるだけでなく、スマートスピーカーで制御できるので良かったです。

ただし、買うならこれではなく上位機種を選ぶことをおすすめします。上位機種であれば別売りのリモコンからの制御にも対応しています。

アパレル編

PlayStation のパーカー

www.gu-global.com

急遽お泊まりすることになって近くの GU で買ったパーカー。会社の人にめちゃくちゃウケが良かったです。素材が軽めなので春秋におすすめ。

シューズ

www.nike.com

お店で見た瞬間にこれめっちゃカッコ良い!となって買いました。ポップとクールの狭間でありたい。

技術書編

実用 Go言語 ―システム開発の現場で知っておきたいアドバイス

A Tour of Go を一通りやったものの Go 言語の文化に慣れなかった自分が入門する本としては非常に良かったです。色々な topic が雑多に書かれていて少しとっつきにくい印象はあります。

学園祭のWeb開発を語る: 具象編2 開発体験・保守性を投げ捨てる

遠い昔に学園祭の Web 開発をしていた話をするシリーズもの

  1. 具象編1: 講習会と砂場遊びで支える組織
  2. 具象編2: 実際に使っていた技術や開発の仕方について語る ←イマココ
  3. 抽象編: 学園祭の開発部署という組織や、学園祭Webサイトというプロダクトの性質から語る

今回は泥臭い技術の話をしていく。


インフラ

当時はさくらのレンタルサーバで、 PHP でできた Web アプリケーションを動かしていた。レンタルサーバが設けた制約により、言語の選択肢はないに等しかった。

レンタルサーバを脱出して VPS にしようという話も出ていたが、我々の代でそれを行うことはしなかった。インフラ、サーバ管理に関して知識がある人間があまりにも少なかったからである。自分は個人で VPS を借りて遊び倒していたが、それを組織に展開するには運用持続性の面で疑義があった。

サーバは本番環境と開発環境の 2 つがあった。開発環境は、各自が実装したものを動作確認するために気軽に利用されていた。

ローカルの開発環境を用意していたのは自分の学年では自分だけだったと思う。Windows PC 上に XAMPP を立てて動かしていた。Docker は知らない子だった。自分は動的な部分(フォームなど)の開発を任されていたので、ローカル環境がないととてもやってられなかった。

Web アプリケーション

HTML をサーバ上で動的に組み立てて吐き出す、という古来のサーバサイドレンダリングであった。2015,16年というと Vue.js の v1 が出た、ぐらいの世界で、フロントとサーバサイドを分離するという思想は広く浸透していなかった。

フレームワークには FuelPHP を用いていた。なぜこのマイナーフレームワークを選定したかは分からない。昔のサイトがこれでできているから使った、という程度のものである。一応、Laravel が今ほどに人気になるより前の時代ではあった。

基本的な機能は備えていたので、下手なことをしなければ XSS や SQLi を回避できるようにはなっていた。

コードは MVC アーキテクチャで作られていた。後にリッチな View に引きづられて Controller が肥大化することを問題視し、Presenter 層を生やしている。

ちなみにテストは誰も書いていなかった。

git を使わないという選択

今思えば大分大胆なのだが、git は一切使っていなかった。サイト公開まではファイルをローカルの思い思いのエディタ(vim派、SublimeText派、atom派で分かれていた)で編集し、それぞれが本番環境に FTP でアップロードして更新していた。コードレビューなんてものもなかった。

GW には大学に集まって集中して開発を行っていたのだが、その時は衝突しないようにデプロイできる権利カードを物理的に受け渡していた。

ソースコードはサーバ上にあるものがマスタであったので、定期的にバックアップを取って切り戻せるようにはしていた。

バージョン管理を取り入れられなかったのは、やはり持続的にみんなが運用できるかというところに不安があったからだ。

前回講習会の話をしたが、1年間で HTML, CSS, JavaScript, PHP, SQL ... を詰め込むだけで相当頑張っていた。ネットワーク局は「一からでも上級生に教えてもらえるから大丈夫」ということで勧誘をする。技術的に長けているサークルは他にたくさんあるので、元からできる人はむしろ入部してこないのだ。

そこで、お客さんや学生にサイトを届けるという目標に直接関連しないバージョン管理の優先度は落とされることとなった。一応、1年間これで何もインシデントを起こさずにやってこれた。

維持するより建て直す方が楽

学園祭サイトの賞味期限は短い。毎年テーマに合わせたデザインにしているし、企画も毎年異なる。よって、サイトは毎年一から作り直していた。

他人のコードを読むという行為は本当につらい。増して、プロでもない学生のコードであればなおさらである。

また、Web アプリケーションエンジニアなら分かってもらえると思うが、ライブラリやフレームワークのアップデートというのは本当に toil で、積み重なり負債になりやすいものである。

1年に1回、その時の最新のバージョンでモノを作るから、その後は重大なセキュリティに関連しない限り更新しなくて良いね、というスタンスだった。

一度、継続して運用していくという前提で受験生応援サイトというものを開発した。合格体験記をどんどん蓄積していく CMS のようなアプリケーションで、データベースに体験記のレコードを追加すればページが勝手に増えるものであった。

自分がいなくなった後どうなったかというと、きちんと引き継がれることなく放置され、現在は作り変えられて消滅している。引き継ぎ資料としてドキュメントも作ったし、そんなに難解なコードでもなかったと思うが、サイトに新たな記事が追加されることはなかった。

毎年人が入っては消え、3年間で全員入れ替わる組織で、何かを継続して運用するというのは本当に難しいのだ。

ページスピードにこだわる

概ね poor な運用への言い訳になりつつあるので、技術的に頑張っていたこともあるんだよ、という話をする。

我々は Pagespeed Insights (現代で言うと Lighthouse)の得点をすべて 100点にすることに魂を燃やしていた。

例えば jQuery を意地でも使わないためにタブの切り替えやハンバーガーメニューの動作を CSS だけで実装したり、CSS を圧縮してインライン化したり、といったの工夫を行っていた。当時の取り組みを、学生時代の自分がブログに output していたので貼り付けておく(現在非公開)。

CSS だけでタブを実装してパフォーマンス比較する話

CSS インライン化の話

Google Analytics で取れるデータや、 Pagespeed Insights や Lighthouse が指摘してくる事項を眺めて、閲覧者の体験をよくするために何かできるか、ということをよく考えていた。数字が目に見えるものは、目標が明確で取り組みやすい。

まとめ

技術的な取捨選択の判断をメンバーの総意で行えていたことは、振り返ると学生集団としては意外とすごいことかもしれないと思う。明確な理由を持って提案し、多角的に評価して採択・棄却を行うという仕草は、社会人として雇われエンジニアをしている今もかなり役立っている。大学生の4年間というリソース*1は有限ではない。

一方で、いつ何か起きてもおかしくない綱渡り状態だったのは事実である。最近の学園祭サイトは、広告を載せて協賛企業からお金をもらい学園祭開催の資金としているものも多いだろう。企業と書面を交わし契約をしている立場なのだから、 availability にはもう少しシビアになるべきかもしれない。

次回は、具体的なエピソードではなく、現代の Web 開発のトレンドも踏まえた上でもう少し一般論の話をしようと思う。

*1:id:arthur-1 は学部で7年間過ごした