mizzsugar’s blog

日々感じていることや学んだことを書きます。エンジニアリング以外にも書くかもしれません。

『システム開発と「具体と抽象」』を読んで

具体と抽象をテーマにした著書が多い細谷氏の、システム開発に特化した具体と抽象本です。 もともと他の著書も好きだったのと、自分自身がシステム開発を生業としているので「これは読まねば!」と意気込んで読みました。

https://amzn.asia/d/066C2DSj

↓「具体と抽象 ―世界が変わって見える知性のしくみ」「13歳から鍛える具体と抽象」の感想文↓ mizzsugar.hatenablog.com

AI時代にリーダーを育成する立場として、悩んでいた部分の原因の一部について書かれていたので共感しました。ただ、本著には「どうすれば解決するのか」をあえて明示していないので、明日から行動できるような答えを求めている方には物足りないかもしれません。しかし、AI時代に求められる能力についてぼんやり不安を抱えている人には、どんな背景によってどんな思考が求められているのかヒントを得られるかもしれません。「答えを言われないと動けない」から脱したい人にも刺さるかもしれません。

「言われたことは得意だが、提案が不得意」

本著はSI業界の課題として「言われたことは得意だが提案が不得意」なことを述べています。その要因として、上意下達の業界構造とそれによる「言われたことを言われた通りにやる」ための問題解決型の思考回路を上げています。 今までの業界構造ではそれで問題なかったけれども、企業の系列構造が崩れてきたこととAIの台頭によって変わってきました。提案して仕事を取ってくることが求められるようになり、問題発見型の思考が必要になってきました。

抽象思考で問題発見、具体思考で問題解決

何が問題か、なぜやるのか、など形がないものを扱う問題発見には抽象思考が求められます。一方、どう作るかなどゴールが決まっているものをあつかう問題解決には具体思考が求められます。 抽象ではWhyを問い、具体ではHowを問うともいえます。 抽象思考と具体思考は完全に分かれているのではなく、グラデーションです。ITのPJに例えると抽象的なものから、企画→要件定義→基本設計→詳細設計→実装のように徐々に具体的な内容になっていきます。

グラデーションになっているからこそ、1段階上の抽象度で「なぜこのタスクをやるのか」「この機能の目的は」など考えることが大切です。設計書に書かれていることを着実に実装する前に、「なぜこの機能があるのか」「どんな要望があるのか」など抽象度をあげて目的を考えると、どんなことに考慮して実装やテストをすべきか見えてきて出戻りや考慮漏れが減らせるのではと思いました。

問題発見と問題解決は思考のOSが違う

問題解決型の人材が問題発見型になるのが上手く行かないのは、そもそも思考のOSが違うからだと述べています。いわば、あるPCのOSをMacOSからWindowsOSにリプレースして動くようにしろと言っているようなものです。 それでも問題発見と問題解決を場面によって使い分けないといけません。そのためのイメージモデルとして「メタ化」が提唱されています。1段階上の段階の思考モデルとして下位モデルである具体と抽象を切り替えます。

野球で言うと、問題発見型はピッチャーで課題解決型はキャッチャー。両方同時にやれというのは防具をガチガチに装備しながらボールを上手く投げれないのと同じです。切り替える必要があります。同時にやれと言っているような指示を出さないように気をつけないとなと思いました。

AIが「SIの具体」を代替していく

「ITの進化は抽象度を上げて複雑さを隠す歴史だ」と述べられています。例えばOSはハードの違いという具体を吸収しました。今の時代だと、生成AIは今までに人間が担ってきた設計や実装の一部という具体を肩代わりしつつあります。定義された問題の解決する今までSIがやってきた役割がAIによってコモディティ化してきているからこそ、抽象化し、問題発見し、構造を設計する力が問われます。

リーダー育成を顧みて思ったこと

メンバーとして与えられたタスクを実装・テストする業務が中心だったところからリーダーとして問題を見つけて定義する立場で苦戦するのは、思考のOSが違うから当然なのだと腑に落ちました。

そして、これは生まれ持っての才能に依存する能力ではなく具体と抽象を行き来するトレーニングでカバーできそうな感触があります。例えば、ある業務で受け取ったフィードバックを一般的な教訓に言語化して抽象化し別の業務ではどう行動するか具体で考えることは、どの役職・立場でもすぐにできそうなトレーニングかなと思います。

Pycon mini Shizuoka2026に参加しました

