ラベル WEB系ネタ の投稿を表示しています。 すべての投稿を表示
ラベル WEB系ネタ の投稿を表示しています。 すべての投稿を表示

2025年9月10日水曜日

CreatedAtにトリガーで対応するという技(?)についてAIに教わりました

 あるツール的なWEB APIを作っていたのですが、

テーブルを定義していて、いつものようにCreatedAt、UpdatedAt、などを作っていました。

わたしはこのやり方はあまり好きではなく、テーブルにいつ誰が作ったか、更新したかを見るのであれば、ログに残せばいいと考えています。


しかしながら、ある現場でCreatedAt、UpdatedAt、CreatedUser、UpdatedUserのようなカラムを全テーブルに持っているプロジェクトがあったので、今回はそれに倣ってやってみようと気軽に考えて、コードの生成をAIにお願いしてみました。

わたしはVSC+Geminiの組み合わせでやってますが、いつものようにGemini君はReadme.mdに書かれた通りの仕様で大体一発でコードを生成してくれました。


で、気になったのがこれ

-- updated_atを自動更新するためのトリガー

CREATE OR REPLACE FUNCTION update_updated_at_column()

RETURNS TRIGGER AS $$

BEGIN

   NEW.updated_at = NOW(); 

   RETURN NEW;

END;

$$ language 'plpgsql';


CREATE TRIGGER update_products_updated_at

BEFORE UPDATE ON products

FOR EACH ROW

EXECUTE FUNCTION update_updated_at_column();


ようするにトリガーでupdated_atにNOWを設定するトリガーを作り

productsのUpdateがあった際に動くようにしているという点です。


これを見たときに、INSERTではトリガーが動かないなと思ったのですが、INSERT時には、テーブル定義でDEFAULT CURRENT_TIMESTAMPが設定されているため、Created_AtもUpdated_Atも同じ時刻が入ります


で、実際更新するときは、管理画面的なところから更新するのでしょうが、

その際は、トリガーが動いて更新日付が更新されるという挙動になります。


更新する際にプログラム側から日付を入れればいいじゃんと思うのですが、トリガーとして動く仕組みのいいところ悪いところをAIに聞いてテーブルを作ってもらいました


観点データベースのトリガーアプリケーション側のロジック
データ整合性◎ 非常に高い (更新漏れがない)△ 低い (更新漏れのリスクがある)
保守性○ (ロジックが一元化)△ (コードが分散・重複する可能性)
DB独立性△ (DB製品に依存)◎ 高い (DBに依存しない)
可視性△ (コードからは見えない)○ (コードで明示的に記述)
パフォーマンス○ (ほぼ影響なし)◎ (トリガーのオーバーヘッドがない)

結論として、created_atupdated_atのようなメタデータの管理には、データベースのトリガー(またはDEFAULTON UPDATE句)を使用するアプローチが強く推奨されます。

データの整合性を担保できるというメリットは、他のデメリットを大きく上回ります。現在のプロジェクトの実装は、このベストプラクティスに従っており、非常に堅牢な設計と言えます。


ぶっちゃけですね、アプリケーション側でやった方が◎が多いんです

しかも△の数も同じです

これでなぜAIがトリガーを強く推しなのかというと、データの整合性の◎はちょっとレベルが違うくらいな◎だということらしいです。


なお、このようにPros/Consをまとめて、同じレベルのものはPros/Consから削除するという手法は、フランクリンがやっていた手法です


まぁ納得いかない人もいるし、別の考えの人もいることでしょう

わたしはモヤッてます





2024年6月29日土曜日

JavaScriptでゲームエンジン作ってみた

ゲームエンジン作ってみた
出てきた芽をつつくと昇天する

プログラムで、芽が突かれたらと言う判定をしていると言うよりは芽が自分が突かれた時の処理として昇天するアニメへ切り替えている
つまり、プログラムが制御すると言うよりは
オブジェクトが自分のシナリオデータに沿って動く
オブジェクト指向であり、データドリブンと言うのはこう言うことだと言う例にもなっている
マウスのクリック効果は録画ソフトがつけているので ゲームエンジンで出してるわけではない (やろうと思えばすぐにできる) まだフレームレートの計算でよくわからないところがあって、 適当に調整してしまったんだけど まぁ動いてるからとりあえずいいか・・・ 計算合わないのがすっごい気持ち悪いんだけど・・・ アニメーションはAsepriteで作った 上に飛ばすときにもう一度クリックすることもできてしまうので、判定処理を抜くルーチンを実装してやらないといけない まぁゲームエンジンは大体できてきた


