AIツールと奮闘記(だいたい実話) その二 〜愛に包まれてしまった処理〜

前回書いている途中で自分が入眠してしまったため続きを書いている入眠用記事担当です。

さて、前回伝え方が悪いのかいきなり全体から違うコードに書き直されて面食らいましたが、気を取り直して進めました。
一度AI側のコードをさらっとチェックして、特に問題が見つからなければテスト環境にdeploy => 出力結果が違えばその箇所を調べて再度AIに修正依頼
を繰り返していたものの、一向に出力結果が思う通りになりません。

( ◜ω◝ ): う〜む、どうも上手くいかんのう...。
( ◜ω◝ ): そう言えばチャット形式のAIて、「基本前回の内容を覚えていない」って聞いたな...。まだあのまんまなんやろか?

しかし某GPT先生の"メモリ"を参照してみると、散々伝えた「修正したい箇所・内容」や細かい仕様も一応入っている様でした。これを消したらそもそも意味無いはず。
AI側には仕様は記録されている前提でとりあえず進めて行ったのですが、ある段階で今度は「Aは正しいのにBを間違う」「Bの問題点を指摘し修正を依頼すると今度はAを間違う」という事態のループに陥ります。

( ◜ω◝ ): 項目Aの値は正しいのですが、項目Bの値がこちらで手動で集計した値と異なっており、正しくありません。
( ◜ω◝ ): 恐らくコード内のxxxの箇所の集計条件が正しく適用されていないと思われます。ここを修正して項目Bの値も正しくなる様にしてください。
[▣🝙▣]: 指示通りxxxを修正しました(長文+絵文字で逐一解説入り)。

( ◜ω◝ ): 今度は項目Bの値が正しくなりましたが、項目Aの値が全部0になってしまいました...。
( ◜ω◝ ): 仕様としては項目Aの値の条件はxxx、項目Bの値の条件はxxxなので、単純に⚪︎⚪︎⚪︎をxxxの条件で集計する様にすれば問題ないはずです。
[▣🝙▣]: 指示通りxxxを修正しました(長文+絵文字で逐一解説入り)。

( ◜ω◝ ): また項目Aの値が正しくなったのに、項目Bの値が変になった...。
( ◜ω◝ ): 問題箇所はxxxの部分なんやから、ここを中心に修正してくれればええんやけどな...。
( ◜ω◝; ): あんまり細かく書き過ぎても精度は上がらんとも聞くし、かと言って大雑把に書くとすぐ勘違いされる様な気がする。

指摘しては修正ループを繰り返していた時、突然見たこともないクエリが入った1文を含むコードが返答されました。
説明はありましたが念の為SQL側の公式ドキュメントを探ると、確かに存在する関数の様です。

( ◜ω◝ ): ほう...。この様なSQL関数を使えばこういう事が出来るのか...。
( ◜ω◝ ): こんなんあるんなら最初からコレで書いてくれれば良いのに。
( ◜ω◝ ): まあいい。要件で使われているバージョンは結構古くて制限多いから、多少分かりづらいコードになっても使えるもんは使おう。

さらっと一通りチェックしたところ、他の箇所にも問題は無さそう...。

( ◜ω◝ ): カラムとかjoinも問題無さそうやな。これで一回実行してみるか。
( ◜ω◝ ): これで上手く行けば、ようやく一山越えるな...。

期待を胸にいざテスト環境にdeployし、画面を起動。
...
( ◜ω◝ ): アッー!めっちゃ重い。システム落ちちゃうかも... => 慌てて実行をキャンセルし事なきを得る

今度はプログラムから生成されるSQLのパフォーマンスに問題があることが判明。

( ◜ω◝ ): まあ元々既存のシステム内には無い処理の仕方してるからなあ...。結構無理してるから仕方ないっちゃ仕方ないが...。
( ◜ω◝ ): しかしSQLのパフォーマンスとか最近気にした事無いしな...。
( ◜ω◝ ): AI先生はそういうのもやってくれるんやろか?

