世界を動かす技術を、日本語で。

時間と労力を多く必要とするウェブサイトの作り方

概要

  • 依存関係 に頼りすぎることのリスク
  • フレームワーク選定 のタイミングの重要性
  • ビルドやコンパイル 工程の複雑化による負担増
  • 時間と労力を 浪費する方法 の皮肉的指南
  • 他の人にも 同様のアドバイス を共有する呼びかけ

時間と労力を浪費するWebサイト開発の教訓

  • npm から無差別にパッケージをインストールし、他人のコードへの 依存関係 を最大化

    • 依存関係が 壊れる のは時間の問題
    • 修正できない理由は、 仕組みを理解していない から
    • 依存関係の 置き換え作業 を繰り返すサイクル
  • 必要かどうか 判断する前にフレームワーク を選定

    • フレームワークのアップデート時に 変更点の把握 が必須
    • 学習コスト と運用負担の増大
  • 常にコンパイル工程 を必須化

    • ブラウザで確認するまでに ビルドやトランスパイル が必要な仕組みを導入
    • プロジェクトの 複雑化依存性の増加
    • 実際のWebサイト制作よりも ビルドシステム作業 が中心
  • コードが実際に動作する形 で書くのではなく、 事前処理 を経由する構築方式を推奨

    • 時間と労力 のさらなる消費
  • もし他にも “労力を浪費する”アドバイス があれば、他の開発者と 積極的に共有 すること

まとめ

  • 依存関係やフレームワーク に振り回される開発体験
  • ビルド工程の複雑化 による本質的な作業からの逸脱
  • 時間と労力を浪費する方法 の自虐的ユーモア
  • 他人にも 同様の遠回り を勧める姿勢

Hackerたちの意見

「複雑化のステップ」っていうコンセプト、楽しんだよ。コードが複雑化するまで、変更の結果が見えないんだよね。

ハハ、コンパイルとコンプリケーションの混同が意図的だったかどうかは分からないけど、笑っちゃったよ :D

ここに著者がいる: このスペルミスに気づかなかった。けど、気に入ったからそのままにしておくよ。指摘してくれてありがとう、ハハ!

問題はツールや依存関係じゃなくて、開発者が過剰設計したくなる誘惑だよね。シンプルに保つためのディシプリンが足りないからフレームワークを使っちゃう。コーディングの自己制御って、今や失われた技術なのかな?

これがまさに投稿の内容だと思う。

コードをシンプルに保つために、あえてフレームワークは使わなかったんだ。フレームワークが柔軟性に欠けて、自分がやりたいことができなかったから。

特定のツール、というかエコシステムは、他よりも過剰設計や過剰な期待を助長することが多いよね。

シンプルに保つためのディシプリンが足りないからフレームワークを使っちゃう。自分もスキルを維持するためにフレームワークを使うことがあるよ。特に仕事でそれを実践してないときはね。もしその衝動がなければ、ずっとシンプルに保ってたと思う。自分は本当に得意だから、複雑さが嫌いなんだ。もっと覚えなきゃいけないことが増えるから、その感覚があまり好きじゃない。絶対に必要なときだけ最適化するよ。企業がこの態度を気にすることはないけどね。実際、これがうまくいくのを見たことがある。LLMを使った仕事は迅速で実用的だし、プロトタイプに過ぎないときは、製品化する必要はない。Pythonのコードとよく練られたプロンプトでLLMをつなげるだけで、必要な結果が得られるから。これで数週間ではなく、数日で出荷できるんだ。もちろん、製品化したいなら、追加の作業が必要で、コードをリファクタリングする必要もあるかもしれない。でも、個人的にはそういうことが起こるべきタイミングと場所だと思う。

コーディングの自己制御って、今や失われた技術なのかな? そうだね。多くの人は、何かを動かすためにコードを書くんじゃなくて、楽しむために書いてる。必要なソフトウェアが退屈だったり解決済みだったりすると、例えばCRUDアプリのように、退屈で簡単に作れる言語やフレームワークを選ぶ代わりに、自分にとって面白くするんだ。新しい言語やフレームワーク、デザインパラダイムを学ぶとか、今流行ってるものを追いかけるとかね。多くの新しいソフトウェアは、最初から過剰設計されてる。大企業が自社のk8sクラスターでマイクロサービスを使ってるから、私たちも自分たちのk8sクラスターでマイクロサービスを使うべきだっていうのも、いわゆるカゴ文化だよね。

逆に言うと、WordPressみたいなものはすごく簡単そうに見えるけど、実際にはコードを書く必要もない!でも、Apacheサーバー全体の管理や、クソみたいなデータベースの管理、PHPでのハードコーディング、cronジョブ、クラウドデプロイメント、プラグインやテーマなどの「機能」がほとんど全てセキュリティの脆弱性になってることを心配しなきゃいけないんだよね。ここで避けるべき落とし穴は、メンテナンスの努力が一つのソースに集中してるわけじゃなくて、実際にはたくさんあるってことだと思う!