どうもゲームエンジンというものがどういう物かわからないという声が出てくるので説明しておく 画面に絵を表示するとき 絵は矩形で描画する サイズは32x32,16x16など、都合のいいドット数であることが多い 描画するときにX,Y座標を指定するが、 X,Y位置に左上を合わせて描画するのが左上基点 X,Y位置に画像中心を合わせて表示するのが中央基点 X,Y位置に画像の左右中央下端を合わせて表示するのがベース中央基点 まぁ呼び方なんかどうでもいい ベース中央基点は、対戦格闘などでよく使う方法で、キャラクターの地面の立ち位置を基点にして表示する方法だ この方が画面の左右スクロール時に位置がどこなのか考えやすい だが、中央もよく使う 例えば、マウスクリックしたところから四方八方に光を散らせるパーティクル効果を表現するときは、雪の結晶のような画像をX,Y位置に画像中心を合わせて描画する このように都合に合わせて、どこを基点に表示するのか変わってくる これらをプログラムで一々調整するのではなく、Asepriteなどのアニメーションデータで雪がチラつくようなアニメーションを組み、それを再生させながら四方八方に散らせて、最後はアニメーションの透明度で消えていく という制御を、画像側主体で動かすのがゲームエンジンの基本的な考え方だ つまり、画像が自分で自分の次のフレームの画像を切り替え、自分の位置を切り替える プログラムはその切り替えるアニメーションパターンや、四方八方に飛び散る物理演算を設定するだけで、あとは画像側が勝手に動く わたしが先に示した草を引っこ抜くゲームエンジンの例では 「Mebae」「Idle」「Pickup」のアニメーションパターンをAsepriteで作っている


インターバルで草を生成するルーチンは以下2つの指定をしてスプライトを生み出している 1.MebaeからIdleまで再生し、Idleはループさせるという指定でX、Y位置をランダム生成してスプライトを生成している 2.その際、当たり判定を物理演算の一種として登録している。 マウスクリックに当たっていたら「Pickup」へ切り替え、「Pickup」が終わったらスプライトは自己消滅するように指定している 全体のスプライト数もわかるので、60個までで草を生み出すのを止めている

        function isPickUp(spr) {
            if (spr.isTouched()) {
                // Pickupが終わったら消えるように設定
                spr.setTagNames(["Pickup","DIE"]);
            }
        }

        function getRandomInt(max) {
            return Math.floor(Math.random() * max);
        }

        async function dispatch() {
            // 最大60個にしておく
            if (gPrim.primitives.length <= 60) {
                // 乱数で座標を生成
                var x = 32 + getRandomInt(640 - 64);
                var y = 32 + getRandomInt(480 - 64);
                // ["Mebae", "Idle","REPEAT"]のように指定すると、Mebae、Idleの順に実行した後、Idleをリピートする
                // ["Mebae", "Idle","DIE"]の場合はIdleを実行した後Spriteが消える
                var sp = await Sprite.build("Futaba", jsMebae, ["Mebae", "Idle","REPEAT"], x, y, 1, 0);
                sp.addPhysic(isPickUp);
                gPrim.append(sp);

                console.log("dispatched", x, y)
            }
            nextTime = 3 + getRandomInt(5) * 1000;
            setTimeout(dispatch, nextTime);
        }


さて、ゲームエンジンは画面の表示位置だけを担当するのではない 当たり判定、繰り返し、消滅、親子関係(親に追従するかしないかの指定も可)などのほかに、音声再生なども行う 例えば、何もないスプライトを親にして、その子供としてダンジョンマップを登録する 上下左右の移動で、何もない親スプライトの位置を変えれば子供の位置が全部変わる つまりマップがスクロールする 例えばぷよぷよのぷよが、自分の上下左右に自分と同じぷよがいるかどうかを調べ、自分の体を変形させる(その際、変形用アニメも用意されていればスムーズに変形する) こういった、例えばをプログラムだけでやることの愚かさがわかるだろうか? ゲームエンジンを使えば、スプライトが自分で考えて自分の姿形を変え、消滅したり、新たなスプライトを生む出したりもできる ゲームエンジンのシナリオデータだけで、自分がやられたら、子供をたくさん生み出すような敵も作れる 子供は子供の攻撃パターンで動くこともできる 物理エンジンの一種として登録させることができる ゲームエンジンがあれば、
これらを全部同時に動かすことができる
RPGもシューティングも格闘ゲームもパズルも同じ組方で実装できる
ゲームの仕事が来た時に
その都度似たようなプログラムが組みたいならやればいい
わたしはその機種ごとにゲームエンジンを作ってからゲームを作る