( ◜ω◝ ): 教えて頂いたコードを元にプログラムを修正・実行してみたところ、発行されるSQLのパフォーマンスに問題がある様です。
( ◜ω◝ ): このプログラムが集計対象とするデータの数は、凡そxxx件です。極力現在の処理内容を維持しつつ、パフォーマンスを改善する方法はありますか?
[▣🝙▣]: はい、可能です。こちらがパフォーマンスを改善したプログラムです(長文+絵文字で解説入り)。

( ◜ω◝ ): 勝手にクラスが追加されとるがな。
( ◜ω◝ ): しかも今までのコード全体(中身は殆ど変わっていない)が、優しくふんわりと別の関数に包まれとる。
( ◜ω◝; ): ...これ何の意味があるの?

果たしてGPT先生の「可能です」は本当なのか。
何故、コード全体を関数で包んでしまったのか。
悩んでいるうちに微かに頭の先端から何かが焦げる様な匂いがしてきました。
to be continued...?
(まだ引っ張るの...?)

AIツールと奮闘記(だいたい実話) その一

働くだけの毎日で遊びや個人の自由に振れる時間が大幅減少した結果、「何をやっても楽しくない」「休みの日も仕事が気になって楽しめない」負のループに陥ったことに最近気付いた入眠用記事担当です。
既にビョーキだと思うんですが、これ労災おりませんかね?おりませんよね。

密かに続けていた(というか途中で無理矢理こじつけた)3文字略語シリーズが一旦ネタ尽きたので、苦し紛れに書いてます。

今回のお題は「AI」。
何周遅れの何番煎じだよって?まあ寝る為の記事なんで気にしないでください。

さて、3年前ぐらいの最初の「AI凄い」ブームでチャット形式のUIが登場した頃に実は早速飛びついてみた入眠用記事担当ですが、その頃は結構厳しめな文字数制限のため「AIに仕事で使うコードを書いてもらう」という用途はあえなく断念し、細々と今まで通り自力でコードを書いていました(APIなども試してごちゃごちゃやっていましたが、もう環境構築に時間取られるより自分で書いた方がいいや、とか考える前に色々仕事自体の納期も迫っていたので...)。
しかしあれから数年後...
相変わらず皆さんAIにはご執心な模様で、一部技術系界隈では盛り上がりが続いていました。
「最早AIを使わないプログラミングなど考えられない!」
「人間が気付かないところまで細やかに指摘してくれるAIは超有能!」
「もう話し相手もAIでいい!」 => (え・・・( ◜ω◝ )???)

な、なんですと?
そんなに凄くなっとるの?
世間の煽りにまたしても乗せられ、これは再チャレンジするしかないか...と、妙な焦りも感じ始めた私。

とは言え、そもそもプログラミングには普通のモデルじゃなくて「それ専用」にチューニングされているものがあったはず...。
でもアレ確か有料だったよな(ついでに名前ド忘れした)...。
少しでも試してからでないと不安だわ...。

ということでまずは以前登録していたアカウントで某GPT先生を頼ってみることに。
既に大まかな部分は自力で作っていたプログラムの難関部分を"爆速"で仕上げてもらうべく、
(ある程度問題の箇所は特定出来ているから、後は"少々手直ししていくところ"ぐらいなら手伝わせても問題ないはず、という判断もあって)
当然社外秘な所やシステム特有の部分はリダクトしプロンプトの書き方(これ意外と時間食うけど)も調べて、いざ投入。
実際にはプロンプトも返答も結構長文なのですが、概ね以下の様なやりとりが始まりました:

[▣🝙▣]: ご要望通りxxxを修正しました(実際は長文+絵文字で逐一解説入り)。
( ◜ω◝ ): おや...いきなりコード全体の書き方が大幅に変わってしもうたぞ...てかこんな処理いらんし...。

どうやら「コードのスタイルは維持したまま」と一々伝える必要がある模様。

( ◜ω◝ ): すみません、提供したコードのスタイルは維持したままで、このプログラムのxxxの箇所を、⚪︎⚪︎⚪︎の出力結果となる様に修正・調整してください。
[▣🝙▣]: 提供された仕様に沿って、xxxの箇所を修正しました。 => なんか"それっぽい"コードが出て来た

( ◜ω◝ ): お、意外と行けるんやない?

