11
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「わからない技術」への向き合い方

Last updated at Posted at 2025-12-22

はじめに

Hubble Advent Calendar 2025の23日目です!

Hubbleでバックエンドテックリードをしている @power3812 です。オブジェクト指向大好きマンで、神クラスを作れないかと模索の日々です:innocent:

今回は今までどうやって自分なりに「わからない技術」に向き合ってきたかを書こうと思います!

「わからない技術」への向き合い方

──技術自体より「考え方」を軸にして、今までGo、Rails大規模新規、LLM Agentツールの作成を乗りこなしてきた話

新しい技術に触るときとか、未知の領域に飛び込むときに、
「うわ、これ難しい、ドキュメントも見てもよくわからない……」って一回思うじゃないですか。

でも僕の場合、未経験のGoで新規アプリケーションAPIを作ったときも、Railsでかなり大きい規模の新規アプリケーションAPIを作ったときも、LLM Agent用の難解複雑なtoolsを作ったときも、
実は 技術そのものに苦しんだというより、"どう向き合うか"に救われたことが多いです。

この記事は「Go / Rails / Agent Tools の作り方」ではなく、
難しそうな技術の“乗りこなし方”そのものの話です。

僕の経験では、技術が変わっても考え方は全く変わりませんでした。

技術って実はそんなに難しくない説

個人的に思ってるのは、技術自体が難しいわけじゃないということ。

難しさの90%くらいは、

  • 情報が多すぎる
  • 依存関係が多い
  • どこから理解すればいいかわからない
  • 概念と実装が一体化して押し寄せてくる
  • 正しい順番で触らないと逆に混乱が増える

みたいな 構造の見えなさ によって生まれている。

だから、僕は最初から技術全体を理解しようとするのをやめています。
大きな塊を一口で飲み込むみたいなことは基本しない。

僕のやっている「わからない技術」への向き合い方

ここからが主軸。
技術名をいったん忘れて、純粋に思考プロセスとして読むと理解しやすいと思います。

1. 「この機能が最終的にどう動けばいいか」を端的に決める

最初にやることは、技術を調べることでも設計を考えることでもない。

「この機能は、最終的にどんな動きをすれば正解なのか」
これを1行で言えるようにする。

たとえば、

  • リクエストを受けたら、◯◯の条件で判断して、◯◯を返す
  • 入力を受け取り、内部で◯◯をして、結果だけを返す
  • 状態を持たず、決まったルールで変換するだけ
  • 失敗しても◯◯までは保証する

中身は一切考えない。
「外から見た振る舞い」だけを定義する。

ここが決まっていないと、

  • 実装を考え始めた瞬間に迷走する
  • どこまで作れば完成なのか分からない
  • 設計の議論が抽象論に流れる
  • 技術的な難しさが無限に膨らむ

という状態になる。

逆に、

「この機能は、最終的にこう振る舞えばいい」
が決まっていれば、

  • 実装は後からいくらでも変えられる
  • 分割も依存もその動きを満たすために決められる
  • 小さく動かすときの最初の形が自然に決まる

技術の難しさは、実装が分からないことよりも、「何を作っているのか分からない状態で手を動かすこと」 から生まれる。

だから最初に決めるのは、目的でも思想でもなく、その機能の“完成時の動き”

ここが端的に決めると、この後の分割・依存カット・小さく動かすが、すべて同じ方向を向いて進み始める。

2. まず塊を分解する

難しさの正体を考える。

  • 目的・仕様(What)
    何を実現する機能か / 入出力 / ユースケース / 制約

  • 概念・ドメイン(Concept)
    登場する概念 / 用語 / ルール / 不変条件

  • 責務・構造(Structure)
    役割分担 / 境界 / インターフェース / レイヤ分割

  • データ・状態(State)
    保持する状態 / 永続化 / スキーマ / 整合性

  • 処理の流れ(Flow)
    呼び出し順 / データフロー / 同期・非同期

  • 外部依存(Integration)
    外部API / DB / メッセージング / 契約

  • 失敗と例外(Failure)
    エラー分類 / リトライ / タイムアウト / フォールバック

  • ライフサイクル・運用(Lifecycle)
    起動 / 停止 / デプロイ / 監視 / ログ

  • 設計方針・非機能(Quality)
    性能 / 可用性 / セキュリティ / 保守性 / コスト

全部ごちゃ混ぜになってるから難しく見える。
だから僕はまずここで解体する。

解体して、「これはこっちの問題」「これは別の責務」みたいに分類していく。

理解は対象が小さくなった瞬間に進む。

3. 外部依存と非本質を切り、理解可能な構造に落とす

技術の難しさは、構造そのものより「外部依存」と「同時に考えさせられる要素の多さ」で爆発する。

だから最初にやるのは、
2で分けた構造のうち、本質でないものを一度すべて切り離すこと。

具体的には、

  • 外部依存を切る
    • DBなし
    • 外部APIなし
    • メッセージング・Queueなし
  • フローの複雑 を落とす
    • 非同期なし
    • 並行処理なし
  • 失敗設計を単純化する
    • エラーは1種類だけ
    • リトライ・分岐なし
  • 設計方針・非機能を一旦忘れる
    • 理想的なアーキテクチャを考えない
    • スケール・性能・汎用性は後回し