フレームワークを使う理由としてこれを見たことがない。合理化としては分かるけど、理由としては見たことがない。彼らはコーディングスタンダード以上のものを提供してるよ。

自分で選んだことの一つが、PHPでウェブサイトを作ることなんだ。ゼロから始めるから、サーバーやセットアップ(セキュリティ/docker/podman)、スタック(php/js/css/html)を学ぶ必要があった。限界があるからこそ、色々やらざるを得なかったよ。コードは見た目が悪いし、全体がごちゃごちゃ。URLはnginxのリライトのおかげで見た目はいいけど、ルーティングはできてない。デザインの選択も限界から来ていて、ユーザーデータは扱えない。セキュリティが不安だからね。サイトが立ち上がったら、bootstrapを使ってCSSの基本を学ぼうとする。でも、CSSのやり方を学んだら、全部消したくなるんだ。SQLには問題ないけど、ORMを使うとSQLの知識がすごく見栄え悪くなる。

俺の場合、前のプロジェクトでの痛みを避けるために、あっちこっち行ったり来たりしてる感じかな。フロントエンドのフレームワークとバニラJSの話も同じ。例えば、ORMを使ってると、プロジェクトを維持するうちにその問題が見えてくるから、次のアプリでは生のSQLを使うことにする。でも、それをしばらく維持してると、そのアプローチの落とし穴も見えてきて、なんでそもそもORMが作られたのかがわかる。で、誰かが最新のORMを紹介してくれて、今回は良くなるって言うから使ってみる。そうすると、前回飛びついた生のSQLから救われるんだよね…無限ループだわ。

時には、物事を過剰に設計する方が楽しいこともあるよね。

投稿はもっと愚痴っぽく感じる。著者がプロジェクトかクライアントに対して不満を持ってるみたい。静的なブログでも、純粋なHTMLで書くよりツールを使った方が管理しやすいよ。自分の個人ウェブサイトはsvelteで動いてるんだ。ブログを持つことに決めたとき、すぐにmarkdownからHTMLに変換するソリューションを思いついて、既存のセットアップにいくつかのルートを追加したら、あっという間にブログが立ち上がったよ。いくつかのパッケージに依存してることなんて気にしない。投稿するのは、自分のリポジトリにプッシュするだけで済むから。

あなたは明らかに著者よりもいい人だね。彼らは最初に個人的な経験に基づいていると言ってたけど、私は彼らの言ってることに深く共感する。これは他のプロジェクトやクライアントに対する愚痴ではなく、何十年も個人のウェブサイトを作ってきた人の学びなんだ。過程で何度も自分を責めて、他の人の前でその旅を皮肉っぽく笑い飛ばせるようになったんだ。

自分が書いた個人的なウェブアプリがあって、React 16で、createReactAppを使ってBabelを設定したんだ。やりたい機能のリストがあって、暇な時間に追加しようと思ってたけど、その3つの機能はすっかり放置されちゃった。ここ2年くらいの間、ちょっとした暇な時間を使っても、機能を追加する代わりに、最新の状態にアップデートしようとして2、3時間かけて失敗して、全然進まない。最近の試みでは、LLMのどれかができるか試してみたけど、ダメだった。最初からやり直そうかとも思ったけど、時間がないんだよね。

いつもORMを使って、次の一年はN+1クエリや膨れ上がったジョイン、プロダクションでしか現れない謎のパフォーマンス問題をデバッグする羽目になる。マイグレーションはランダムに失敗するし、スキーマの変更は悪夢だし、チームはSQLの使い方を忘れちゃう。ORMはデータベースを抽象化することを約束するけど、結局問題が起きたときに戦わなきゃいけない別のレイヤーになっちゃうんだよね。

数年前、数年ぶりにフルスタックの役割を担う機会があったんだけど、最初に気づいたのは、過去にできていたSQL文を手で書けなくなってたこと。ORMを使ったけど、結局それがパフォーマンスの問題を引き起こして後悔した。これが私にとってのシニアエンジニアの定義だと思う:自分がいくつかのことをすでに忘れていて、知識の幅が限られていることに気づいた人。

ここでこの感情をよく見るけど、私はDjango ORMで14年間全くそんな経験がないんだよね。