しかし当然このままテスト環境にdeployするわけには行かないので、一応チェック...(私も「AIが書いたコードだから間違いありません!動かなくても修正出来ません!」で済むなら済ませたいもんです...)。

( ◜ω◝ ): む...やはり誤り発見。てか何?この1行...。
( ◜ω◝ ): この1行があると⚪︎⚪︎⚪︎の結果がxxxになってしまうと思われるのですが、何故この1行を追加したのでしょうか?
[▣🝙▣]: 失礼しました。仕様の「xxxの箇所を、⚪︎⚪︎⚪︎の出力結果となる様に」というところを、xxxの可能性を考慮していないコードになっていました。修正しました。

( ◜ω◝ ): なるほど、伝え方が悪かったんやな。じゃあ次はもっと細かく仕様書かんとな。

そう内省しつつ修正されたコードをチェックすると...

( ◜ω◝ ): ん?「修正しました」ってどこを???問題の箇所もさっきと同じ1行にしか見えんのやけど...。
( ◜ω◝ ): ...変数名がtblからtbに1文字変わっとるが...まさかこれのことじゃあるまいな?
( ◜ω◝ ): すみません、このコードだとxxxの処理を行う箇所が先程と変わっていない為、恐らく出力結果も変わらないと思うのですが...。
[▣🝙▣]: 失礼しました。修正しました(さっきと同様の長文+絵文字を使った解説付き)。

( ◜ω◝ ): お、コードがちょいと変わったぞ。どれどれ...。
( ◜ω◝ ): これ、わしが最初に書いた「手直しが必要な部分」とおんなじやん...。
( ◜ω◝; ): ...なんでやねん念...。

to be continued...
(え?続くの?...)

API(3文字略語シリーズ最終回?)

最近いい事無さすぎて、「何かええ事ないかな〜」が口癖になった入眠用記事担当です。
あまりに無さすぎて道行く人にすら「何かええ事ありません?」と聞いてしまいそうです。
暇じゃないんですよ。その逆です。貧乏暇なし。
という訳で今日もノルマ達成と皆様の仮眠に貢献する為に、せっせと眠たい記事を書きます。

さて今回はAPI(Application Programming Interface)
文字通り「アプリケーションがプログラムを通じて情報をやり取りするためのインターフェース(接点)」です。もっと簡単に言えば、ソフトウェアやプログラム、Webサービス同士が互いに情報を交換したり、機能を呼び出したりするための「窓口」や「ルールブック」のようなもの...ですかね?(例えが合ってるか怪しい)。
例えば、あなたが天気予報アプリを開いたとき、そのアプリは気象庁や天気情報提供会社のAPIを「叩いて(呼び出して)」最新の天気情報を取得し、私たちの画面に表示しています。アプリ開発者は、天気情報の収集や解析の仕組みをすべて自前で用意する必要はなく、APIを通じて必要な情報だけを効率的に入手できるのです。

APIは基本的にプログラマにとっては便利なものです。

1. モジュール化と再利用性の向上: 機能ごとにAPIを定義することで、システムを独立したモジュールに分割できます。これにより各モジュールの開発・テストが容易になり、他のシステムでも同じ機能を再利用しやすくなります。
2. 関心の分離: 例えばフロントエンド(ユーザーが見る画面)とバックエンド(データ処理やビジネスロジック)をAPIでつなぐことで、それぞれが独立して開発を進められます。フロントエンドエンジニアはUI/UXに、バックエンドエンジニアはサーバーサイドの処理に集中できるのです(たぶん)。
3. 開発効率の向上と並行開発: 明確なAPI仕様があれば、複数チームや複数人が同時に異なる部分を開発しても、スムーズな連携が可能です。これにより、開発スピードを大幅に向上させることができます。あくまで「明確な仕様があれば」の話ですが。
4. 外部サービスとの連携: Google Maps APIやTwitter APIのように、既存の優れた外部サービスが提供する機能を自社のアプリケーションに簡単に組み込めます。これにより、開発コストを抑えつつ、リッチな機能を提供できます(店舗様のサイトでもGoogle MapのAPIを利用してお店の位置やお店までの道のりをご案内したり、Xを埋め込んでお店のニュースやその他情報を発信されていますね。まさにアレです)。

