Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

良かれと思ってはビジネスではないな。。。

自分の悪い癖をメモっておこう。。。

  • 良かれと思って、詰めきれていないものをクシュってまるめてしまい、巻き取ってしまう。
  • 相手の都合にただ合わせて線を引いているだけなので、自分を責任を全うできてねぇ。逆説的だけど。
  • あれも取れそうこれも取れそうで、目先のものを掴みにいきすぎてしまって、時間軸の組み立てが崩壊してしまい、いい加減な仕事に結果的になってしまう。

ことし1年、これをぶら下げておこう。忠告してくれた恩人に圧倒的感謝。

誠意とは言葉ではなく・・・

100日で心折れるスタートアップで一番好きな言葉をメモっておく

どれだけ口では「協力します!」「一緒にやろう!」と言っていても、実際に行動を共にしてくれない人は仲間にあらず。行動で応援してくれる人はごく限られた人だけです。 えい. 100話で心折れるスタートアップ (p.52).

SHUT THE FUCK UP, do the right thing, right!

2025年始まってるやんけ

昨年はずっとお仕事をしていて、デイタイムでFlutter、空いた時間はRemixな1年だった。Full-Stack TS楽しい。

プライベートでは、ICL(眼内コンタクトレンズ)の手術を行った。とにかく近視がひどいので、遠くが見えるようになりたかった。やってみたところ、左右1.2以上見えるようになったので、とても満足している。それでも近視は進んでしまうのだろうけど、なるべく目に力を入れず、ゆったり遠くを見るように心がけたい。メガネを掛けることに抵抗はないので、今後は老眼鏡を愛でていくことになる。

今年は色んなものを手放せるようにしたい。今まではこれというかたちがなかったので、何を実装するにも自分から始めないといけなかった。プロジェクト・テンプレートを今年の6月までに固めて、7月からメンバーが主体となって実装が進められる体制を作りたい。それができないと、自分の限界を超えることができないから。

正しく、手放そう。

今年の僕の標語です。仕事でもプライベートでも。

2024年終わってまうで

会社の運営という意味では本当にお客様に恵まれて、紹介で色んなお仕事を頂けました。過去最高の売上を達成できたのはいいのですが、自分の限界が明らかに見えてきたので、来年は僕が会社の仕組みを作る仕事を中心にやっていくのが目標です。今まで自分でやっていたのを外に出したり、今はお金にならないことを投資として進めたり、そういうことが10年目になってやっとできるようになってきました。

これだけの時間がかかってしまったのは単純で、恐ろしい話なんですけど、自分で自分の会社をどうしていいかわからなかったから。ソフトウェア開発を今後もやるかやらないかの踏ん切りがつかず。起業最初はやめるつもりだったけど、お仕事の99%がソフトウェア開発を求めてきた。システムの企画や導入のディレクション等のコンサル仕事で食っていくつもりだったんだけど、やってることはFlutterテックリードという。。。

コロナ禍でFlutterを覚えて、自分のソフトウェア開発のリスキリングが楽しかった。そのため、ソフトウェア開発をやるのはコロナ禍では決まったが、自分が新しくWebアプリケーションを作るツールキットを選んで磨き上がることができなかった。その間はFlutterをやることで時間を稼いだ。昨年秋にRemixに出会ったことで、全てが整った。

自分が心中できる技術を見つけることができたのが2024年の最も大きな出来事。あとはこれにそって、作っていくだけ。

コードを書き続けていると経営のお仕事が全部後ろ回しになってしまう。経営の仕事は営業(顧客開拓)と採用なので、この両輪をどういうコストをかけて回していくか。全員エンジニアで5人ぐらいの会社にしたいとおぼろげに思ってる。今はパートナー入れて3人。

Remixで書き直すことで他人が僕のコードに手をいれることができるようになる。コードを捨てる局面を早く迎えたい。ビジネスに変化があった証なので。コードは書いた瞬間から陳腐化するから、捨てやすさがとても重要。最近はそこにしか興味がない。メンテナンスってコードを捨てることで新陳代謝を図ることのはずなので。

良いものがなければなんにも売れないので、まずは採用とプロダクトを作る両輪を錆びつかせずに回すのが来年で出来たら。来期も既に黒字は確定しているレベルなので、今こそ色んなトライをしなければ、尻すぼみしていくだけ。お金をちゃんと使う!使わないと投資にならない。今できている延長線上の仕事を回すだけで現金残高を増やすことに、意味が見いだせない。自分で捕まえた顧客を元に全く違うスキームで事業を作ることで会社の収益ポートフォリオを変えていかねば! No 現状維持!変えなくちゃ!

深夜のテンションでそのまま終わり。

ユーザー独自属性をどう作るかみたいな話

