Blog

A collection of 114 posts
Devlimeの再利用設計で保守性を高める
blog

Devlimeの再利用設計で保守性を高める

1. 背景 Devlimeの開発は、複数の開発者がそれぞれの機能とドメインを担当し、同時に開発を進める方式で行われていました。Vizendプラットフォームを基盤として開発されているため、プロジェクト構造や基本的な開発方式はある程度統一されており、全体的なアーキテクチャも十分に整備されていました。 しかし、製品規模が大きくなり機能が増加するにつれて、既存機能を修正したり、他の開発者が作成したコードを分析したりする状況が徐々に増えていきました。その過程で、同一または非常によく似た機能であるにもかかわらず、開発者ごとに異なる方法で実装されているケースを頻繁に見つけるようになりました。 例えば、特定のデータを取得するロジックは複数の画面で同じように使用されていましたが、各サービスで個別に実装されていました。また、画面上で状態を表示するUIも、似た機能であるにもかかわらず、互いに異なるスタイルと構造が使用されていました。 初期の開発段階では、このような方式は大きな問題にはなりませんでした。しかし、機能が増加するにつれて重複コードが急速に増え、同じ機能を修正するため
7 min read
React Queryのキャッシュ戦略に関する考察
blog

React Queryのキャッシュ戦略に関する考察

1. 序論:サーバー状態(Server State)はいつ古くなるのか フロントエンドを運用していると、ユーザーから繰り返し寄せられる報告が二つあります。一つは「たった今登録したのに一覧に表示されません」で、もう一つはその反対の「何もしていないのに画面が突然ちらついて、再び読み込まれました」です。一見すると無関係に思えるこの二つの症状は、実は同じ根本原因から生じています。それは、サーバーのデータをクライアントが「どのくらいの間、どのような基準で、まだ有効だと信じるのか」というキャッシュ(Cache)ポリシーの欠如です。 多くのチームがこの問題をReact Query(現在のTanStack Query)で解決しており、私が所属するプロジェクトも同様です。しかし実際にコードを見てみると、最も重要な「キャッシュをどのくらい保持するか」についての合意が一か所に集約されておらず、個々のフックに分散しているケースが非常に多くあります。 React Queryの価値は、「サーバー状態(Server State)」と「クライアント状態(Client State)」を区別す
9 min read
Keycloakifyのpage_hint状態管理の改善
blog

Keycloakifyのpage_hint状態管理の改善

はじめに 現在のプロジェクトでは、Keycloakを基盤としたログインおよびアカウント関連画面の保守を担当しています。今回は、従業員アカウントの初回設定画面で、リロードすると通常のパスワード再設定画面に切り替わる問題を確認し、その原因を分析しました。 最初は一般的なReact SPAと同じように考え、画面を区別する値をURLのクエリパラメータに設定するだけでよいと思っていました。しかしコードを追ってみると、Keycloakifyではその方法だけでは不十分でした。原因は、Keycloakifyの画面遷移方式とKeycloakのラウンドトリップ処理にありました。 URLだけでは不十分だった画面状態の管理 最初に問題を見たときは、単純に考えていました。従業員アカウントの初回設定画面と通常のパスワード再設定画面を区別する必要があるため、URLにpage_hint=isTempのような値を付け、その値を基準に画面を分ければよいと思っていました。 一般的なReact SPAであれば、この方法はそれほど不自然ではありません。画面遷移は通常react-router
6 min read
モバイルUIで初めてのお出かけ
blog

モバイルUIで初めてのお出かけ