PyCon mini Shizuokaに今年もスタッフとして参加しました。去年は当日スタッフのみでしたが、今年は準備期間から参加しました。

PyCon mini Shizuoka 2026 - connpass

聞いたトーク

生成AI時代に、画像処理やオーディオ処理のノードエディターを作る理由

生成AIで画像処理・オーディオ処理の試行錯誤をできる時代にノードエディターを自作してそれを使って処理をするお話でした。 トークの前はイメージできていなかったのですが、実際に動いているものを見ると、ノードエディターだと処理の結果を目視で比較しやすくて感動しました。

NodeのUIに使っているReact Flowは知らなかったので勉強になりました。

AI主導でFastAPIのWebサービスを作るときに 人間が構造化すべき境界線

ちゃんと設計しないでAIに任せるとちぐはぐな実装をするから大事なところは取り決めておこうという話でした。データの意味・認証認可・画面ごとの整合性は人間が決めて、正しいかどうかを判断しようとのことでした。

Specは仕様書ではなく、AIと人間の間の約束事という考え方はこれからSpec駆動で開発する時に意識しようと思いました。

画面ごとの整合性がズレにきづく力は今の時代にどうつけていくのか考えて行きたいと思いました。*1

speakerdeck.com

Pydanticで複雑なJSONを一発でValidation

複雑で様々なバリエーションのあるJsonデータを安全に保存するためのバリデーションにJsonSchemaからPydanticに変えた話でした。 かなり整理されていたけれどもそれでも複雑でこれはきつい…というデータ構造だったので、機能が豊富で継承関係を整理しやすいPydanticにしたのは英断だと思いました。 JsonSchemaからPydanticのコードを生成するdatamodel-code-generatorは知らなかったので勉強になりました。*2

slides.takanory.net

DSPy入門 Pythonで実現する自動プロンプト最適化 〜人手によるプロンプト調整からの卒業

LLMのモデルの更新頻度高いしその都度プロンプトを書き換えないといけない作業は不毛だな…と思うので、それを自動化する話は興味深かったです。 機械学習よりも集めないといけないデータの件数が少ないとはいえ100件データを集めるのが難しいサービスもありそうと思う反面、データが集まっていて「こういうふうに回答すべき」というノウハウやドキュメントが存在するであろう問い合わせ系のサービスでは導入しやすそうと雑に考えました。

speakerdeck.com

キーノートとLTはスタッフ業しててちゃんと聴けずでした。X実況やスライドで追います。

懇親会

今年の懇親会は静岡市の醸造所 West Coast BrewingStarwatcherの樽が用意されました。 スポンサーの皆様のお力と、会場から醸造所まで車で30分もかからない立地の良さと、車を運転してくれるスタッフのおかげで実現できたんだなあと感動しました。

スタッフ業

準備期間の大きな仕事としては2つありました。それと、当日スタッフをしました。

グルメマップ

去年と同じくランチは会場を閉めて食べに行ってもらうスタイルなのですが、去年は「どこに行けば良いか分からない」という声がありました。去年の反省から作りたいと思っていたので、グルメマップの企画・制作をしました。 Pythonで地図表示をするアプリを作る選択肢を考えつつも、費用・納期・要件の簡潔さからGoogle Mapで制作しました。

Xでオススメしたお店・メニューをランチで食べた報告を見て嬉しかったです!

www.google.com

ノベルティのステッカー

デザイン・サイズの決定、発注先選定、発注作業をしました。

デザインはロゴがすでにあったのでそちらを使用させていただきました。ノベルティの話がある前からロゴは存在していたのですが、ロゴの利用規約的にこういったグッズ制作に利用できることが分かっていたのはスムーズに進める上でありがたかったです。

ただ、見積もってみると発注してから出荷する期間が思ったより長く、「ノベルティ作ろう!」と決まったのが遅かったのもあり、試作することも考えると期間がギリギリなのは焦りました。バッファ込みでスケジュールを組みましたが、余裕でバッファ使いきりました。配布する分が届いたので安心しました。バッファはとても大切。

ノベルティのステッカー

当日スタッフ

受付・懇親会の用意をしました。タイムキーパーなどは他の方が担当してくれたので、トークをじっくり聞くことができました。 Connpassのサブイベント機能について、メインイベントを登録するとサブイベントの出席も確認できたのは便利で感動しました。 スタッフ業とは直接関係ないですが、Connpassを改善されたLTもあり、日々の進化・運用に感謝の気持ちが募りました。