人々はORMについて愚痴るのが好きだけど、私のように生のSQLも書いてORMも使う人間からすると、ORMを使わないビジネスプロジェクトはちょっと赤信号だと思う。そういう設定でよく見るのは(時には一つか二つだけど、通常は少なくとも一つはある): - ユーザーが制御できる変数でつながれたSQLクエリ — SQLインジェクションに対して完全にオープン。 (フォームフィールドがそのままクエリに入るのはもう驚かない。) - 明確な関心の分離がない — データアクセスロジックが至る所に散らばってる。 - SELECT *を書くのを避けるための自家製「SQLヘルパー」があって、でも今は基本的なクエリを再構築するのがパズルみたいになってる。 - 半端なデータアクセス層が「魔法」の層の下に埋もれていて、見つけるのがほぼ不可能。要するに: 私はSQLに反対してるわけじゃないけど、すべてのアプリケーション、特に5〜50人の同時ユーザーの小さなものまで手書きしなきゃいけないと思ってる人には警戒してる。

これは多くの人がORMを使っているからこその共通の感情だね。みんなが頻繁に使うから、利点を当たり前に思って、欠点を強調しがち。ORMのパフォーマンス問題で文句を言って、カスタムクエリに切り替えた開発者と一緒に働いたことがあるけど、結局それもORMコードと同じくらいメンテナンスやパフォーマンスの負担になった。私の疑念は、ほとんどのツールと同じように、開発者が使っているものの限界や内部の仕組みを理解する時間を取らないことが問題だと思ってる。

ElixirのEctoのアプローチが好きだな。SQLを言語に持ち込んでセキュリティを扱い、アプリの実際の問題に対するオプトインのソリューションを構築する。下では、すべてがシンプルで(例えば、クエリは構造体で、合成可能)、ドライバ層ではBEAMをフル活用してる。これと同じくらい成熟していて完全なソリューションを見つけるのは難しい。JS/TSの世界では、Drizzleの方向性が好きだけど、ランタイムや型システムから避けられない基本的な複雑さがある。(型システムを批判するつもりはないけど、TSは最初からこのレベルの洗練を考えて作られてなかったから、複雑さが目立つんだ。)