ブラウザでよいのなら、ブラウザに特化したゲームエンジンを作り、
スマホにも対応させればよい
G123など、すでにやっているではないか?
あれを作ればいいだけのことだ

 

2014年1月17日金曜日

ajaxplorer から pydio へ

重宝している ajaxplorer だが、いつの間にか pydio という名前に変わったようだ。
iPhone 用のクライアントも pydio バージョンが出ている。

ところで、アップデートはそこそこ頻繁に行われているので、
気軽にアップデートしまくっていたのだが、
その間に、日本語のファイルやフォルダが作れなくなっていた。

まぁ、きっとどこかにlocaleあるんだろうなぁと思って検索したら、
bootstrap_conf.php のコメントに書いてあった。

conf/bootstrap_conf.phpに以下を追加すると良い。
//define("AJXP_LOCALE", "en_EN.UTF-8");
define("AJXP_LOCALE", "ja_JP.UTF-8");

コメントアウトしてるサンプル部分だが、
en_EN.UTF-8じゃなくて、
en_US.UTF-8じゃないのだろうか?
javaのプロパティと同じルールだと思うんだが・・・

2013年9月10日火曜日

ajaxplorer Version 5.0.3 - 2013-09-02

現在会社で使ってるドメインキングのレンタルサーバには空きがあるので、
ajaxplorerをセットアップしている。

以前レンタルサーバのPHPバージョンが古かったため、
仕方なく4.xx系のajaxplorerを使っていたのだが、
こないだちょっと気が向いて調べてみたら、いつの間にかPHPが5系になっているのに気がついた。

おいおい、いつからだよ、、、

そしたらajaxplorerも5系にしたいよねぇ?
ということでやってみた。

FTPでajaxplorerのフォルダごと書き込み権限くっつけて、
WEBブラウザからajaxplorerにadminでログインし、設定からUpgradeを選択した。
するといくつかのパッチが当たりますけどいいですか?と出る。
続行すると、何の苦もなくアップグレード完了

FTPで後から見てみるとなにやらやばそげなファイルのパーミッションはきっちり変わってる。
良く出来てるなぁ

インターフェースに関してははっきり言って以前の方がセンスあったように思う。
気がついた問題点としては、MBCSのフォルダを作成すると、フォルダ名が空状態になってしまっている。
作成自体はできているようなので、リフレッシュすると出てくる。
i18n問題が残ってると使う気がめっきり減ってしまうので、後で報告しとこうと思う。

2013年1月8日火曜日

ajaxplorerを入れてみた

以前、ajaxplorerをドメインキングのサーバに入れた事があるのだが、
そのときには、ファイル名の日本語が化ける事があって、
アップロード自体が失敗する事もあった。
ファイル名の先頭に半角の"-"をつけたり半角の"+"をつけたりすると、
アップロードが出来るとかいう訳のわからん状況だったのだが、
最近どうなっているのかと本家サイトを見てみたら、
かなり進化しちゃってるようではないですか?
http://ajaxplorer.info
なんとiOSクライアントもある。

ajaxplorerとは、
WEB上でエクスプローラーライクな操作で、ファイルのアップロード、ダウンロードが出来、ユーザーとロールも作れるので、このユーザーはこのロールでここまでしかアクセス出来ないようにするとかカスタマイズも出来る。

ようするにWEB上にドライブがあるような使い方が出来、ユーザ毎のアクセス権も設定出来る。
ここまで出来てしまったら、ガンガン使いますよ

DropBoxみたいに自動的にSyncするとか高等なことは出来ないけど、
普通に共有フォルダがあると考えればとても良い。
しかも容量はドメインキングのMプランだったら、
色々設定した残り容量だけでも40GB以上は使えるはず。

最新のajaxplorerは文字化け問題も無く、特に何をする事もなく普通にインストール手順に従ってインストールすればきっと動かせるでしょう。
唯一、PHPのアップロードサイズに制限があるので、
ajaxplorerのベースフォルダにある.htaccessを編集して、
自分は以下のように追記した。

php_value memory_limit 512M
php_value post_max_size 512M
php_value upload_max_filesize 512M
php_value max_input_time 800
php_value max_execution_time 800
まぁ大き過ぎると思うんで、もうちょっとサイズはしぼってもいいかもしれない。

2011年6月21日火曜日

mongocco

mongoccoは昔自分がやってたアバターチャットシステムだ。
ちょっと記憶が定かでない部分があるけど説明してみる。