はじめに 入社後、ずっとWeb画面を基準にデザインしてきました。そんな中、ビジェンドプロジェクトに参加することになり、ビジェンドデザインシステムを基盤にWeb画面のデザインを続けました。1年以上の時間をかけて、自然とWeb中心の感覚が身につきました。どのくらい余白があれば息苦しくならないのか、フォントは何pxなら読みやすいのか、ボタンはどこに置けば自然に手が伸びるのか…… そんな中、班長ノートのモバイルアプリプロジェクトが新たに始まり、ありがたいことに担当デザイナーに任命されました。ビジェンドのコンポーネントに慣れた状態でモバイルプラットフォームに向き合ったとき、単に画面が小さくなっただけではありませんでした。Webとモバイル、2つのプラットフォームを比較しながら、実際に「これは違う」と感じた瞬間を整理しました。 フォント 本格的な画面制作に入る前に、デザイントークンとタイポグラフィを先に整理しました。Web制作では本文に12pxを使うこともありましたが、班長ノートのモバイル制作では、ラベル・チップを除き、13pxを最小サイズに設定しました。 一見
6 min read
宣言的フォームバインディング
blog

宣言的フォームバインディング

1. はじめに Webアプリケーション開発において、ダイアログ(Dialog)やモーダル画面を通じたデータ編集フォーム(Form)を実装することは、最も一般的でありながら複雑度の高い作業の一つです。特に管理画面やダッシュボードの「コンテンツ詳細情報編集画面」のように、画面が開くタイミングでバックエンドAPIから非同期に詳細データを取得し、フォームの初期値としてバインドする構造では、より綿密な状態制御が求められます。 初期のコンポーネント設計では、最も直感的な方法であるuseEffectフックを利用して、外部Propsとして渡された詳細データの変更を検知し、フォーム管理状態に手動で値を注入する命令型(Imperative)アプローチを採用しました。しかし、この方式は高度化の段階で予期せぬ同時実行性の問題を引き起こしました。ユーザーがダイアログを素早く閉じて別のアイテムを選択し、再び開いた際、非同期データのフェッチタイミングが重なることで、以前のデータの残骸が入力フィールドに一時的に残ったり、フックの呼び出し順序とコンポーネントのレンダリングライフサイクルがずれるこ
5 min read
MATを活用したHeapDump分析
blog

MATを活用したHeapDump分析

性能分析の古典的な定番、Heap Dump K8s環境でプロジェクトを進めている途中、特定のPodが繰り返し再起動されるケースを発見しました。Podがなぜ再起動されるのかを確認するためLast State属性を調べたところ、原因は当然のようにOOMでした。通常、Podがこのように無限に再起動される場合、その主な原因はOOM Killedです。 この状況でOOMを引き起こした原因を探るため、まずLogを確認します。しかし、このようにLogを確認しても、OOMの原因は簡単には見つかりません。なぜなら、OOMの主な原因はErrorではなく、スレッドのボトルネック、つまりDB I/Oに時間がかかりすぎることで非同期処理中に性能ボトルネックが発生することだからです。エラーログが一行もないままメモリだけが徐々に増加し、Podが停止する状況では、ログだけで原因を特定するのは困難です。 このようにLogからOOMの原因を分析できないときに役立つのが、まさにHeap Dumpです。最も伝統的なプロセス分析手法であり、現在でもバックエンドの性能分析で最もよく使われている技術の一
6 min read
シングルトンパターンを用いたキャッシュ管理
blog

シングルトンパターンを用いたキャッシュ管理

1. はじめに 企業向けサービスでは、ユーザーごとの権限管理は非常に重要な機能の一つです。ユーザーがログインした後、どのメニューを表示できるか、どの機能を使用できるか、どのデータにアクセスできるかは、すべて権限情報によって決まります。 開発中のサービスも、ユーザー権限に応じて表示されるメニューが変わる構造になっていました。管理者は専用の管理者ページから、ユーザーまたは役割(Role)ごとにメニュー権限を設定できます。ユーザーがログインすると、その権限情報に基づいてアクセス可能なメニューを構成し、画面に表示します。 このような権限管理機能はサービス運用において必須ですが、実装方法によってはシステムのパフォーマンスや保守性に大きな影響を与える可能性があります。特にユーザー数が増加し、ログインリクエストが多くなるほど、権限の取得方法について検討する必要があります。 本稿では、メニュー権限情報を管理する過程で発生した問題と、それを解決するためにシングルトンパターンを活用したインメモリキャッシュを導入した背景、実装方法、そして導入後に得られた効果について紹介します。
8 min read
putlfAbsent()の限界と変更検知の改善
blog