少なくとも、table=db.table("table1") table.insert({"col1": val1, "col2": val2}) みたいに書けるものが欲しいよね。もし手でたくさんのINSERTを書いてるなら、きっと適切に引用してないか、15個のプレースホルダーを使ったクエリを書いてて、いつか間違った場所に入れちゃうと思う。ORMや関連ツールキットは、「コンピュータサイエンスのベトナム」と呼ばれていた頃からずいぶん進化したよ。俺はJavaのJooQ(https://www.jooq.org/)とPythonのSQLAlchemy(https://www.sqlalchemy.org/)の大ファンなんだ。この2つは、上のコードサンプルのケースをカバーするオブジェクトSQLマッパー(通常は生成されたオブジェクト付き)と、ホスト言語内でのSQL用DSLをサポートしてるから、クエリビルダーを作るためのコード生成をしたいときには最高だよ。俺は非常に複雑な検索インターフェースに取り組んでいて、結合やサブクエリ、再帰CTEなどを構築してるけど、コードはかなりメンテナンスしやすい。

Prismaのおかげで、ORMで何でもできるってことを実感した。今は変わったかもしれないけど、少なくとも去年までは、distinctがメモリ内で処理されてたんだ。理由があったみたいだけど、確かに何かのメリットはあったんだろうね。でも、OOMを追跡してるときにこれを知ったんだ。明るい面としては、同僚とたまにこのことをネタにして笑えるようになったよ。

数週間かけて手書きのSQLクエリを書くことで、プロファイリングやクエリヒントの追加にかかる時間を何時間も節約できるよ。メンテナブルなシステムを望むなら、すべてをORMを通すように強制しよう。ORMクラスから自動生成されたマイグレーション - ORMの表現とデプロイされたスキーマが同期しているかをビルドの一部としてチェックすること。リンターで直接SQLアクセスメソッドをブロックする。これをやれば、メンテナンスは楽になるよ。

結局、これはトレードオフだよね。誰もが自分のコードやカスタマイズを3ヶ月後に覚えてるなんてことは例外だと思う。ORMやフレームワークは、何度も反復するから覚えやすい慣習みたいなもんだし。特定のユースケースよりもはるかに大きな人口に対応できるように膨れ上がってるのには理由があって、それがまた別の問題を引き起こすこともあるけどね。

ビジネスチャンス:N+1クエリを防ぐ型システムを発明する。

無料でこれらを手に入れるためのプロのヒント:nextjsとprismaを使え。確実に痛みと苦しみが待ってるよ;彼らは速く動いて壊すから、毎週の脆弱性や破壊的な変更を楽しみにしておけ!

言語コミュニティの人たちが「私は新参者です、どのフレームワークを使うべきですか?」って投稿するのを見ると、いつも面白いなと思う。「私は運転初心者です、どのブランドのナイトロを使うべきですか?」って聞いてるようなもんだよ。いや、まずは運転に慣れろって。

言語によるね。これはRubyではかなり定まってる。

コンテキストによるかな。俺はRuby、Node.js、Java、GawkのバックグラウンドからErlang(Elixirじゃない)に来た。Erlangコミュニティに最初に質問したのは、ビルドツールは何か、ユニットテストフレームワークは何か、プロジェクトのセットアップはどうなってるかってこと。これらのツールや概念が何をするかは知ってるけど、Erlangのツールの最新の状態を知りたかったんだ。俺には海の足があるけど、Erlangではまだなんだ。なんでErlangかって?それが他のものとは全然違うから!

いいアイデアがあるかも(?): 1. 同じプロジェクトで複数の開発者がいること。2. 各開発者は自分のツールや技術を使って、それぞれの部分だけを担当し、他の開発者がやった部分は完全に理解しないようにする。これで色々な楽しみが生まれるよ。 - 同じものの実装が複数あって、一貫性がない - さらに面白いのは、その不一致な実装が互いに影響し合って壊れちゃうこと!これが始まったら、簡単なボーナスもあるよ。Bが起きたら、自分のツールセットの中で変な追加処理で「修正」して、上の(2)をうまく避ける。これが成功すれば、複数の開発者がこの技術を組み合わせて、奇妙な壊れ方のピンボールゲームを引き起こすことができる。注意: CSSはこのゲームを始めるのに最適な場所だよ!

すべてのDevOpsをサイドでやって、複雑なマルチAZのKubernetesクラスターが動いていることを確認しよう。AWSのバズワードサービスをできるだけたくさん使って、GPTに「複雑な900ノードのNext.jsマイクロサービスセットアップのための超セキュアなAWS K8sはどう?」って聞いたときに読んだものを使ってね。

まじで。今の職場はこんな感じ。リトロスペクティブでコーディングスタンダードについて触れないように言われたんだ。うん、これにはめっちゃイライラしてる。内心死にそうだよ。

バックエンド版: - ローリングリリースのディストリビューションを手動でインストール - パッケージや構成管理を使わずに手動でインストール、ドキュメントなし - コンテナやハイパーバイザーを使わずにベアメタルにインストール。ラベルのないスパゲッティパッチケーブルの巣があればボーナスポイント。 - デプロイやアップグレードを自動化しない - 何のバックアップも持たない - パッチ適用、DDoS緩和、DR/BCPの計画がない

ワイルドカード証明書をベンダーから買って、必要なところに手動でインストール。どこに置いたかやいつ期限が切れるかはメモしない。プライベートキーが漏れないことを祈る。可能な限りのメトリクスを集めて、適当なアラート閾値を設定して、何も調整しない。これでアラート疲れに悩む専任チームを雇えるね。全インフラで単一のLTS OSリリースを標準化して、新しいLTSリリースに切り替えるのをギリギリまで待って、すべてのOS変更を一気に飲み込む感じ。

常に、常にコンパイルステップを必要とする [...] 例えば、実行されるコードを書くのではなく。バニラJSを書くことが、非常にシンプルなケースを除いてコンパイル言語を使うより優れているとは思えない。俺には悪いアドバイスに思える。

この発言のニュアンスは、強調のために繰り返された最初の言葉にある。

著者が言いたかったのは、できるだけ多くのビルドステップを使えってことだと思う。

NodeはもうビルドステップなしでTSを直接実行できるようになったよ。ブラウザでしか実行されないTypeScriptも含まれてる。指定されたコードファイルをNodeアプリにインポートして、出力を文字列として送信するだけ:my_script.toString(); これで、コンパイルステップなしでNodeとブラウザの両方で実行できる強く型付けされたコードが完成だね。

  1. 依存関係は、ピン留めされてない状態で追加するとプロジェクトを壊すことがある。最近のパッケージマネージャーは依存関係を自動でピン留めしてくれるけど、もし依存関係が壊れたらどうするか?別の依存関係に置き換えるか、ゼロから自分で書くこともできる。依存関係を使うことで、最初は時間を節約できて、行き詰まったときに自分のライブラリを書く時間を使うことができる。2. フレームワークも依存関係と似たようなもので、プロジェクトの初期段階で要件がはっきりしていないときに時間を節約できるし、十分なユーザーやリソースが揃ったら、自由にゼロから書くことができる。3. 最近はコンパイルがめちゃくちゃ速い。多くのツールがRustで書かれているからね。例えば、Viteを使ったプロジェクトは、10年前のノートパソコンでも数秒でビルドできる。要するに、これらのことは、維持するのに多くの時間とエネルギーを必要とするウェブサイトにはならないってことだ。