例えばお問い合わせフォームとかで、名前とメアドは必須とする。ただ、あるユーザーはドロップダウンで予算種別や流入経路を出したい、とあるユーザーはFAX番号も出したい、みたいなやつ。

スキーマレスのFirebaseの場合ユーザーごとにスキーマ作れば終わる(アプリ側は大変だけど)んだけど、RDBはそうもいかないよね。

今まで見たなかで大きく3パターンあるようなので、整理をする。

1. 属性ごとにテーブルが作成する

DrupalというCMSで見たパターン。 属性を追加することでconfigが更新され、configには追加したフィールドの格納場所がわかる。で、Field APIでカスタム属性をを全部引っ張ることができるようだ。

2. metaテーブルを作る

WordPressが得意としている実装。option_metaとかuser_metaとか。

field_namefield_valueを保存するテーブルを作って、キー/値ペアを作るやつです。カラムのスキーマはバイナリ以外は自動的に文字列になるので、そのあたりが微妙。重量みたいなカスタム属性があって、4.3kgである場合、本来はDecimal(10,1)とかなんだろうけど。型情報も保存して、toXXXいれるしか無いんかな?

この種の設計は、SQLアンチパターンとはされているけど、格納する→表示するだけなら、まぁそこまで。検索したいとなると、無理。格納表示ならJSONでよいだろって思い始めている。

SQLアンチパターン EAVと4つの解決策

EAVだと検索性が死ぬので、それらの対応策としては、親のテーブルにtype属性を作って、そのtype属性に応じたテーブルを作りJOINするパターンが有る。STIってやつですかね。単一テーブル継承。

マルチテナントのアプリケーションになっちゃうと、ユーザー単位でSTIが作られるので、テーブルの継承が出ずに、結局EAVにならざるをえない(型が決まらないので)。field_type field_name field_value validation みたいなテーブル作って、そこで頑張る感じかな。。。

3. JSONカラムを作って逃げる

WordPressのカスタムプラグインなんかで、どっかで見た実装。フィールド、ラベル、タイプ、バリデーションなどをJSONで用意して、動的にフォームを組み立てて、値も入れちゃうパターン。実装も単純。

まとめ

  • カラムで吸収:STIJSON
  • レコードで吸収: metaテーブル(EAV)
  • テーブルで吸収: Drupal

EAVになったらJSONで大差ないよ派なので、JSONでいいかなー。

組織が抱える過剰な忖度文化というパワーワードに感銘を受けた件

この会社さんが仰ってること、非常によく分かる。

cgo-gal.com

過剰な忖度文化というフレーズがいいし、上司にそうですねと言わないといけないとか、全く同感。もちろん相槌を打つのはあると思うけど、それしか言わなかったお前は何も表現してねぇだろって話だよね。ほんまそうよ。

別の記事で、Lilyさんという方が至言を仰っていて。

Lilyが思う令和のギャルは、自分が経験に基づいた考え方を、表現にまで落とし込んで、恐れずにリリースしている子かなぁ。

いろんな人がいろんな考えを持っているのは大前提で、「うちはこう思うし、こう表現するから」って、他者の目線を入れずに表現できる子がいいなって思う。 r25.jp

すごいなLilyさん。20年ぐらいマネージャーやってるんじゃないかという視点だよこれ。僕が思うに、ほとんどのプロジェクトで、全く出来てない。それも、自分の考えを表現する訓練を積んでない or 足りていないからだ。思ったことを伝える技術を磨いていない。そういう人が役職上マネージャになってしまうと、そのチームは機能しない。少なくとも錆びついたギアでしか動けなくなる。

「自分が経験に基づいた考え方を、表現にまで落とし込んで、恐れずにリリース」する経験ってのは、ビジネス上だと、「それ、おかしくね?」をキチンと言えるかどうか。

「なんか、おかしくね?」ってすごい大事なサイン。でも、それをストレートに出せる人って、そうそういないんだよね。ナチュラルに出せるという意味。ナチュラルにできる人は、自分は他人と違って良いんだって確信できてる。ギャルマインドってココだよね。どう転んでも自分の表現でいいじゃんってさ。僕なんてそれをブログでやり続けたら色んな人がいろんなことを教えてくれたぜ。

おかしいと思ったことはおかしいって言えない職場で働くの、無理じゃないですか? なんで無理してるのかわかんないよね。おかしいって通したら他の人の立場がとか、それはわかるよ。どうせ辞めるし、それもあるね。でも、おかしいものはおかしいし、筋が通らないのは筋が通らない。誰かにしわ寄せが来るだけ。しわ寄せが来るのはあなたのせいじゃないし、巻き取る意味もないかもしれないけどさ、どうせ次でも「それ、おかしくね?」と向き合う時は来るから。リリースしようぜ、自分の経験に基づいたヘルプをさ。