世界はオープンワールドとクローズドワールドがあって、孤島で成り立っている。
オープンワールドはインターネット越しにみなさんとチャットができる。
クローズドワールドは、自分の家のルータ内のアドレスでログインできるけど、インターネット越しには接続出来ない。

IDを持った人は、島一覧から好きな島を選んで起動する。
すると、その人がサーバ役になって、他の人が島に降り立つ事が出来るようになる。
サーバ役の人がいなくなると、別の人にサーバ役が引き継がれる。
サーバ役になれるのはIDを持ってる人でポートを開けたり設定しとかないといけない。
IDが無くてもGUESTで参加することが出来る。
GUESTはサーバにはなれないし、アイテムも持ち帰れなかったんじゃないかな・・・たしか・・・

島にはいろんなものが流れ着き、木には実がなる。
アイテムショップではどんぐりでいろいろな物を買える。
買ったものは島に配置することができる。
色々な色がついたキューブを並べたり積み上げたりして、
ドットアートのようなことをすることもできる。

島一覧には害虫の発生する島があって、そこで害虫を倒してどんぐりを稼ぐ。
アイテムショップはどんぐりで購入できる。

とまぁ、大体こういうシステムなんだけど、革新的だったのはサーバが必要なかったってことだ。
アイデア次第で、このシステムはもっと応用が出来ると思う。

すでにサービスは停止していて、ダウンロードも出来ないが、
ファンは結構残ってると思う。

2011年6月18日土曜日

mantisについて

使う側の立場での使い方を書いておこうと思う。
設定する側の立場での使い方は以後書く予定

自分の書き方なんでかなり大雑把である。

1.基本は検索
  検索を押しておけば、なにが残っているのか一目瞭然
  メインなんか押してもまったく何の情報も出てこない
  新規登録をする前にまずは「検索」をして、
  他に似たような登録がないのかきちんと確認することが重要

2.登録
  気をつけないといけないのは
  (1)わかりやすいタイトル
  (2)わかりやすい説明
  (3)必要なときは再現手順
     ステップ毎に番号をつけて、誰でも再現できるように記述する

3.ステータス変更→フィードバック
  「フィードバック」はどのステータスからも戻り得るステータス
  例を挙げると
  (1)説明がわからない登録がされた場合
     もっとわかりやすく書いて!と開発者から登録者にフィードバックを求める
  (2)解決済みからフィードバック
     本来QAが完了にするフェーズだが、
     解決してないんじゃない?となると
     開発者にフィードバックして治ってないよと知らせる。
  担当者はその都度設定できるので、
  誰が現状ステータスの担当なのかしっかり設定するのが重要

4.ステータス変更→内容確認
  開発者が変更する事が殆ど
  時間が無い時は、解決まで出来ないので、
  とりあえず開いて内容確認しましたというフローにまでもっていく
  QAに開発者が仕事してないから新規たまりまくってます!
  とか言われるのは避けたいw

5.ステータス変更→再現済、担当者決定、解決済み
  上記3、4もそうなんだけど、
  ステータス変更するのは一体誰かというのが問題になる。
  結論から言うと誰でもやるべき
  完了以外はとりあえず開いて読むべき
  そして、誰が担当なのがふさわしいのか考えて、担当者はきちんと設定する。
  本当にバグなのか、問題なのか、仕様じゃないのかなんてことは、
  プロジェクトにかかわる全員が把握するべき事なので、
  誰もがステータスをどんどん前にすすめるベきなのは間違いない

6.ステータス変更→解決済み
  これやるのは間違いなく担当者となった開発者

7.ステータス変更→完了
  これやるのは間違いなくQA
  完了にする権利は開発者には無い!
  (QA居ない場合はしかたないけど)
  ようするに6で解決済みになったからと言って終わりじゃないのだ。
  最終的に完了と判断するのはQAであって、
  QAが納得しなかったら完了になんかならない。
  逆に解決済みから開発者にフィードバックされてしまうかもしれない

ステータスは上記のように順番ではなく、
新規からいきなり解決済みになることもある。
「新規」から「完了」になるパターンは、
よっぽどうっかり登録した間違いパターンだと思う

mantisbt + dokuwiki on ドメインキングのレンサバ

現在日本ではwikiと言えばpukiwikiだと言える。
しかしその開発はすでにほぼ停止状態。
pukiwiki plus も出ているが、それで作られたサイトを見ると、
どうもwikiっぽいデザインから抜け出す事が出来ない。