こうして 「目的・概念・責務・最小の処理フロー」だけが残った世界を作る。

このレベルまで削ると、技術は急に「理解できるサイズ」に落ちてくる。

依存を切るというのは、実装を雑にすることではなく、理解のスコープを意図的に狭めること

この工程を挟むだけで、どんな技術でも触れそうにない塊から分解可能な構造物に変わる。

4. 最小の構造で「正しい動き」を1本通す

大事なのは、全体を理解してから作り始めることではない。

2で分け、3で削った結果として残った構造が、「本当に満たすべき動き」を実際に通せるかを確認する。

ここでやるのは、完成形を作ることではなく、機能がブラックボックスとして正しく振る舞う最小形を動かすこと。

  • APIなら、入力を受けてレスポンスを返す endpoint を1本
  • システムなら、1つの責務と1つのデータだけを扱う処理
  • Agentなら、input → 処理 → output が一直線につながる流れ

この時点では、

  • 外部依存はモックのまま
  • エラーは成功/失敗の2択だけ
  • パフォーマンスや拡張性は考えない

重要なのは「この構造で、意図した動きが実現できるか」

最小構成で1本の流れが通ると、
それが 理解の基準点 になる。

あとはそこを起点に、

  • 依存を戻す
  • 分岐を増やす
  • 失敗ケースを増やす
  • 構造を洗練させる

と、段階的に広げていけばいい。

小さく正しく動くものが1つあるだけで、技術は「分からない塊」から 「拡張可能な構造」 に変わる。

5. 構造を統合し、「全体として正しく動く形」に戻す

4で最小構成の流れが1本通ったら、
ここで初めて、分解していた要素を段階的に戻していく。

やることはシンプルで、
2で分けた構造と、3で一度切った要素を 「正しい動きを壊さない範囲」で統合していくだけ。

この段階で見えてくるのは、

  • 責務と境界は適切か
  • 依存の方向は破綻していないか
  • 処理の流れは自然につながっているか
  • データと状態は無理なく受け渡せているか
  • 失敗と例外はどこで扱うべきか
  • 設計方針・非機能をどこまで入れるべきか

バラして理解していたパーツが、「なぜその形で存在しているのか」を持って再接続されると、システム全体が急に立体的に見え始める。

このタイミングで初めて、

  • どこが複雑さの源泉か
  • どこが拡張しやすいか
  • どこを抽象化すべきか / すべきでないか

が腹落ちする。

分解 → 最小実行 → 再統合まで通せたとき、
ようやくその技術や仕組みを
「理解した」と言っていい状態になる。

余談:未経験の Go で API を作ったときの話

未経験で Go を触り始めたとき、一番分からなかったのは文法というより、
struct と interface が、オブジェクト指向とどう違うのかという部分でした。

クラスも継承もない中で、責務をどう分けるのか、どこに振る舞いを置くのかが全然ピンとこない。

なので最初から本番っぽいものを作るのはやめて、struct・interface・オブジェクト指向の違いを理解するためだけの最低限を検証することにしました。

やったことはシンプルで、

  • mock を使って、とにかく response を返すところまでを書く
  • DB / 外部API は全部切る
  • request バリデーションや認証みたいな middleware はすべて後回し
  • handler → service → repository だけ置く
  • domain は struct とメソッドを数個置くだけ

この最小構成で1本のデータの流れが通ったとき、struct は「データ構造」ではなく、
振る舞いと責務の境界を表現する単位なんだ、という感覚が掴めました。

interfaceも、継承の代わりではなく、
依存の向きを制御するための仕組みとして見ると急に分かりやすくなります。

オブジェクト指向で考えていた「クラス設計」とは違って、Goでは「構造と振る舞いをどう分けて、どう接続するか」を考え続ける言語なんだな、と思いました。

クリーンアーキテクチャも最初から理想形を理解するものではなく、依存の向きを一度だけ正しく作って動かすと腹落ちします。

そこから先は、必要になったタイミングで、DB を繋いだり、バリデーションや認証を戻していけばいい。

最初にやるべきなのは完成ではなく、「意味が分かる最小構造」を手元で動かすことでした。

具体の内容は過去に書いたので、興味ある方は読んでもらえるとありがたいです。

分割(Divide)して統治(Conquer)

ここまでをまとめると、分割(Divide)して統治(Conquer)する...

そうです!どこかのPodcastでもよく話題に出るDivide and Conquerです!

mosaic_20251217233600.png

デカルトの時代から変わらない思想っていうのはエモいですね。

おわりに

ここまで書いてきましたが、やっていること自体はそんなに特別な話ではありません。

分けて、
余計なものを落として、
小さく動かして、
またつなぐ。

新しい技術に触るときは、今も「難しそうだな」と思います。
でも、その正体はだいたい まだ構造が見えていないだけ です。

構造が見えれば、言語が変わっても、規模が大きくなっても、やることは案外変わりません。

もし今何かに詰まっていたら、一回シンプルにして、小さく動かしてみてください!
それだけで、だいぶ楽になります。

明日は、@mst_nishioさんです!

11
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?