筋が通らないことをやっていると、時間が経てば経つほど、正しい方向に戻すのは難しくなる。筋が通らないままに作った仕組みなりが出来上がっちゃうから。

もちろん言いっぱなしだと他人批判に取られちゃうから、最低限と根拠と理由、まずは理由が必要かな。おかしさを生み出してる理由がどっかにあるわけで。それを出すから相手に伝わる。いいんよ、理由には根拠がなくたって。理由を裏返して根拠を見つけたらそれで。

よし、これをメインのブログに乗っけていくぜ。いい感じのドラフトだ。

TypeScriptで好みのORMが見つからない問題

TypeScriptでバックエンドを書いちゃう皆様、ORMは何をお使いですか?

私はシェアが大きい Prismaを使ってみたんですが、どうも肌に合いません。その理由は以下のようなものです。

2025.01.07 追記

まったく同じ理由で自分と同じ構成にしている方がいましたので、こちらどうぞ! Prisimaやめたポイントが同じ!

zenn.dev

1. Prisimaの独自スキーマ、いらない

ORMの特徴として、テーブルのスキーマに合わせてカラムの型、ENUM、外部キー、ユニーク制約などを生成してくれます。Prismaはこれを独自のDSLで実現し、npx prisma generateスキーマを生成します。

自分だけかもしれませんが、ORMのスキーマに細かいリレーションシップの定義は不要です。ActiveRecordhasMany的な定義を事前に入れるのはだるいし、JOIN条件はクエリで組み立てればいいじゃん派。JOIN条件が複合条件になる場合もあるし。enumは欲しいけどね。

そんなに難しくないDSLですけど、DSLを元にコードを自動生成する設計の場合、結局DSLの中身を理解して、クエリを組み立てないといけない。PrismaのWhere句に相当するクエリの書き方は、個人的に肌に合わなかった。覚えるのがだるい。

Prismaのようなスキーマ生成をする場合、その作業をnode.jsのコンテナに入れないといけない。その場合、GAEの無料インスタンスに乗らないんですね。それも個人的な都合でネックでした。無料で充分まわるんだもん、業務系のシステムってユーザー数が少ないからw CloudFlareとかに乗せる時も気になってます。今はもう気にしなくて良さそうだけど。

2. Prisma、集約系の機能が弱い

業務系システムやWebサービスの管理画面系になると、GroupByを使わない日は無いと思います。Prismaの独自DSLによって、GroupByの条件を指定するのがとてもだるい。

GroupByした時、JOINできないのも勘弁してほしかった。CTEも怪しい。

TypedSQLがリリースされましたけど、動的な条件組み立てに対応していないので、あまり使い道がない。

3. Prisma、DB独自の関数が利用できない

Prismaが意図的にやっていること。わからんでもない。ブラックボックスになるしね。MySQLだと date_format関数をよく使うので、それが使えないのは困り申した。

Prismaも良いところはあって、クライアントを拡張できること。ページネーション用の関数を生やしたり、RLSに対応したり、クエリを発行する前に where tenant_id = 2みたいなマルチテナントやる時に必須のWHEREを付け加えたり、クエリ発行後にログを出したりイベント発行したりできる。ミドルウェア的な機能が欲しい場合、現状Prisma一択だと思う。

今の自分は、それが必要じゃなかった。

Drizzle with Kysely

自分がメインで使っているのは、Drizzleです。独自スキーマも要らない(全部TypeScriptになる)し、ORM的な使い方もクエリビルダ的な使い方もできる。Prismaのように、1回のクエリ発行でしれっと2発のSQLを投げるみたいなことがない。JOINした時に、user.post.titleみたいな感じで補完されるのすごく便利... マイグレーションもあるし。

Kyselyはすごく好きなクエリビルダなんだけど、SQLの結果セットをそのまま取得する。オブジェクトがネストされない。user.postにはならず、result.title として取得する必要がある。そのため、SELECT句でカラムを指定することが多くて、集約系のQueryじゃない場合は面倒さがある。

でも、SQLの表現力を最大限活かせるのがKyselyのメリットなので、以下のようなQueryを発行したい場合は、drizzleのスキーマからKyselyのスキーマを吐き出して、Kyselyでクエリを書くのがいいなと思っています。

  • CASE/WHENのようなSELECT句で加工するようなクエリを書きたい
  • DB関数を使いたい
  • GroupBy / Havingなどをガッツリ書きたい
  • CTEを使いたい

上記のようなケースはあまり無いと思うけど、使いたい時はあります。

DuckDB-wasmとかでローカルにDuckDB入れて、クライアントサイドでダッシュボードの集計をするみたいな時代になっているので、SQLをサーバサイドでゴリゴリマッチョすることは減るのかもしれないけど、Kyselyを使うケースはまだまだ多いでしょう。