会社のプロジェクト用にドメインキングのレンサバにmantisを設置した。
mantisとの連携ではdokuwikiを採用するのがベストである。
他のwikiとの連携も出来るのだが、
文字エンコーディングの問題があって行き着く先はmantisbt+dokuwikiであった。

使い勝手はpukiwikiの方が慣れていたのだが、dokuwikiでもそう難しくはない。
良いのはメンバーごとのアクセス制限が手軽に出来る事
これでレンタルサーバ上に置いてあったとしてもメンバー制限が出来るので内容が漏れることは無い。
セキュリティ上どうなのかは正直よくわからないが、
当面コレで運用していこうと思う。

2011年6月17日金曜日

Joomla の使い方がなんとなく分かって来た

Joomlaはなんでもかんでも分けるようだ。
記事でもニュースフィードでもメニューでも「セクション」「カテゴリ」をきちんと設定してからでないと駄目なのだ。
最初その辺りがよくわからなかったが、そういうJoomlaのこだわりが分かればそれに従って考えればいい。
静的コンテンツの場合は分類を未分類にしておけばいいらしい。

2011年6月12日日曜日

Joomla を入れた

会社用のWEBサイト構築のためにXoopsを使っていたが、なんだかでかい割には何をするにもモジュールが必要なので、いっそのことWikiにしてやろうかと思ったが、WikiだとWikiくさいから嫌だなぁと思っていたら、Joomlaというのを見つけた。これめちゃめちゃいいわ。

2011年5月24日火曜日

ドメインキングで借りたサーバ(その後)

ちょっと結構かなり気に入って来た。
ajaxplorer(3.2.3)はファイル名によって日本語のファイルの転送に失敗する。
フォルダも日本語は無理。
転送に失敗する場合はファイルの先頭を-にしたり+にしたりすると転送失敗しなくなった。

ajaxplorer の機能は素晴らしいので今後もきっと発展すると思う。
みんな使うべし!
http://www.ajaxplorer.info/wordpress/

あと、使い方がよくわからないのだけどxoopsを入れてみた。
cubeじゃ無い方。
どっちも使った事無いのでどっちがいいのかよくわからない。
とりあえずうちの作りかけHPはこちら
http://yachiyo.galeon.jp/
それとEC-Cubeで作った笹子堂せんべい屋のHPはこちら
http://sasagodo.galeon.jp/

どちらもgaleon.jpのサブドメインとして作った。
galeon というのは大航海時代の船でガレオン船から・・・

2011年5月9日月曜日

グループウェアの必要性

カレンダー、ファイル共有、ワークフロー管理、MindMap、UMLなどそれぞれ別個にWEB上にツールが存在する。
ドキュメントのリークが問題になるケースは多いのだが、グループウェアを使ってもそれは結局防げない。
既存のグループウェアをカスタマイズしまくったとして、
出来上がった物が企業のニーズに合っているかというと、実はもっとあれやこれやしたいことがあるのだ。

今のところ、WEB技術に求める物、実現できる物は合致していない。

原因の一つはWEB技術の進化が、市場の食い合いによって右往左往してきたことによる。
今ではメジャーであるJavaScriptは、そもそもネットスケープというブラウザのスクリプトだったし、方言も多かった。
Perlも生まれたときにはWEB用のCGIにしようとは考えられていなかった。

とかく新技術と言う物は脆弱性との戦いを強いられる。
生き残った新技術で出来ることを実現しようとしたり、今までと違う実装をしようとしたり、
WEB技術というものは試し試し進歩してきたのだ。

試し試し進歩してきたものをかき集め、一つにまとめたものがグループウェアだ。
既存のグループウェアを使うのではなく、かき集めればそれで足りる!

今回、ドメインキングでレンタルサーバを借りた。
笹子堂のWEBページをこちらに移すつもりで、EC-CUBEを入れた。
だいたいカスタマイズも終了。
テストで購入手続きしたりなんだりもしてみた。
まぁ大体OKだと思う。

続いて、自分の会社のためにグループウェアを検索したが、冒頭からの理由によりグループウェアの検索をやめた。
自分が一番欲しいものはセキュアなファイル共有なのだ気がついた。
どこでもファイルを見れるようにしたいのだ。
そこでAjaXplorerを入れた。
.htaccessを変更し、ファイル1つあたりの最大転送量を1Gにした。
php.ini ではなく、.htaccessで変更出来るとは知らなかった。

次はMantisでも入れようか、
会社の宣伝ページには、一枚かっこいい絵を貼っておけばいいんじゃないだろうかと思う。