speakerdeck.com

まとめ

今回始めてお会いした方、12月のPyladiesから知り合った方、数年ぶりにお会いした方、いろんなご縁がありました。 仕事でPythonを使わなくなりましたが、Pythonコミュニティは良いなと改めて実感しました。

*1:1回0→1で設計〜運用するのを体験するとか、E2Eテストやって気づきを得るなど泥臭い方法しか思いつかない… これからは、全体の整合性を保つための観点のガイドライン的なものをAIに読み込ませて、AIとの対話を通して学ぶとかになるのでしょうか。

*2:手放しに完璧に置き換えたからそのまま使える!というものでもなく十分な検証は必要とのことでした。が、生成AIにやらせると余分な項目追加されたりするので、単純作業はツール派の私は歓喜です!

「「分かった!」と思わせる説明の技術」を読んで

わわわIT辞典の方が書いた説明の技術の本だと聞いて読み始めました。わわわIT辞典は大変わかりやすい説明で、プログラミング初学者の頃によくお世話になっていました。数年が経ち今、仕事上説明をする機会が増え、分かりやすい説明ができる「わわわ」の方の考えを学ぼうと思いました。

https://amzn.asia/d/1Hyq6qg

説明はおもてなし

「分かった!」と思わせるためには、おもてなしとして説明をするとのことです。相手に「分かった」と思ってスッキリしてもらうこと。そのためにはまず相手のレベルを知って、相手のレベルに合わせた説明をします。

相手のレベルを知るために、「何%理解した?」と聞き、本人の自認よりも10-20%下げて理解度を見積もるのは良い考えだなと思いました。ダニングクルーガー効果で高く自認するケースもありますし、「こんなん分かる舐めるな」と言われた方が理解されないよりマシという吹っ切れた考え方も説明する時に活かそうと思いました。

思い切って削る

難しいことは思い切って削るのが「分かった」と思わせるコツだそうです。削ると専門家からみたら「正しくない」状態になるときがありますが、相手のレベルやコミュニーケーションの目的に沿って削るのは悪いことではないというスタンスです。難しいことは100%正確な状態だと難しいままで理解されないので、確かにと思いました。

いわるく「厳密には正しくない」ことを伝えるのは良くないとエンジニアだけの世界にいると思いがちになるので、コミュニーケーションの目的達成のためには悪いことではないというスタンスには救われました。

クライアントだけでなく、初学者に教える時もどこまで端折るかよく迷います。初学者のようにいずれは100%知らないといけない人については、レベルが足りなかろうが伝わらないと話が進まないところは説明を頑張りつつ、それ以外のところについてはその時のレベルに合わせ分解して説明して、そのうち100%を目指すと割り切るのも1つの戦略かもしれないと思いました。

「ITエンジニアの転職学」を読んで

直近で転職する予定はありませんが、現職に残るにしてもキャリア形成に有益だと評判が良いので読んでみました。

https://amzn.asia/d/cFxS4CJ

データや経験に基づいたアドバイスや理論に納得したのはもちろんのこと、筆者の方の温かい目線と書き味に、自然と前向きな気持ちになれました。

「XXしないとヤバい」「XXするのが一流」みたいな構文がなく、最後まで安心して読めました。キャリアは気になるけど過剰な煽りが苦手な人にもおすすめです。

また、「人生の一部としての仕事」というスタンスを感じました。例えば、「40代は人生の中でこういう時期だと心理学上言われているので、キャリアと向き合うときにこう感じる人もいるでしょう」と言った感じです。より良い人生にするためにこう向き合うと良いという、温かいメッセージを受け取りました。

6つの評価軸×5つのレベル

実装力、組織貢献力、事業貢献力などの6つの軸と

主力メンバーレベル、リーダーレベルなどの5つのレベル

を定義したマトリックス表が大変参考になりました。

いろんな会社の評価指標を参考にされており、具体的な内容に差はあれど方向性は大体他の会社もそんな感じなんだろうな、と私も数社経験したなりに思いました。

各軸での自分のレベルを振り返り、どんな経験を積めば次のレベルに到達できそうか考えるきっかけになりました。

評価制度を考えている人や、マネジメント業務をしている人にも役に立ちそうです。

20,30,40,50代以降の過ごし方

どの年代がどんなことを期待されているのか、どんな風にキャリアを考えるのかが述べられていました。

こちらも、自分の立ち位置の振り返りとマネジメント業務両方に役立ちそうです。