putlfAbsent()の限界と変更検知の改善

1. はじめに リアルタイム監視システムでは、特定の値に対する計算式のメタデータを複数のサービス間で同期する必要があるケースが多くあります。今回のプロジェクトでも、計算式が生成または変更された際にイベントを発行し、他のサービスへ変更内容を伝達する機能が必要でした。 初期実装では、同一の計算式が重複して生成されないように ConcurrentHashMapの putIfAbsent()を使用しました。条件文に putIfAbsent()を組み込み、処理を通過した場合にのみ計算式伝達イベントを発行するよう実装しました。計算式は通常、一度生成されると変更されないと判断していたため、最初の登録だけを処理すれば十分だと考えていました。 しかし、さまざまな運用シナリオを検討する過程で、予期していなかった問題を発見しました。一部の計算式は、初期設定値の構成だけでなく、利用可能なセンサー信号の構成に応じて計算式自体が変更される可能性があり、従来の構造ではこのような変更を検知できませんでした。 たとえば、特定の計算式はAという信号だけが存在する場合、次のように生成されます
8 min read
AI時代、デザイナーの「次」
blog

AI時代、デザイナーの「次」

近年、AIを活用したデザインツールが急速に進化する中で、デザイナーの役割について考える機会も増えています。 以前は、画面を直接設計し、コンポーネントを制作することがデザイナーの中心的な業務でした。しかし今では、AIが短時間でかなり完成度の高いUIを生成する時代になりました。AIがますますそれらしい画面を作り出すのを見ていると、自然と次のような疑問が浮かんできました。 「UIを作ることがますます簡単になるとしたら、これからのデザイナーの競争力は何になるのだろうか?」 ちょうど最近携わることになったプロジェクトは、こうした悩みを直接実感できる経験でした。企画画面はAIを通じて制作されており、私はその画面を検証しながらプロジェクトに参加することになりました。 最初は、AIが作成したUIの完成度を確認する程度だろうと考えていました。しかし実際に検討を進めるほど、関心は自然とUIからデータ構造やユーザー体験へと移っていきました。 そのとき、以前経験したゲーム会社の運営指標ツールをふと思い出しました。ゲームと教育サービスはまったく異なる分野に見えますが、運営者の視
7 min read
React Query Key Factoryパターンを使ってみた
blog

React Query Key Factoryパターンを使ってみた