APIを提供する側(設計する側)になった場合、その「使いやすさ」が非常に重要です。良いAPIは直感的で理解しやすく、開発者が迷うことなく利用できるものです。具体的には...
・命名規則: エンドポイント名やパラメータ名が分かりやすいこと。
・リクエストとレスポンス形式: JSONなど標準的で扱いやすいデータ形式を採用すること。
・HTTPメソッドの適切な使用: RESTful APIであれば、GET(取得)、POST(作成)、PUT(更新)、DELETE(削除)などを正しく使い分けること。
・バージョニング: APIの変更に備え、バージョン管理を適切に行うこと。
・エラーハンドリング: エラー発生時のレスポンスが明確で、原因究明に役立つこと。
・ドキュメンテーション: APIの仕様、使い方、認証方法などをまとめたドキュメントが整備されていること。
これらの要素を考慮することで、利用者に優しい、そして開発者自身にとっても保守しやすいAPIが生まれます。

APIは現代のソフトウェア開発において、異なるシステムやコンポーネントを繋ぐ「共通言語」であり、効率的で柔軟な開発を実現するための基盤技術です。APIを効果的に設計し活用する能力はエンジニア/プログラマにとってますます重要なスキルとなっています。

とまあ月並みな事を書きましたが、上記のGoogle Mapなどの例にある様に、基本的には店舗様の御目に触れる様なものではありません。

MVC、CMS、ORMと"アルファベット3文字の略語絡みでどこまで退屈な記事を生産し続けられるか"チャレンジも、そろそろネタ切れの様です。
何かええ事ないかな。

ORM(言い尽くされた話題でお茶を濁すの巻)

毎度ネタに悩んではロクな事を思い付かず、結果眠たい(当たり障りない)記事にならざるを得ない入眠用記事担当です。
さて今回もノルマ達成のためにせっせと眠れる記事を書きます。

今回のお題は「ORM(Object-Relational Mapper)」。
(一応弊社Fu-Kakuで利用されていますしこの手の話題に賛成派・反対派がいるのはいつもの事なのですが、記事書くために色々調べているともう早速お題にしたのを後悔しています。)
ORMはオブジェクト指向プログラミング言語とリレーショナルデータベースの間の「通訳」のような役割を果たし、データベース操作をより直感的かつ安全に行えるようにするツールです。多くのフレームワークで採用されており、現代のアプリケーション開発において欠かせない存在となりつつあります。
しかしORMは万能薬ではありません。メリットがある一方で思わぬ落とし穴も存在します。今回はORMのメリットとデメリットを深掘りし、どのような場合にORMが有効なのか、あるいは避けるべきなのかを考察していきたいと思います。

まずORMが開発現場にもたらす主なメリットを見ていきましょう。

1. データベース操作の抽象化と生産性の向上:
ORMを利用する最大のメリットはSQLを直接記述することなく、使い慣れたプログラミング言語のオブジェクトとしてデータベースのテーブルやレコードを操作できる点です。これにより、INSERT、UPDATE、DELETEといった定型的なCRUD処理の記述量が大幅に削減され、開発者はビジネスロジックの実装に集中できます。例えば、新しいユーザーを登録する場合、SQLならINSERT INTO users (name, email) VALUES ('山田太郎', 'yamada@example.com');のように記述する必要がありますが、ORMならuser = User(name='山田太郎', email='yamada@example.com'); session.add(user); session.commit();といった具合に、よりオブジェクト指向的なアプローチで記述できます。
2. データベースの種類への依存性の低減:
多くのORMは、MySQL, PostgreSQL, SQLite, SQL Serverなど、複数のデータベースシステムに対応しています。ORMがデータベースごとのSQL方言の違いを吸収してくれるため、理論上はアプリケーションコードを変更せずにデータベースシステムを切り替えることが可能です。プロジェクトの初期段階でデータベースが未確定な場合や、将来的な移行の可能性がある場合に大きな利点となります。
3. コードの可読性と保守性の向上:
SQLが散在するコードに比べ、ORMを使用するとデータアクセスロジックがモデル(オブジェクト)に集約されるため、コード全体の可読性が向上します。また、テーブル定義の変更があった場合でも、ORMのモデル定義を修正するだけで済むことが多く、修正箇所が明確になり保守性も高まります。
4. 静的型付け言語との相性の良さ:
JavaやC#、TypeScriptのような静的型付け言語とORMを組み合わせることで、コンパイル時に型チェックの恩恵を受けることができます。これにより、カラム名のタイポやデータ型の不一致といった単純なミスを早期に発見でき、コードの堅牢性が向上します。
5. セキュリティリスクの低減:
ORMは、パラメータ化クエリを適切に使用することで、SQLインジェクションのような一般的なセキュリティ脆弱性のリスクを大幅に低減してくれます。開発者が意識せずとも、安全なデータベース操作が実現できるのは大きなメリットです。