30代の仕事の向き合い方として「組織の目標を達成することにフォーカスしつつ、その過程に自分独自の工夫を加えて、会社と自分のこだわりのバランスを取る」というところが印象的でした。(これはチームリードしているなら、20代でも当てはまること)

自分の工夫を加えて目標達成した結果が、「〇〇さんがいないとできなかったこと」になるのかもしれないと思いました。いきないそこを目指すのは難しいけど、自分の工夫を加えるのはそれよりはハードルが低いので、そのスタンスで頑張ろうと思いました。

django-anymailとResendでメール送信する 〜Railway無料プランSMTP通信できない問題の解決〜

RailwayというPaaSのFreeプランで開発をすすめていたところ、メール送信でつまづいたのでその原因と解決策の共有です。

使用技術

原因

RailwayはProプラン以上でないとSMTP通信できないそうです。 Outbound Networking | Railway Docs

何回メールを送ってもSTG環境では500エラーになり、ローカル環境では正常送れるのはこの仕様のためでした。

HTTP APIを使ってメールを送信しないといけません。

解決策

今回は運良くDjangoを使っていたので助かりました。

結論から書くと、django-anymailというDjangoでメール送信を簡単に実現するパッケージを使い、ResendのHTTP API通信のメール送信機能を使ってメール送信します。

settings.pyにこれを追加するだけ!

EMAIL_BACKEND = "anymail.backends.resend.EmailBackend"  # デフォルト値から書き換え
ANYMAIL = {
    "RESEND_API_KEY": os.environ.get('RESEND_API_KEY'),
}  # 追加

まず、以下の条件でメールサービスを探しました。

  • [must] HTTP API通信でメール送信できる
  • [want] 無料プランがある
  • [want] django-anymailがサポートしているメールサービスである

3条件すべて揃っているのがResend でした。 なお、SendGridも候補にあがっていましたが、2025年5月にdjango-anymailのサポート切れとなっていました。

github.com

SendGridのパッケージを使えばSendGridを使えますが、django-anymailはsettings.pyに設定値をいれるだけでメールサービスと通信する箇所を実装しなくてもメール送信できる手軽さがあります。 手軽さが勝利して、django-anymailを使えるResendを選びました。

まとめ

  • django-anymailを使えばsettings.pyを書き換えるだけでメールサービスを利用できる
  • django-anymailがサポートしているメールサービスを選ぶ必要がある
  • Resendは無料プランがある かつ django-anymailのサポートがあるのでDjangoでの開発の最初に使うメールサービスとしておすすめ

SupabaseとMetabase のローカル環境セットアップ

DBにSupabase使うアプリのデータ分析をMetabaseでする構成を作るにあたり、ローカル環境の構築に苦戦したでその備忘録です。 ローカル環境なので、Supabase環境はSupabase CLIで、MetabaseはMetabaseのDockerコンテナで作ります。 アプリ部分はNext.jsにしていますが、今回は関係しないので説明は割愛します。ローカルでNext.jsをインストールして立ち上げるよくある方法です。

使用技術

種類 使用技術名
OS Ubuntu 24.04
コンテナ管理 Docker 17
フロントエンド Next.js
バックエンド・DB Supabase (PostgreSQL, Auth, Storage)
データ分析 Metabase
データ可視化 Metabase UI

構成図

本番環境

ローカル環境

ローカル環境構築方法

① Supabase CLI のインストール

curl -fsSL https://cli.supabase.com/install.sh | sh

② Supabase プロジェクトを作成

supabase init

ローカル環境起動:

supabase start

完了すると、コンソールに次のような情報が表示されます。

Started supabase/local-dev
Database URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres

このDBをMetabaseから参照します。

③ Metabase を Docker Compose で起動

プロジェクトルートに docker-compose.metabase.yml を作成:

version: '3.8'

services:
  metabase:
    image: metabase/metabase:latest
    container_name: tea-metabase
    ports:
      - "3002:3000"
    volumes:
      - metabase_data:/metabase-data
    networks:
      - supabase_network_tea-subscription  # Supabaseのネットワークに接続
    restart: unless-stopped

volumes:
  metabase_data:

networks:
  supabase_network_tea-subscription:
    external: true

⚠️ supabase_network_tea-subscription は、supabase start 実行時に自動作成されるネットワーク名です。 環境によって異なる場合があるため、次のコマンドで確認してください:

docker network ls