1. はじめに:クエリキーが重要な理由 React Query(TanStack Query)を初めて導入すると、ほとんどの場合はこのように始めます。 useQuery({ queryKey: ['product-list'], queryFn: fetchProducts }); useQuery({ queryKey: ['product', productId], queryFn: () => fetchProduct(productId) }); useQuery({ queryKey: ['project-health', productId], queryFn: () => fetchHealth(productId) }); コンポーネントが数個しかないうちは問題ありません。しかし、ドメインが増え、チームメンバーが増え、機能が積み重なると、ある時点で次のような状況に直面します。 * 「product関連のキャッシュをすべて削除したいけど、キーはどこにあるんだ?」 * 「['product
4 min read
LLMコーディングエージェントのタスク管理方法
blog

LLMコーディングエージェントのタスク管理方法

- Task/Plan Harness 適用記 - 1. はじめに 近年、開発業務においてLLMベースのコーディングツールを使用する割合がますます高まっています。私もプロジェクト作業の生産性を高めるためにCodexを使い始めました。最初は一般的な方法で使用していました。必要な作業をプロンプトで説明し、LLMが作成した結果を確認したうえで、不足している部分を再度依頼するという方法です。簡単な修正や反復作業では、この方法だけでも十分に効果がありました。 しかし、作業規模が大きくなるほど、単純なプロンプト方式には限界がありました。プロンプトを長く書いても、LLMは作業全体を安定して管理できず、作業時間が長くなると、前に合意した内容や以前の変更意図を見失うことがありました。最初は、私がプロンプトをより詳しく書けば解決できる問題だと思っていました。しかし実際には、プロンプトの問題というより、作業を管理する構造が不足している問題に近いものでした。 この記事では、LLMベースの開発作業で私が経験した問題と、それを解決するためにTask/Planハーネスを適用した過程を
13 min read
メガソフトウェア時代の暗黙知プラットフォーム
blog

メガソフトウェア時代の暗黙知プラットフォーム

序論:ソフトウェアパラダイムの大きな変化 人類の技術発展の歴史は、道具の進化と、それに伴う成果物の規模拡大という一貫した法則に従ってきました。かつての大工は、職人として培った熟練の経験に頼り、手 hammerと片刃のこぎりだけで家を建てていました。この時代の建築は、徹底して個人の能力に収束しており、完成した建築物も小規模な戸建て住宅や村の小さな倉庫の水準を超えることは困難でした。一つの建物を完成させるために費やされる絶対的な時間と労働力の効率も、極めて低いものでした。しかし産業革命を経て現代に至り、建築用具がクレーン、掘削機、コンクリートポンプ車のように高度化・精密化されるにつれて、建築の様相は完全に一変しました。今日、人類はもはや数十坪規模の平屋木造住宅にとどまらず、数千世帯が同時に居住する大規模マンション団地や、数百メートルの高さを持つ超高層ビル、さらには巨大なインフラを備えた仮想都市まで建設しています。これらの巨大な都市建築物には、過去の hammerとのこぎりでは想像すらできなかった複雑性、安全性、そして有機的な管理体系が求められます。 ソフトウェア工学
12 min read
Text2SQL構築記
blog

Text2SQL構築記

近年のAI技術の発展に伴い、データの活用方法にも大きな変化が起きています。私が進めているプロジェクトでも、LLMを活用したさまざまな機能に対する要件やアイデアが次々と出ています。 その中でも、ビジネス現場から寄せられる数多くのデータ抽出リクエスト(Ad Hoc)を、いかに迅速かつ正確に処理するかという課題を解決するため、「Text2SQL」技術の最新動向を調査し、プロジェクト導入に向けた検討内容を共有したいと思います。 1. 問題:開発者に蓄積する負債と意思決定のボトルネック 私たちのプロジェクトを含む、ほとんどのデータ活用組織で共通して経験する場面があります。 - 「このような条件の受講生が何人いるのか、クエリを1つ作成してください。」 - 「先週の研修実績データが必要なのですが、いつ頃受け取れますか?」 問題は、このような依頼が単発の1〜2件ではないという点です。開発者は実際の分析やモデリングよりも、単純なクエリ作成に時間を費やすことになり、依頼する顧客や企画担当者の側では、意思決定のために結果を待たなければならないボトルネックが発生します。
5 min read
React Nativeハイブリッドアプリ入門
blog

React Nativeハイブリッドアプリ入門

1. はじめに a. なぜハイブリッド構成なのか ReactのWeb開発者が初めてReact Nativeに触れるとき、最初に直面する悩みは「既存のWebをどこまで再利用できるか」です。モバイルアプリを作るからといって、すべての画面とビジネスロジックをReact Nativeで書き直す必要はありません。すでにReact Webアプリケーションにルーティング、権限処理、状態管理、API連携のフローが整っているのであれば、それをReact Nativeアプリ内部のWebViewで実行するハイブリッド構成も現実的な選択肢になります。 この構成は、Webとアプリの役割を分担する方式です。Webアプリケーションは既存の画面とドメインロジックを維持し、React NativeアプリはWebViewを包むネイティブシェルの役割を担います。ネイティブシェルは、認証情報の保存、スプラッシュ画面、ネットワーク状態の検知、Androidのハードウェア戻るボタン、安全領域の処理など、モバイル環境に近い機能を担当します。 ただし、WebViewを使うからといって、Webのアドレ
11 min read
Site footer