はい。色んな記事でよく書かれている話ですね。


一方で、ORMの利用には注意すべきデメリットも存在します。

1. 学習コスト:
ORMは便利なツールですが、それ自体がひとつの抽象レイヤーであるため、独自の概念や使い方、設定方法などを習得する必要があります。また、内部でどのようなSQLが発行されているのかを理解しておかないと、思わぬパフォーマンス問題を引き起こす可能性があります。
2. パフォーマンスのオーバーヘッド:
ORMが自動生成するSQLは、必ずしも人間が手で書いたSQLほど効率的であるとは限りません。特に複雑なクエリや大量のデータを扱う場合、ORMの抽象化レイヤーがオーバーヘッドとなり、パフォーマンスが低下することがあります。N+1問題などは、ORMを利用する上でよく遭遇するパフォーマンス問題の一つです。
3. ブラックボックス化のリスク:
ORMがデータベースアクセスを抽象化してくれる反面、実際にどのようなSQLが実行されているのかが分かりにくくなる「ブラックボックス化」のリスクがあります。問題が発生した際に、原因の特定やチューニングが困難になるケースも少なくありません。ORMのログ機能などを活用して、発行されるSQLを常に意識することが重要です。
4. ORMの限界とSQLの必要性:
非常に複雑なクエリや、データベース特有の機能を利用したい場合など、ORMだけでは対応しきれないケースも存在します。そのような場合は結局生のSQLを書く必要が出てきたり、ORMの制約の中で妥協したりする必要が生じます。ORMが提供する機能の範囲を理解しておくことが重要です。
5. 不適切なマッピングによる問題:
オブジェクトとリレーショナルデータベースの間のインピーダンスミスマッチ(設計思想の違いからくる非互換性)を完全に解消することは難しく、不適切なマッピング設定はパフォーマンスの低下や予期せぬ挙動を引き起こす可能性があります。

これらもまあよく聞く話です。


何でもそうである様に、ORMにも(ざっと思い付く程度では)こうしたメリット・デメリットがある訳ですが、実際どういうケースなら「使うのもアリ」になるかと言うと...
・小〜中規模のCRUD処理が中心のアプリケーション: このようなケースでは、ORMの生産性向上のメリットがデメリットを上回ることが多いでしょう。特にスタートアップなど開発スピードが重視される場面では強力な武器となります。
・パフォーマンス要件が非常に厳しいシステム: 金融取引システムや大規模なリアルタイム分析基盤などミリ秒単位の応答速度が求められるシステムでは、ORMによるオーバーヘッドが許容できない場合があります。このような場合はSQLを直接記述するか、パフォーマンスを重視した軽量なORMを選択するなどの検討が必要です。
・複雑なデータ分析やバッチ処理: 大量のデータを扱うバッチ処理や複雑な結合・集計を伴うデータ分析では、ORMが生成するSQLが非効率になる可能性が高まります。このような処理はSQLで最適化した方が良いケースが多いでしょう。

...とまあ、こんな感じでしょうか。ありきたりですね。
Fu-Kakuにも当てはまるっちゃ当てはまるし、そうでないかもしれないところもあると言えます。

今回も書いていて自分で読み返すうちに強い眠気に襲われたので、その役目だけは一応果たしている様です。