supabase_network_XXのようなネットワーク名を探し、その名前をComposeファイルに記載します。

起動:

docker compose -f docker-compose.metabase.yml up

④ Metabase にアクセス

ブラウザで http://localhost:3002 にアクセスします。

初回セットアップ画面で次のように設定します:

項目
データベースの種類 PostgreSQL
ホスト SupabaseのDBコンテナ名(例:supabase-db
ポート 5432
データベース名 postgres
ユーザー名 postgres
パスワード postgres

⚠️Supabase CLI はDBを 127.0.0.1:54322 でホストマシンに公開しますが、 MetabaseはDockerコンテナ内で動作しているため、127.0.0.1 では接続できません。 代わりに SupabaseのDBコンテナ名 を指定する必要があります。

Dockerコンテナ一覧で supabase_db_XXX のような名前のものです。

docker ps

下記のNAME列の値です。

CONTAINER ID   IMAGE                                                   COMMAND                    CREATED              STATUS                  PORTS                           NAME    
5b7e5eede59f   public.ecr.aws/supabase/postgres:17.X.X.XXX             "sh -c '\ncat <<'EOF'…"   23 hours ago         Up 23 hours (healthy)   0.0.0.0:54322->5432/tcp, [::]:54322->5432/tcp        supabase_db_XXXX

⑤ 動作確認

Metabaseの「データベース一覧」に Supabase の postgres が表示されていれば成功です。 これで Supabase → Metabase のローカル開発環境が完成しました。

最終的なディレクトリ構成

├── metabase
├── nextjs-app
├── docker-compose.yaml
├── .env
└── supabase
    └── config.toml

まとめ

  • Supabase CLI は裏側で Docker Compose を使ってローカル開発環境を構築している。

  • Metabase は Supabase のDBコンテナと同じDockerネットワークに参加させる必要がある。

  • Metabaseの接続設定では、ホストにコンテナ名を指定するのがポイント。

「#100日チャレンジ」を読んで

ルーズな生活を送る大学生がChatGPTでソフトフェアエンジニアになったシンデレラストーリーという先入観を持っていてごめんなさい。AIという学習アシスタントがいる時代でのプログラミング学習の過程を綴った本でした。 未知の領域にチャレンジしようとしている人にとって。やってみようと思わせる1冊だと思います。軽妙な語り口でさくっと読めます。*1

https://amzn.asia/d/dU77mIt

ChatGPTの使い方の変化

100日間の中で、プログラミングへの理解度が高まるにつれてChatGPTの使い方が変わっていく様子が書かれていたのが興味深かったです。「プログラミング全くわからないけどChatGPT使ってサクッと実績残そう」と1日目に訳もわからずChatGPTがコピペするところから始まります。意図しないコードを出力するChatGPTとの苦戦を通して、プログラムを理解していないと理想のものを作れないと気づき、100日目には内部構造を主体的に設計してChatGPTをあくまでアシスタント的に使うまでになっていました。

楽しい習慣にすることで続けられる、せっかくだから1%だけでも成長しようという気になる

ずっと意味も分からずコピペだけでも100日達成できるのに、成長できたのも素晴らしかったです。

100日続けられてその間成長できたのは、苦行ではなく楽しさを感じることだから、と言った旨が書かれています。著者にとって100日チャレンジは努力や苦行ではなく、習慣として楽しむものだそうです。「せっかく自分で始めたことだから1%でも成長しないともったいないから少し頑張ってみる」と奮い立たせて「今日はChatGPTが言ってたクラスというものを使ってみる」など1日で出来そうな範囲で進めていました。

しかも、ChatGPTに聞けるので未知の領域を少し頑張るハードルが低いのも、続けられる材料になったと思います。

1日ずつなど目標をすぐ見える範囲にするなど達成しやすくすることで挫折せず楽しく習慣にすることができたのかもしれません。

記録することで成長を感じられたのも良かったと思います。

まとめ

  • ChatGPTによって未知の領域への挑戦のハードルが下がった
    • わからなくても動くものを作れるので確実に最初の成功体験を得られる
    • 進むにつれてわからないことができてもすぐ聞ける
  • 楽しく習慣化できるように工夫する
  • 「今の実力で少し背伸びできる範囲で頑張る」を繰り返すと気づけば大きな成長になっている

*1:PyConJP 2025で著者の基調講演があるそうです。さくっと読めるので気になる方は読んでから参加するのもアリだと思います(今回私はお留守番しますが…🥲)