CMSにおけるデータベース設計のポイント

前回に引き続き、店舗様の実運用にはあまり(というか全く)関係の無いお話をさせていただきます。
入眠剤としてご利用ください。

CMS(コンテンツ管理システム)は、Webサイトのコンテンツを効率的に管理・公開するための強力なツールです。しかし、その性能と拡張性は背後にあるデータベース設計に大きく左右されます。適切なデータベース設計は、CMSのパフォーマンスを向上させ、将来的な機能拡張にも柔軟に対応できる基盤となります。

1. データベース設計の基本原則
CMSのデータベース設計では、以下の基本原則を考慮することが重要です。
正規化: データの重複を排除し、整合性を保つために、テーブルを適切に分割します。正規化により、データの更新や削除時の矛盾を防ぎ、データベースの効率を高めます。
インデックス: 検索やソートを高速化するために、適切なカラムにインデックスを設定します。インデックスは、データベースのパフォーマンスを大幅に向上させる効果があります。
データ型: 各カラムに適切なデータ型を選択します。これにより、データの整合性を保ち、ストレージ効率を高めます。
リレーションシップ: テーブル間の関連性を適切に定義します。これにより、複雑なデータ構造を効率的に管理できます。

2. CMSデータベース設計の重要ポイント
CMSのデータベース設計では、以下のポイントを考慮することが特に重要です。
コンテンツの構造: 記事、ページ、画像などのコンテンツタイプごとに、必要なカラムとリレーションシップを定義します。コンテンツの構造を正確にモデル化することで、柔軟なコンテンツ管理が可能になります。
メタデータ: コンテンツのメタデータ(作成日、著者、カテゴリなど)を適切に管理します。メタデータは、コンテンツの検索、分類、表示に不可欠です。
バージョン管理: コンテンツの変更履歴を管理します。バージョン管理により、過去のバージョンへの復元や変更履歴の追跡が可能になります。
ユーザー管理: ユーザーアカウント、権限、ロールを適切に管理します。ユーザー管理は、セキュリティとコンテンツ管理の効率化に不可欠です。※ちなみに弊社Fu-Kakuでは、それぞれの権限レベルのユーザーに対しメニューの各画面毎にアクセス制限を設定することが可能です。

3. パフォーマンスと拡張性を考慮した設計
CMSのデータベース設計では、パフォーマンスと拡張性を考慮することが重要です。
キャッシュ: 頻繁にアクセスされるデータをキャッシュすることで、データベースの負荷を軽減しパフォーマンスを向上させます。
スケーラビリティ: 大量のデータやトラフィックに対応できるスケーラブルな設計にします。スケーラビリティは、将来的な成長を見据える上で重要です。
セキュリティ: データベースへの不正アクセスを防ぐために、適切なセキュリティ対策を講じます。セキュリティは、CMSの信頼性を維持するために不可欠です。

4. まとめ
CMSのデータベース設計は、その性能と拡張性を大きく左右する重要な要素です。適切なデータベース設計により、CMSのパフォーマンスを向上させ、将来的な機能拡張にも柔軟に対応できる基盤を構築できます。CMSのデータベース設計では、正規化、インデックス、データ型、リレーションシップなどの基本原則を考慮し、コンテンツの構造、メタデータ、バージョン管理、多言語対応、ユーザー管理、プラグイン/拡張機能などの重要ポイントを適切に設計することが重要です。また、パフォーマンスと拡張性を考慮し、キャッシュ、スケーラビリティ、セキュリティなどの対策を講じることも重要です。

これらは所謂「教科書的な」原則やポイントではありますが、弊社Fu-Kakuシステムにおいても例外ではなく、これらの基礎の上に様々な要件とそれに対応した設計・実装が積み重なっています。Fu-Kakuがお客様のご要望にお応えし機能拡張を行い常に進化し続けられるのも、正にこうした基盤があるからなのです。

さて、いかがでしたでしょうか。
ここまで読んでも眠気に襲われない方がいらっしゃいましたら、実際に入眠剤を試してみられるのも良いかもしれません。
或いはこういうのチョット勉強してみるのも良いかも?

BACK TO TOP