"idea"

生成AIとマネジメント階層の平坦化

「アート・オブ・プロジェクトマネジメント」を読んでいる。https://www.oreilly.co.jp/books/9784873112992/ 大体のタスクには1/3の法則が適用できるとしている。つまり、タスクは設計・実装・テストの3段階に別れていて、ざっくりスケジュールも3等分できる、みたいな主張(記憶で書いているので正確なことは本を参照してください)をしている。

ここからは100%僕の自論。マネジメントする人は基本的に実装フェーズをマネジメント対象の人に委譲するのではないだろうか。 3段階に分割されたタスクのそれぞれのフェーズはやはりタスクであって、再帰的にまた3段階に分割されると考えている。仕事を作るフェーズが設計、それを実際に行うフェーズが実装、その実装が欲しかったやつなのかを確かめるのがテストである。そう思うとマネジメントする人は設計やテストを実は自身が行っていて、実装フェーズだけを他者に任せていると言えそう(かける時間を考えると多少無理がありそうな気もするがひとまず気にしない)。

ところでマネジメントの階層構造は浅いほど純粋な実装の割合が高まる。純粋な実装の割合を説明する。マネジメントの階層構造は全てのノードで枝が三つの木構造をなす。それぞれの枝は設計・実装・テストに対応する。ノードはタスクを表す。ルートから実装の枝だけを辿った先の末端のノードが純粋な実装である。純粋な実装が欲しいものであることを保証するために設計が存在して、その設計を満たすことを保証するためにテストが存在する。実際の価値を生み出すのは純粋な実装である。

純粋な実装の割合を高めるためにはマネジメントの階層を浅くして、余分な設計やテストを削減すれば良い。つまりマネジメントレイヤを減らすこと、息を止めてできる実装のサイズを大きくすることが効く。理想的には全ての主体がマネジメントのトップにいる(マネジメントの不要な組織)と効率が最大になる。問題に対する能力の問題でそれが叶わないケースが多いだろう。理想的には全員が最強な集まりが最強なのだ。社長を100人集めてそれぞれの組織の実行に必要な能力を社長に宿らせれば、100人だけで100社分のアウトプットができる。確かに効率が理想的である。

さて、生成AIの登場によって人間ではなくAIにタスクを以前よりも段違いに任せられるようになってきた。普段生成AIを使っている我々は知っているのだが、やはり設計とテストを僕たちがやって、実装を生成AIに任せるという生成AIのマネジメントをやっている。生成AIのおかげで僕たちはタスクの1/3を自動化できるようになったのだ。これはこれまでの人間をマネジメントする状況と変わらない。一方で、生成AIは人間よりもだいぶ汎用的で素早い。そのため人間ほどの問題の分割統治が必要ないだろうと思う。これはマネジメントの階層を浅くすることに寄与する。下手にマネジメント階層を深めないで社長が直接生成AIを使って実現できるならば、マネジメント階層の深さは理想的になるのだ。

極端なパタンについて述べたが、現実にも生成AIはマネジメントの階層を浅くする方に有利な技術だろう。組織は今後もっと浅いマネジメント階層になっていくのではないだろうか。つまり仕事では自律的な行動がこれまで以上に求められることになっていく(昔からこの傾向はずっとそう?)。

追記: 価値観が疑われると悲しいので言い訳を書いておきます。ここでの主張は思考実験であって、単純化するとこういう考え方があってよいだろうという主張です。心の底から社長100人の組織が最強の組織だと思っている訳ではないし、たくさん無理な仮定や推論を置いています。マネジメントがタスクをこなすための木構造である、とか言っているがそんなわけがないし。

生成AIは実装をしてくれるのは間違い無いのだけど、設計とテストをする能力も備えている。とはいえそのための段取りがあるとないとでは当然ながらその成果が異なる。設計・実装・テストを効果的に遂行できるような環境を用意することが生成AIを使役してより平坦なマネジメント階層を構築するのに有効である。

  • コンテキストを共有すること
    • そのタスクの背景・目的を共有する
    • 例えば大きなタスクを分解した中の一つのタスクとしての位置付けであれば、そのとき実現してほしいタスクだけでなく大きなタスクを共有した上でそこに含まれるタスクの一つをやってほしい、というように依頼すれば背景や目的を伝えられる。僕の実感として良い成果が得られるように感じる。Claude CodeでTODOリストを作成して一個ずつこなしていくのはこの手法の一つのインスタンスだと思う。

  • 検証の観点を共有する
    • コードを書いてくださいと言われただけなら当然検証はしない
    • 要件を与えれば良いだろうか
  • 検証環境を用意する
    • REPLを用意するとかTDDできるようにするということ

コーヒーの抽出手法

この記事は僕と生成AIとの対話です。

コーヒーの抽出手法について以下の課題について議論してください。

ペーパードリップやフレンチプレス、エスプレッソなど様々な手法がありますが、あれらは不必要に凝っているように感じます。粉に挽いたコーヒー豆をお湯につけ煮出し、不要な成分を除去するというステップさえ踏めれば、あとは再現性を高くすることが肝要なはずです。職人技をできるだけ排除すること、片付けや準備を簡単にすることも評価基準に入れたいです

以上を踏まえて既存手法を比較検討して、さらに新たな効果的な抽出手法を提案してください


ご指摘の点は、コーヒー抽出の本質を捉えた非常に鋭い視点だと感じます。多くの抽出法が持つ「職人技」や複雑な手順は、コーヒーを淹れる楽しみの一部である一方、本来の目的である「美味しいコーヒーを安定して飲む」ことから遠ざけてしまう側面があることは否めません。

ご提案の「粉に挽いたコーヒー豆をお湯につけ煮出し、不要な成分を除去する」という本質的なステップに基づき、**「①再現性の高さ」「②職人技の排除」「③準備・片付けの簡便さ」**を最重要の評価基準として、既存手法の比較と新たな抽出手法の提案をさせていただきます。

まず、ご提示の基準で主要な抽出手法を再評価してみましょう。

抽出手法再現性職人技の排除準備・片付けの簡便さ評価
ペーパードリップ×お湯の注ぎ方(速度、高さ、円の描き方)という職人技への依存度が高く、再現性は低くなりがちです。器具も比較的多く、準備に手間がかかります。ただし、ペーパーフィルターが微粉や余分な油分をしっかり除去してくれる点は、ご指摘の「不要な成分の除去」において非常に優れています。
フレンチプレスお湯を注いで時間を計り、プレスするだけ。職人技が介在する余地が少なく、再現性は高いと言えます。しかし、金属フィルターのため微粉や油分が多く残り、後片付け(粉の処理)が非常に面倒という大きな欠点があります。
エスプレッソ×××マシンの性能に加え、豆の挽き目、タンピング(粉を固める力加減)など、再現性を担保するには高度な技術と経験が必要です。準備・後片付けも最も手間がかかる手法の一つであり、ご要望とは対極にあると言えるでしょう。
エアロプレスフレンチプレスと同様の浸漬式(お湯につける方式)で再現性が高く、かつペーパーフィルターを使うため後片付けが非常に簡単です。注射器のような形状で、粉がひとかたまりになって捨てられます。ご要望の基準を非常に高いレベルで満たした、既存手法の中では最も合理的な選択肢の一つです。
浸漬式ドリッパー<br>(クレバー、HARIOスイッチ等)ドリッパーの底に弁がついており、お湯と粉を一定時間浸漬させた後、スイッチ一つで濾過・抽出が始まります。お湯を注ぐ技術が不要で、再現性は極めて高いです。ペーパーフィルターを使うため後片付けも簡単。これもまた、非常に優れた選択肢です。

現状の製品では、空気圧を利用する**「エアロプレス」や、浸漬と透過を両立した「浸漬式ドリッパー」**が、 ご指摘の思想に最も近い、合理的で優れた抽出法と言えます。

既存手法の優れた点を組み合わせ、さらに理想を追求した、ご家庭にあるもので今日からでも試せる新しい手法を提案します。これを**「サーモ・イマージョン・メソッド(The Thermo-Immersion Method)」**と名付けます。

この手法の核心は**「①徹底した温度管理」「②攪拌の自動化」「③クリーンな濾過」**の3点です。

  1. 断熱性の高い容器(魔法瓶、保温タンブラーなど):抽出中の温度低下を限りなくゼロに近づけ、再現性を極限まで高めます。
  2. ペーパードリッパーとフィルター:最も手軽で効果的に「不要な成分」を除去します。
  3. スケール(はかり)とタイマー:再現性の基本です。
  4. コーヒー豆(粉)とお湯

  1. 準備
    • コーヒー豆を計量し、中挽き~やや粗挽きに挽きます。
    • 断熱容器と、抽出先のサーバー(またはカップ)にお湯を注ぎ、温めておきます。
  2. 投入・浸漬
    • 温めた断熱容器のお湯を捨て、挽いた粉を入れます。
    • スケールの上で容器のゼロ点を合わせ、沸騰したお湯を目標の量まで一気に注ぎます
    • すぐに蓋を閉め、タイマーをスタートさせます(例:4分)。
    • 蓋を閉めたまま、容器全体をゆっくりと5~6回、逆さにするように攪拌します。スプーンなどでかき混ぜる必要はありません。これにより、誰がやっても均一な攪拌が可能です。
  3. 放置
    • タイマーが鳴るまで、そのまま放置します。断熱容器が抽出温度をほぼ一定に保ち続けます。この間、コーヒーの成分がムラなく、安定して溶け出します。
  4. 濾過
    • タイマーが鳴ったら、温めておいたサーバーの上にペーパーフィルターをセットしたドリッパーを置きます。
    • 断熱容器の蓋を開け、中のコーヒー液をドリッパーに静かに全て注ぎ入れます
    • 全ての液体が自然に落ちきるのを待つだけです。

  • 極めて高い再現性:お湯の注ぎ方という最大の変動要因を排除。断熱容器により抽出温度が最後まで維持されるため、誰がいつ淹れても味がブレません。
  • 職人技の完全排除:求められるのは「計量する」「注ぐ」「待つ」という単純作業のみです。
  • 準備・片付けが容易:使用器具は断熱容器とドリッパーのみ。断熱容器は口が広ければ洗いやすく、抽出後の粉はペーパーフィルターごとゴミ箱に捨てるだけで済みます。
  • 高い品質:浸漬式により豆の風味を余すことなく引き出し、ペーパーフィルターが雑味や過剰な油分をカットするため、クリーンで甘みの際立つ味わいになります。

この「サーモ・イマージョン・メソッド」は、コーヒー抽出の複雑さを削ぎ落とし、その本質である「溶解」と「濾過」を、最も合理的かつ安定的に行うことを目指した手法です。ぜひ一度、お持ちの魔法瓶やタンブラーでお試しください。コーヒーの新しい可能性が見えてくるかもしれません。


鍋で抽出してペーパーフィルタで濾しました。元々時間とか温度とか測るタイプの人間じゃないので、再現性も何もないことに気がつきました。

良書を読む文化がもっと流行ってほしい

この記事は、技術者の成長において「良書を読み込む文化」の重要性を論じた文章です。

新しいメンタルモデルを手にいれるための手法として、良書を読み込むことが有効だと考えます。

Known unknown(知らないことを知っている、例えばOSにはプロセスとスレッドというのがあるらしいが、何が違うかわからない)な対象を理解するためには、質問に回答してくれるチュータやNotebookLMのようなツールを用いれば良いでしょう(プロセスとスレッドの違いを質問すればいい)。一方で、考え方を新しく身につけるためにはその手法は効きません。なぜなら古いメンタルモデルしか持たない人間が新しいメンタルモデルを獲得するための質問をすることが困難だからです。

メンタルモデルを新しく説明して頭に叩き込むことは大変です。説明する側はよく整理しないといけない(聞き手が察することには期待できないので)し、聞き手は誤解をしないように注意深く説明を腹落ちさせる必要があります。

例えば技術研修は新しいメンタルモデルを研修生に叩き込む手段の一つです。やはり大変な営みなので技術研修をする講師には高いレベルのエンジニアの工数を注ぎ込む必要があるし、研修を受ける人々には研修期間中はそれに集中することが許されています。

技術研修は効果的ですがスケールしません。一方で良書を読み込むことはスケールします。さらに良書は研修よりも洗練されています。なので僕は良書を読み込むことが有効だと考えるのです。

まず、技術研修がスケールしないことを主張します。講師をアサインする必要があることがネックです。アサインするためには社内に適任者がいるとか、社外から適任者を頑張って呼び出すとかする必要があります。そもそもアサインできないことが多いでしょうし、できたとしても労力と金銭的なコストがかかります。

良書は安いです。大体の技術書は一万円も出せば購入できます。給料をもらって働いている人間なら程度の差こそあれ世界最高レベルの技術書を年に一回買うことは容易いのではないでしょうか。また良書は簡単に入手できます。Amazonで1分で注文できます。どんなに時間がかかっても、一週間もあれば本が手元に手に入るのではないでしょうか。そして大体の研修に比較して、よりレベルの高い専門家がより労力をかけて作成しています。技術的にも説明としてもレベルが高いはずです。

研修をするのはそれはそれで良いとして、研修は受けるのに良書を読み込むことはしない人がいるのはなぜでしょう。要因として以下があるのではないでしょうか

  • 良書を知らない、見つけられない
  • 本を読み込むことを選択肢に持っていない
  • 英語を読むことを選択肢に持っていない

知らない、見つけられないのはある程度しょうがないでしょう。人に教えてもらうのが有効と思います。幸いなことに社内では本を紹介し合う文化が多少あります。そこで一定解決できるでしょう。インターネットには良書を紹介してくれる人がちらほらいます。アンテナを貼っておくと良いでしょう。

本を読み込むことを選択肢に持っていないのは経験の問題でしょう。読み込んだことのある人と一緒に読み込む練習をすれば良いと思います。大学の研究室でやられている輪講会はこの目的を持つと考えます。

また、良書は往々にして英語で書かれています。気合いで読めば読めるので、これも経験の問題でしょう。

輪講会に参加するモチベーションを高めて開催すれば参加してくれるでしょう。参加してくれれば良書を読み込む経験による慣れと、一冊の良書を読み込んだことによる新しいメンタルモデルを身につけることができます。

社内で二つの輪講会を開催しています。両方を狙って開催しているのが A philosophy of software designの輪講で、慣れを狙ったのが型システムの輪講です。

僕が思う良書です。どれも文句なしにおすすめです。どういう領域のメンタルモデルを手に入れられるかはそれぞれの本の冒頭に書いてあるはずです。

  • プログラミング in OCaml
  • Essentials of Programming Languages
  • A Philosophy of Software Design
  • プログラミング言語Go
  • K and R
  • 数学文章作法

パッとはそんなに出てこなかったです。

2025-06-15

2025-06-11 で不変条件を上手に設定して保つことがプロダクトを成長させるために効き、その効き具合は投下できるリソースの増加に応じて増すみたいなことを書いた。不変条件に限る必要はないはずで、内部品質を高めることが効くと思う。内部品質の高めかたの一つとして不変条件をいい感じにする方法がある。

CI・CDは開発・運用から動作検証とデプロイを自動化した。つまり、それに必要な人手をゼロにした。それらに必要な人間の頭がゼロになったのではなくて、求められる頭の使い方と必要な作業の種類を変えた(作業の量を減らして負荷の高いスポットな労働に変換した)。

AI前提な開発をそのパターンに当てはめて考える。

例えばブランチを切ることから始まるプルリクエストの作成を自動化することはAI前提な開発の一つの形態である。ブランチを切る時点で達成するべきコードベースの変更の目標が定まっていて、それをプロダクトとしての品質を保ちながら意味あるスコープで実現するのがここでいうプルリクエストの作成である。コードベースがまともで、CIが整備されていればその手のプルリクエストを人間であれAIであれできる。この自動化が広く実現するようになると、プルリクエストでどんな変更を実現したいかを決めることと、プルリクエストをマージして良いことを検証することが自動化した仕事の周辺に残る。そしてこれらは今まで単に実装するだけよりも少しレベルの高い作業として認識されてきたものである。

多少抽象的な課題から、それを具体的に落とし込んで、どのようなプルリクエストが必要かを洗い出すことも最近商用化されているAIには可能である。この自動化が広く実現するようになると、周辺に残る仕事は多少抽象的な課題を抽出することと、プルリクエストをマージして良いことを検証することである。

多少抽象的な課題を抽出することは、claude codeの開発のためにやられていそうという観測がある。インターネットを徘徊してユーザの反応を見れば良い。

プルリクエストをマージして良いことの検証はCIとそのメンテナンスとしてAIである程度自動化できるだろう。AIが直接判定しても良い。これはまだ現時点では難しいように感じる。僕が実現させられていないだけかもしれないが。

僕はGMOペパボのエンジニアとして働いていて、定期的に評価資料を書く。何人か上長がそれを元に僕の評価を決定する(だいぶ端折った説明)。評価資料を書くのはそれなりに大変。具体的には自分の実績を元に評価要件に沿って評価を主張することが求められる。

評価資料を書く仕事はいかのような作業に分解できる

  1. 実績を洗い出す
  2. 評価要件を理解する
  3. 評価要件に照らし合わせて自身の評価の主張を想像する
  4. 主張をサポートする実績を対応づける
  5. そこに論理を持たせる(まともな文章として主張を書く)

会社ではGitHub上でのアクティビティ(PRの作成とかissueの作成とか)を一覧できる仕組みがある。それを使うとGitHubで行った仕事へのポインタ一覧を取れる。レビューコメントとかは取りずらいのがネック。

SlackやNotion、対面でも仕事のやり取りや成果は発生しているがそれらを体系的に取得する方法はない。記憶と検索を頑張る必要がある。

何回か評価を受けたり、上長とお話をすることによってインストールできる

こんな感じで成果を出せたし、これくらいの評価を主張できるだろう、を想像する。数学とかでこんな感じの命題は成り立つだろうと証明を書くまえに想像するのと同じ思考。

この主張を示すためにはこの実績を説明できれば十分そう、を洗い出す

要件・主張・実績を頭に入れて、文章としてまともに書き下す。

  • 要件の理解と主張をすることは自分でやりたい。ぼくの専門性とか仕事の出来栄えは自身で認識していたいので。
  • 実績を洗い出すことはできれば自分ではやりたくない。大変なので。でもSlackとかNotionのログを洗うのは大変。
  • 主張をサポートする実績を対応づけけるのは自動化したい
  • 論理を持たせるのは半自動化したい
    • ドラフトを書いてもらいつつ、その内容を自分の中で腹落ちするものであるようにしたい

主張を書いた上で実績を対応づける作業をAIにさせたいが、どんな成果を出したか思い出すのが大変なので実績を洗い出してもらってそれを読んで記憶を取り戻したい。日記が上手に書かれていれば、それを要約するのでも構わないだろう。

2025-06-11

不変条件とそれをできるだけでかくとることについて語りたい。

不変条件はさまざまな対象に対して課される。例えばプログラム実行時の不変条件、永続化されるデータの不変条件、コードベースの不変条件などなどある。それらがロバストであり(条件を課す対象の変化に対して不変条件が変わりずらく)条件が強ければ強いほど良い不変条件だと考える。

不変条件の例として、型エラーにならないとか、メモリリークが起きないとか、データ競合が起きない、二重決済が起きない、外部モジュールのデータ構造は公開されているコンストラクタのみから構成する、外部サービスのデータにはAPIを通してのみアクセスする、などがある。アーキテクチャとか静的解析とかでは不変条件をプログラムとかサービスとかに課していて、開発ではそれを守りながら(時には条件を手入れしながら)変更を加える。

不変条件を手入れするのは一般的に難しいがそれに乗っかって済む変更は失敗したときにすぐわかるので嬉しいし、それに乗っかっている限り不変条件が守ってくれる範囲の誤りは起きないことが保証される。だからロバストで強い不変条件は良いものである。

開発に投下できるリソースが増えるほど不変条件をよく手入れすることがプロダクトを成長させるために効く。不変条件の手入れを細切れにやるのも大事だと思うが、不変条件の品質を高める技術が重宝されるとも思える。

書いてみると当たり前か。


生成AIによって変更の速度が上がったしコストをかけるのが簡単になった(採用しなくても金を払えば労働力がすぐに手に入るようになったという意味で)。この背景の変化によって不変条件を扱う戦略はどのように変えるのが最適だろうか。

2025-06-10

大阪旅行に土曜日から行っていて今朝帰ってきた。飲み会が先週の水曜日から連日会ったのと金曜日が一日研修のあとやはり飲み会でそれらが連続して記憶されているからちょっとした旅行と感じている。

水曜日から金曜日は酒の飲み方が良くなくて週末に話を聞いたり振り返ったりして反省していた。人に迷惑かけるのが良くないし、自分の幸せにもつながらないのでただ愚か。その線引きをあらかじめした上で自制できないのが良くないと思う。周囲に甘やかしてもらっているだけなのでそろそろ改善しよう。


大阪旅行は二泊三日の予定で、万博に行き、中日に山崎にいくことと、泊まる宿だけを決めていた。

最終的には僕は二泊では帰れず泊まる宿は寝る直前にみんなで変更したので半分くらいは行き当たりばったり。あと僕は初日に遅刻した。

全部ここに書くのはめんどいので思い出したトピックを箇条書きでメモ

  • 土曜日
    • ぼくが帰宅に失敗
    • 起床に失敗
    • たこ結び
    • 合流
    • 先輩
    • TW
    • かき氷
    • 未来都市
    • 住所が曖昧
    • 串カツ
    • ブルートフォース
    • やつの登場
    • アイス
    • おっちゃん
    • 風呂
  • 日曜日
    • 電車
    • おにぎり
    • 街並み
    • 神社
    • ID
    • 釜?
    • 5m
    • スチルポッド
    • アルコール
    • 原酒
    • ブレンド
    • 反応
    • ハイボール
    • 酔い始め
    • 飲み比べ
    • ノンエージ
    • ニューポッド
    • 暴れはじめ
    • 銅・新しい樽材
    • そば・天ぷら
    • 寝落ち
    • ラーメン・アイス
    • 昼寝
    • お散歩
    • プラダ
    • 天馬
    • 寿司
    • 串カツ
    • ワイン
    • 連行
    • シラフの振り
    • 脱走
    • たこ焼き
    • サウナ
  • 月曜日
    • 寝坊
    • 郵便局
    • 紀伊國屋
    • イタリア風おじさん
    • フランクフルト
    • ティモール
    • アゼルバイジャン
    • 傘・ポンチョ
    • 360
    • 紅茶
    • チュロス
    • おいしいごはんが
    • 仲良し
    • 紳士
    • イタリア
      • 優先
      • 工芸
      • 映像
      • 編集・体験
      • 心臓
      • インタビュ
      • 絵?
      • 加速
      • 空間
      • 侘び?
      • 重いやつ抱えたおじさん・筋肉・毛束
      • 筋肉聖人
      • パン・平和
      • ミケランジェロ
      • 写真・時間
      • 工業・展示方式
      • レストラン
      • ピザじゃないやつ
    • 終電
    • エスカレータ
    • 光るやつ
    • サイクロイド
    • ショップ
    • 充電
    • 発券
    • 新大阪
    • 駅員さん
    • ラーメン
    • 飲み会
    • 31
    • サンライズ
    • 車掌さん
    • パジャマ
  • 火曜日
    • 近く

金曜日に社内での研修と懇親会があり、普段は一緒じゃない人たちと一緒に飲めたのが嬉しくて調子に乗って飲みすぎた結果、終電を逃し右往左往しながら始発で家に帰った。この右往左往したタイミングで先輩の家にスマホと家の鍵以外の全ての荷物を置いてきた。

そこから「ちょっと」睡眠したところ、予定していた新幹線が出発する時刻に目を覚ました。まあしょうがないと思ってリュックに多少の着替えと充電器だけ入れて家を出たのだった。

なんやかんやあって新幹線に乗り(幸い自由席で座れた)、新大阪に着いたのが12時頃。前日の夜から何も食べていなかったので大阪っぽいものでも食べようと駅弁屋さんで「たこ結び」を買って食べた。タコでも入っているのかなと前日の酔いが残った頭で買ったのだけど、当然のようにたこ焼きが入ったおにぎりで、それが5個も入った弁当だったので一発で満腹になってしまった。おかげでアルコールの消化とその日の体力につながったのだけど。

万博会場についてゲートを潜るとなんと僕は移動が早かったようで、予定していた新幹線でちゃんと移動していたみんなと一緒のタイミングで入場できていた。合流してでっかい木造建築とか見つつ歩いていると、なんとみんなはご飯を食べていなかったのでベトナム料理を食べることに。お腹がいっぱいだったので僕はかき氷を食べた。練乳があらゆるところについていて手がベタベタになったことを覚えている。他のみんなはバゲットみたいなやつとか、味のしない麺みたいなやつを食べていた。パクチーが苦手な先輩は日本風で嬉しいと行っていて、先月ベトナムに行っていた後輩は、これはベトナムではないと話していた。そしてそのかき氷を待っている間に大学の部活の先輩とたまたま会った。向こうはたまたまご家族と来ていたらしい。世界は狭い。

なんやかんや散歩をしていたら、予約していたTech World(台湾)のパビリオンの時間になったので突撃して一瞬で入場した。瞬きをする間に社会と政治に関心のある先輩(今どき新聞を毎朝3部読んでいるらしい、同世代)Tech Worldは日本が国として認めていない台湾が万博に参加するために数年前に作られた(ように見える)企業であることを教えてもらう。形式を大事にしつつ、まあいいじゃんというところではしたたかに進めるスタイルが好き。

入場したタイミングで心拍計を渡された。場内ではそれをつけて僕の心拍をトラックするとのことだった。どの展示で心拍上がったかをみて、最後にフィードバックしてくれる。たいしたフィードバックは来ないのだろうとは思いつつ、ちょっと嬉しい。心拍計を腕につけるときに先輩に腕細いことがバレた。腕の太さってどうしたら変わるんでしょうね?この部位につく筋肉は存在するだろうか。あそこには腱しかなさそう。

最初はでかい杉(だったかの木)にもしたデカ円柱型スクリーンとそれを取り囲むタブレットによる、自然豊かな島(台湾のことぽい)の生態系の豊かさを演出していた。教育テレビに出てきそうなアニメといった雰囲気で、内容は好きだった。火の鳥をアニメ化したらああいう感じになりそう(多分すでにされているけど見たことない、偏見。あと火の鳥はほとんど読んだことない)。

次に山とかの自然環境の美しさを語る演出が会った。4Kプロジェクタとか謳っていたのだが、メガネを先輩の家に置いてきた僕にとってはなんとなく綺麗な気がするくらいなものである。それでも僕は綺麗な自然とかが好きだし、タイポグラフィの演出がよかった。文字が流れるし、その文字で構成される格言というか詩というかみたいなやつの内容が台湾の主張として好きだったという印象を持っている。さらに、霧の中の山を進んでいく、みたいな場面が映し出されるタイミングで実際にミストが流れて自分が霧の中に突入したかのような演出がされて高揚した。このエリアがTeck Worldで一番好きだった。

次は胡蝶蘭の展示。胡蝶蘭が台湾の名産であることを初めて知った(なんならあの花が胡蝶蘭であることを初めて認識した)し、それへの印刷技術はすごかった。

最後にシリコンに関する映像展示があったのだけど、それはまあ疲れちゃったのかなという感じ。映像が流れる前はディスプレイがディスプレイの顔をしていなくて、光るタイルみたいになっていた。それをタップすると剥がれ落ちて裏から光が漏れ出し未来の世界が開かれて映像が始まる、みたいな演出で会った。その演出は好きだった。そういう自分を世界観に引き込むような演出が好きなのだろうか。世界観が溶け合うのが好き?

それが終わると心拍計の計測データをもとに台湾のおすすめ観光スポットを紹介してくれるのでした。やはり真ん中の山とかの演出が一番テンション上がっていたみたい。

展示エリアを抜けると売店があって、よくわからん銭湯に売っていそうなジョウロがあったりしたけどスルーして、みんなでかき氷とお茶を注文して外に出た。

せっかくなのでかき氷をでかい木造建築(リングとか呼ばれている?)の上で食べたのだけど、落ちついて座れる場所がなかなかなくてかき氷がそれなりに溶けてしまった。芝生が広がっている傾斜地に座って一服したのだけど地面は湿っていてお尻濡れたと騒ぎつつかき氷食べたのを覚えている。先輩が持ってきてくれたレジャーシートに座って難を逃れる。

この後色々巡って万博会場を20時頃に後にするのだった。

宿への入り方が見つからないとか、串カツ屋さんがぼったくられそうで怖かったけどちゃんと上手いとか、結局宿に入れたけど色々あって泊まれるもんじゃないとかがあり、カプセルホテルで就寝。

日曜日はカプセルホテルで目覚めた。約束していた時刻に目を覚まして山崎ウイスキー工場に向かう。身分証明書もやはり先輩の家に置いてきているので年齢確認されないように大人っぽい振る舞いを心がける。それが功を奏したのか、無事に見学ツアーの受付をしてもらえる。毎度思うけど、サントリーの工場見学はホスピタリティが高い。見学ツアーの前に案内してくれる係の方が集合ロビーを回って雑談してくれる。いい方だった。

ツアーでは山崎ウイスキー工場の製造工程のそれぞれのエリアを見学する。オーバーホールの時期とのことで、稼働はしていなかったがその分じっくりとエリアを見学できた。麦を煮込む桶や醸造桶、スチルポットをよく観察できた。とはいえ単一のウイスキー工場で説明を受けてもウイスキーの味の違いがどのように生まれるかはわからないので、毎回詳しい人にアテンドしてもらって差分を説明してもらうとかすると良いのだろう。あるいは自分で真面目に勉強するか。

樽で熟成させる貯蔵庫にも入れていただいた。入った瞬間から香りとアルコールの気が強くて、ダメな人は本当にダメだろうと感じたし、自分も長くは持たなさそうと思った。あのサイズの樽で熟成させるの、工業として非効率ではないだろうか。工業ではなく職人技なのだろう。

その後、原酒と山崎の試飲、ハイボールを作る体験に参加してツアーはお開きとなった。どれも美味しかったが原種に比べてやはりブレンドされた山崎が美味しくて結局はブレンドか、と思い知る。

買い物をした後にサントリーのウイスキーを試飲できるエリアで飲み比べをする。12年とか18年とかをいただいたけど、僕はノンエージが好きなようだった。爽やかな感じがしてうまい。ニューポッド(熟成してない、蒸留直後のウイスキー)は独特のアルコールというか植物ぽいような風味がしたけど、まあ美味しかった。やはりウイスキーの方が好きだけど。この段階でみんなそれなりに酔っていた。

工場近くの蕎麦屋さんに入った。蕎麦は売り切れていた(なんてこった)ので天丼をいただく。色々あってお腹パンパンになって大阪駅に戻る。電車でみんな爆睡。

まだ酔っていたしやることも決めてなかったのでカプセルホテルでまったりした。酔いが覚めてから大阪の街を散歩して天馬に向かった。後輩がアホみたいに泥酔したので寝かしつけて三人でしっぽり飲む。ここで僕が過去に失っていた飲み会の記憶を教えてもらって反省する。

僕は万博に行きたかったのでみんなと別れて一人で行動した。荷物が邪魔だったので梅田駅の郵便局で手取り足取り教えてもらいながら、ほとんど全ての荷物を自宅に郵送に出す。

どうせ暇になるだろうと踏んで紀伊国屋書店でガイドブック、小説、14歳からの社会学を買って万博会場に向かう。会場に入ったら売店を全て回ったが目当てのグッズは売っていなかった。そろそろ万博の売店がどういうものなのかを理解し始める。とはいえミャクミャクパペットに出会って買えたので満足。可愛い。イタリア風なおじさんに「それどこで買ったんだ?」的なことを聞かれた(ような気がしている)ので場所を教えてあげた。やっぱり可愛いよね。

売店巡ってもしょうがないのでぶらぶらしつつ、一人ででかアメリカンドッグを食べる。向かいの大阪風の婦人に品評されるアメリカンドッグを一人で食べる僕。

どこか名前を忘れた国の列に並んでいる時に雨が強くなってきた。びちょびちょになっている時にその列がレストランの列であることを知る。であれば用はないので抜けて雨具を買いに再度ショップへ。アゼルバイジャンのパビリオンに行く。外は綺麗だが中はYoutubeで十分な内容だった。がっくし。

ここまででへとへとになってしまったので甘いものを食べて本命のイタリアパビリオンに行こうと決意。いのちの輝きふうチュロスを食べる。生チュロスとか言って良さそうなもので、外の揚げられている部分はもちろんカリカリしているのだけど、中の生地はもっちりというかなんというかな感じがして美味かった。青いやつと赤いやつがあり、赤ではつまらんと思い青を頼んだのだけどまぶされる砂糖が青いだけだった。めちゃくちゃ美味しいから良い選択をしたと思うことにする。

イタリアパビリオンの行列に並ぶ。ここで梅田で買った小説が活躍してちょうど一冊読み切った頃に入場した。おいしいご飯が食べられますように、みたいなタイトルの小説で芥川賞を取ったとのことだった。おいしいご飯を食べるために労力をかけることに忌避感を持つ男性と、その男性が付き合っている丁寧な暮らしをする女性を嫌っている女性が主人公。舞台は一つの職場で三人は同じ職場で働く。男性は付き合っている女性のことが性癖にはマッチしているのだけど、それ以外の点では軽蔑している。などなど。

本の内容はこれくらいにしてイタリアパビリオンに話を戻す。入場してから謎に工芸品とそれを作る職人さんがいるエリアがある。そこはスルーしてほしいと叫ぶ係員さんがいるのが面白い。あれだけ待ったのだからみんなスルーするわけあるかい、と思いつつさらっと流して次へ向かう。次へ向かうと幕の前で待たされて、時間が来るとバルクでシアターに入る。係員さんはロットを乱したくなかったんだね。そう言ってくれればみんな幸せだったろう。

シアターでは内容は忘れたがイタリアのすごいポイントを雰囲気で紹介する映像が流れる。あはー、としか思わなかったがなんとなく引き込まれる映像であった。凝ったスライドショーみたいな。

凝ったスライドショーは往々にして場面転換が凝っている。例えば画面が割れるような演出がある。イタリアパビリオンでは実際に画面が割れて、画面の奥から次の展示室が現れる。次の展示室は部屋というよりは空間で、上下左右を見渡してもそこにはイタリアの博物があるような場であった。正面には地球を抱えたなんとか像があって迫力があるし、上には飛行機が飛んでいて床には波打つような演出が、左右にはなんかよくわからないが綺麗な構造が広がっていた。これがイタリアである。

それらしい像を二体見て、宗教画とか現代アート、ミケランジェロの絵を見た。工業製品の展示もそれなり。

階段を登らされて出た先は屋上庭園だった。周囲のパビリオンや輪っかの木造建築がライトアップされた様子を背景にしつつ、庭にふさわしい樹木が巡らされていて世界観がまたガラッと変わった。外の世界に帰ってきはしたのだけどそこは庭だった。

庭を散策してふわふわした気持ちで歩いているとついには階段を降りる時がくる。よくわからない赤い布の下を3枚潜ったとき、地上に戻り徐々に元の万博会場に帰ったのだった。

出たところで溶けた石像を見てからピザっぽいパンを食べて帰りの新幹線を調べると終電は無くなっていた。気合いでサンライズで帰ることにする。

23:59:59という時刻を扱うのはやめよう

この記事は生成AIを使って書いた記事です。ほとんど生成したものですが、レビューしてありますし加筆修正を人間が行なっています。


プログラミングやシステム設計において、しばしば「23:59:59」という時刻が“終端”(end of day)として扱われます。しかし、このアプローチには多くの落とし穴(pitfalls)や混乱が潜んでいます。本稿では、なぜ23:59:59のような終端時刻を避けるべきかを整理し、より堅牢で明快な代替手法をご紹介します。

  • オフバイワンエラー(Off-by-one Error) 23:59:59を終了時刻として設定すると、しばしば「23:59:60」や「24:00:00」をどう扱うかで混乱が生じます。特に、うるう秒(leap second)の挿入時には「23:59:60」が発生し、想定外のバグを誘発することがあります。
  • 不明瞭な閉区間(Closed Interval)と開区間(Half-open Interval) 23:59:59を含むか否か、すなわち区間を[00:00:00, 23:59:59](閉区間)で扱うのか、[00:00:00, 23:59:59)(半開区間)で扱うのかが曖昧になり、仕様書(specification)と実装に齟齬が生じがちです。

  • 日次バッチ(Daily Batch)とカレンダー表示 例えば、日次バッチ処理を「23:59:59までのデータを集計」と定義すると、処理が終わるわずかな遅延で翌日の00:00:00以降のデータが取りこぼされたり、重複集計されたりする恐れがあります。
  • ユーザーインターフェース(UI)の混乱 ユーザーに「23:59:59表示」を強いると直感的ではなく、かえって誤操作を招くことがあります。多くの人にとって「23:59:59」はピンと来にくく、特にミリ秒(milliseconds)やタイムゾーン(time zone)をまたぐ場合の理解が難しくなります。

  • データベース(Database)のクエリ WHERE timestamp <= '2025-04-30 23:59:59' といった条件は、ミリ秒精度のタイムスタンプやタイムゾーンが絡むと正確性を欠きやすいです。
  • テスト(Testing)とモック(Mock)の難易度 テスト時に23:59:59を意図的に生成・モックするのは手間がかかり、テストケースの網羅性を落とす原因となります。

23:59:59を扱いたいときは、きっと何かの期間の終わりを表すことを目的としているでしょう。「終わりの時刻まで」、と捉える代わりに終わりの時刻の直前までと捉えることで、23:59:59ではなく00:00:00を扱えば済むようになってすっきりします。具体的には以下の通りです。

  • [開始, 終了) の形式 例:[2025-04-01 00:00:00, 2025-05-01 00:00:00)
    • 「2025-04-01 00:00:00以上かつ2025-05-01 00:00:00未満」という明確な条件設定が可能。
    • オフバイワンエラーを防ぎ、うるう秒も意識不要。

  • 「24:00」表記
    • 同日23:59:59の次に位置づけられるため、論理的な終端(end-of-day)を明示できます。
    • 例:2025-04-30T24:00:002025-05-01T00:00:00 と同一視されます。
    • ただし、すべてのライブラリがサポートしているわけではない点に注意。

23:59:59を終端時刻として安易に扱うのは、多くの境界値エラーや実装・運用の混乱を招く原因となります。代わりに、半開区間(half-open interval)[開始, 終了)やISO 8601の24:00表記を採用し、仕様(spec)から実装(implementation)、テスト(testing)まで一貫して明確な時刻管理を行いましょう。これにより、バグの減少と運用コストの削減が期待できます。


参考情報

以上を踏まえ、次回からは「23:59:59」という時刻を見直し、より堅牢な方法で時刻管理(time management)を実践してみてはいかがでしょうか。

A Philosophy of Software Designの読書メモ

各章のまとめをする。随時僕の思ったことを差し込む。なのでこのドキュメントを読んであの本を読んだ気になってはいけないし、あの本と同じくらいに信頼してはいけない。

  • 以下のような事項については議論がされている
    • 開発プロセス
    • 開発ツール
    • プログラミングテクニック
      • OOP
      • functional
    • デザインパターンとかアルゴリズム
  • 設計については1971の “On the Criteria to be used in Decomposing Systems into Modules” から発展がない

  • 分割統治が大きな関心ごとだが、そのための教育はされていない
    • どのように問題を分割するか
    • 問題の分割を決めることは設計のでかいタスクの一つ
  • プログラマの品質とか生産性にはそれなりにばらつきがある
    • 能力には才能ではなくて良い練習が効くのは一般的に言われているらしい
  • 設計のスキルがプログラマのすごい・普通を分けるだろうと仮定して、学部一年生に対して講義を始めた
    • 原理・原則を座学で伝える
    • ソフトウェア開発のプロジェクトもやって、それらを活かす練習をする
      • 学生はたくさんコードを書いて講師にレビューを受けて改善する
  • その講義で伝えた設計の原則を集めたのがこの本
  • この本を書いた人はスタンフォードの教授で色々ソフトウェアを作ってきた
  • 複雑さを減らすことがどの原則よりも大切

  • ソフトウェアはそれがどんなものであるかを表現できれば作れたも同然である。例えば筋肉がなくても作れる
  • そのためソフトウェアを書くのを律速する能力は、作っているシステムがどんなものであるかを理解する能力である
  • 残念なことにプログラムを成長させていくに連れて複雑さは増していく。
  • 複雑さを増すとそのソフトウェアを理解することは難しくなり、成長させる速度やコストは増す。バグも入る
  • 開発ツールで複雑さに対処することはできるし、そうしてきた
    • コード生成とかバージョン管理とかプログラミング言語とかはその例
  • ツールの力だけでなんとかしきることは、とはいえ無理
  • ソフトウェアを簡単に作れるようになって、もっとすごいシステムを安価に作れるようになるためにはソフトウェアをシンプルに保つことが必要
  • まあ複雑さはどう頑張っても増えるものではあるのだけど、設計をシンプルにしておけばソフトウェアがでかく強力になってもまだ耐えられるようにできる

  • コードをシンプルで明らかにすること: こっちはまあそうでしょう、と思える
    • 名前の付け方に一貫性を持たせる
    • 特別扱いを減らす
  • 複雑性をカプセル化する。(moduler designと呼ぶらしい)
    • 分割統治をするということ
    • 丁寧に説明すると、でかい問題を解決するために部分問題の証明を忘れられるようにすること

橋とかのデザインと違って、ソフトウェアはずっと設計を変え続けるもの。この考え方に足していないのがウォーターフォールな開発で、一度に全体を設計したらそれを開発の過程で変更することはなく、もし微妙なところが出ても書く開発対象の範囲内で対処する。

アジャイル開発は設計を変え続けるアプローチに即している。将来的に開発したいでかいものは見据えつつ全体の設計は後回しにして欲しいソフトウェアのサブセットをまずは設計して開発する。開発の段階でまずそうとわかった設計は、次の開発の前に変更してまずさを潰す。こうすることで設計の問題が小さいうちに課題を発見し解決できる見込みが増える。

こういうイテレーティブな開発では設計が終わることはない。開発者は常に設計に気をかける必要があるし再設計する必要がある。改善するために小さく刻んで開発しているのだからそれはそう。設計を改善できないのならば、アジャイルに開発する意味がない。

今日ではアジャイルな開発をしているわけで、開発者常に設計の課題について考える必要がある。設計のことに常に気をかけないということは、常に複雑さに対処しなければならないということ。

二つある

  1. ソフトウェアの複雑さを理解すること
  • 複雑さとは何か
  • 複雑さは何が問題なのか
  • 不必要な複雑さを持っていることにどのようにして気がつくか
  1. ソフトウェア開発にあたって、複雑さを最小化するための個別なテクニックを習得すること

この章では複雑さとは何かや、どのようにシステムが不必要に複雑であるかを見分けるかを議論する。設計がシンプルかを見分けるだけでは設計をシンプルに作ることはできないが、その判断をもとにシンプルに作るためのアプローチをできる。

設計方針を色々試してみれば良くて、その結果いい感じになるやつを使えば良い。そのいい感じになるかの評価をできるようにすることがこの章の目的である。

この本で議論を進めるために以下のように複雑さを定義する: 複雑さはソフトウェアシステムの構造に関するもののうち、システムの理解や修正を難しくするものである。

例えば以下のような例がある

  • コード片がどのように動作しているか理解できない
  • システムのどこを修正して良いかわからない
  • 他に影響を与えずにバグ修正をするのがむずい

要するに、理解と修正が難しければそのソフトウェアシステムは複雑であるということ。それが簡単だったらシンプル。

システムの複雑さは、コンポーネントの複雑さをその変更頻度で重み付けした上での総和であると思える。

また、読み手にとっての複雑さと書き手にとっての複雑さは異なる。書き手にとってシンプルであっても読み手にとって複雑であればそれは複雑である。自分がそういうコードの書き手であったら、その分断が起きた理由を探ると良いだろう。そのギャップを埋める必要がこの仕事にはあるのだから。

一般的に三つの兆しがあって、開発を辛くする

  • 変更範囲の拡大: 簡単にできそうな変更が思ったより大変なパターン。メンタルモデルとその実現方法があっていないときに生じる。メンタルモデルを表現する力が足りていない
  • 認知負荷: うまく使うためにやらないといけないことが多いことが原因
  • unknow unknown: 変更する必要性に気がつけなくなっていること

unknown unknownが特に辛い。変更範囲が広いのはめんどいのは間違い無いのだけど、全部対処すれば自信を持って変更を完遂できる。一方でunknown unknownは自信を持つために全てのコードを読む必要があって辛い。システムがでかいとそもそも無理。

設計の目標の一つにシステムを明らかにすることがある。認知負荷とunknown unknownを減らすことにつながる。理解もコーディングもシュッとできるのがいい。何かを考えてそれが実際に通じるかの判断も簡単になる。

複雑さの症状をざっと見て、なんでソフトウェア開発が辛くなるのかを議論した。次に複雑さの原因を議論してシステムに問題が入らないように設計できるようになりたい。

複雑さは依存と不明瞭さによって生じる。ここではそれらをざっくり語って、後の章では細々とした設計での意思決定がどのようにそれらと関係するかをみる。

扱う対象がそれ単体では理解できない、変更できないときに一緒に変更するやつに依存するという。頻繁に変更するコンポーネントが他のコンポーネントに依存していると、依存されているコンポーネントまで頻繁に変更するハメになる。そこで以下のシステムの複雑さの定義の言い換えを思い出す。

システムの複雑さは、コンポーネントの複雑さをその変更頻度で重み付けした上での総和であると思える。

依存が多いシステムではたくさんのコンポーネントの変更頻度が上がるため、システムの複雑さも大きい。

特に複雑なコンポーネントを他の変更が多いコンポーネントから依存させないことがシステム全体の複雑さを抑えるために効く。

大事な要素が明らかになっていないことを指す。例えば数値の単位がわからないとか、名前がなんの意味も表してないとか。あるいは依存が存在することが明らかじゃ無いのもそう。一貫性のなさもこの要因で、同じ名前が異なる用途に使われているとやばい。

ドキュメントがやばいことが多くの原因で、コメントをちゃんと書けばよかったりする。デザインが良ければそもそも明らかであってドキュメントを不要にすることもできる。

めっちゃコメントがいるような場合はデザインがまずいことの兆しだし、明瞭さを増すためにはシステムの設計を改善するのが正攻法。

依存は変更範囲の拡大と認知負荷に作用して、不明瞭さはunknown unknownと認知負荷に作用する。依存と不明瞭さを下げる設計技法が手に入ればソフトフェアの複雑さを下げられるはずだ。

一個一個の細かい要因が全体を壊すほどの複雑さ単独で生むわけではなくて、複数が重なり合って首が回らなくなるもの。対処するためには “zero tolerance” philosophy に従うべきらしい。

複雑さは既存のコードベースを修正することを難しく、またリスキーにする。

プログラミングタスクに際してのマインドセットは良いソフトウェア設計のために大事な要素である。

良いデザインを得るためには、すぐにコードが動くことを至上とするするtacticalなマインドセットではなくて、綺麗なデザインのために時間をかけた上で問題点を修正する方針が必要だ。

この章ではなんで戦略的なアプローチが良い設計を生むのか、そして戦略的なアプローチの方が結果的には安いことを主張する。

多くの開発ではtacticalな手法が取られる。例えばバグを治すためにその場しのぎの対症療法をするようなこと。確かにそのときは早いのだけど、良いシステムの設計が得られることはないだろう。そういうときに、少しずつ不必要な複雑さがシステムに入り込む。

そのうちしんどさに気がついてリファクタリングとかをしたくなるのだけれど、仕事には期限があって新しい機能を追加しないといけないからやはり複雑さは残ったままになる。今見えている問題にはすぐに効くパッチだけ当てて、全体をよくすることはない。

そのうちマジでヤバくなるのだけど、その頃には全体を治すのが大変になっていて、当然そんな時間を取ることはできないので諦めてずっとその場しのぎの変更を入れ続けることになる。

一回tacticalな道に足を踏み入れるとそこから抜け出すことは容易ではないのだ。

まともなソフトウェア設計者になるための第一歩は動くだけのコードでは不十分であることに気が付くことだ。タスクを早く終わらせるために不必要な複雑さをコードに入れることは許されない。コードは既存のものに追加されていくものなので、今書かれているコードを将来誰かが編集することにもなる。なので今書くコードは動くだけでなく素晴らしい設計を体現することを目標にしないといけない(もちろん動く必要はあるけど)。

Strategic programmingには投資の心構えが必要で、例えばよく考えることに時間を投資するとか、いくつか設計してみて一番綺麗なやつを選ぶとかする。変更の可能性をいくつか想定してみてまあいけそうだと思えることを検証する。良いドキュメントを書くこともその一環である。 colliraryとして、良い設計をするためにはソフトウェアを変更する能力が効く、が主張できる。ソフトウェアを変更する能力がないひとは変更に強いことを主張できないが、変更する能力がある人はその設計がどこまでの変更をどのくらいの大変さで実施できるかを評価できる。他にも、設計がまずいことに気がついたときに目を瞑るのではなくちょっと時間をかけてよくする必要がある。

最初に全部設計するのは効果的ではなさそう。理想的な設計は作りながらわかっていくものなので、少しずつのたくさんの投資を基礎の上で行うこと。 1-2割の時間を設計にかけることをここでは提案している。スケジュールを破壊するほどは長くはないし、利益を産むために十分な時間でもあるはず。

Facebook, Google, VMWareを引き合いに出してstorategicにやった方が良さそうですよ、と主張している。意味的に新しいことはここでは特に言ってなさそう。よくある(本当によくある)tactical programmingの正当化への反論をここではしている。

  • storategic programmingをしろ、効果は思ったよりもすぐに現れる
  • 明日ではなく今日やるもの
  • 全てのエンジニアが良い設計への投資をすることが効果的

開発者がシステム全体ではなく一部の複雑さだけに対処すれば良い方にすることを目的とするソフトウェア設計着本がある。 Modular designと呼ばれていて、ソフトウェアの複雑さをなんとかするためにすごく大切。

この章ではこの基本的な原則を解説する。

ソフトウェアシステムを複数の(それなりに独立した)モジュールに分解する。ここでいうモジュールはクラスかもしれないし、サブシステムかもしれないし、サービスかもしれない。理想的にはそれぞれのモジュールは他には全く依存しないで欲しい、つまり開発者はそれぞのれモジュールを他のモジュールのことを完全に忘れて開発できるようになっていて欲しい。そういう理想的な世界では、ソフトウェアシステムの複雑さはそれを構成するモジュールたちの複雑さの中で一番複雑なやつの複雑さである(あれ、そういう定義だったか。まあ気持ちはわかる)。

現実世界ではそうは問屋が卸さなくて、あるモジュールは他のモジュールの関数とかを呼ぶ必要があって、多かれ少なかれ他のモジュールを知っておく必要がある。モジュールの間いに依存が生じることもあるはず(つまりあるモジュールを変更したら、他のモジュールを変更する必要が出てくるかもしれないということ)。 Modular designの目的はモジュール間の依存を最小化すること。

依存を管理するためにはモジュールを二つの要素、インターフェースと実装に分けて捉えると良いだろう。モジュールを外から使うために知っておくべきものがインターフェースで、そのモジュールが何をするかを表す。それをどのように実現するかは表さないのが典型的。実装はインターフェースを満たすためのもの。あるモジュールで仕事をする開発者は、他のモジュールのインターフェース、そのモジュールのインタフェース、そのモジュールの実装を頭に入れて働くことになる。他のモジュールの実装を頭に入れる必要はないし、そうしないべきである。

ここでいうインターフェースはプログラミング言語の意味論で強制されるものに限らなくて、自然言語でドキュメントとして記述されることもある。そのモジュールを使うために開発者が知るべき情報は全てインターフェースの一部である。形式的でない部分はコメントとして書くしかなくて、それが正しいことをプログラミング言語が保証することはできない。そして残念なことにそういう形式的でない部分は複雑でより多い傾向にある。

明瞭に書かれたインターフェースは開発者がそのモジュールを使うために知る必要のあることを占めることであって、unknown unknownを減らす。

Modular designと関係する概念。抽象化は対象を単純化した見方のことで、重要でない詳細を捨てたもの。複雑なことをしなくてもそれを扱えるようになるので抽象化は便利。

モジュラなプログラミングではモジュールがインターフェースによってその抽象化を提供することになる。インターフェースはモジュールの単純化された機能を説明することになるということ。モジュールを使うためには重要でない詳細を捨ててそのモジュールを理解すれば済むので嬉しい。

捨てているのが重要でない部分であるのが大切。抽象化のミスり方には二つある。

  1. 重要でない詳細を抽象化に含めること: 抽象化を複雑にする点でよくない
  2. 重要な詳細を抽象化に含めないこと: 不明瞭なシステムになるのが良くない。抽象化だけをみている開発者はその抽象化を正しく使うために必要な情報を見落とすことになる

後者のことをfalse abstractionと呼ぶ。一見シンプルだけど実はそうでもないやつ。抽象化を設計するためにはどんな情報が大切かと、どのように大切な情報を減らすかが鍵。

機能的でシンプルなインターフェースを持つモジュールが最高のモジュールということになりそう。抽象化がうまくいったやつがいい。そういうモジュールのことをdeepなモジュールと呼んでいる。

反対にインターフェースが複雑な割に大した機能を提供してないものはshallowなモジュール。

我々はモジュールをdeepにすることを目指すべきであって、そのインターフェースの絶対的なサイズは問題ではない。

  • モジュールをインターフェースと実装に分けて捉えることで、その複雑さをシステムの他の部分から隠せる
  • そのモジュールを使う側はそのインターフェースだけに気をかければ良い
  • 大事なことはモジュールが深くなるように設計すること。そうすれば隠蔽できる複雑さを最大化できてシステム全体の複雑さを抑えることに貢献できる

2025-04-27

学生の頃に数学の先生が図書館で本読むとインターネットとかで調べるのと違って周りの本とかにも目がいって視野が広がっていいぞ、みたいなことを話していた。いらないことを言わないで聞いたことに対して察して回答をしてくれるAIがついているので、視野が以前に増して広がりにくくなっているだろう、と考えられる。実際にそうかの判断はまだ下せないと思うけど。脱線とか下手くそな質問によって見えていなかったものが見えることもあるし、そもそも今までは答えに辿り着けなかった疑問に対しても今なら到達しやすくなったと思う。速度が上がればもっと遠くに行ける気もする。なので視野が広がる力が働いているとも思える。

AIも検索も読書もすればいい

2025-03-25

  • 以下の三つについて紹介しつつ、ぼくの信じる主張をする
    • how to design programs
    • a philosophy of software design
    • di: これについては良い書籍を思いつかなかった、気持ちは以下からえている
      • インターフェース設計
      • unixというかパイプ、gatherじゃないけどあのschemeの書籍に書いてあったアレみたいな原則
      • mock
      • 逆数学
      • 取り回しやすい、仮説と結論の関連付けをする含意
      • effect system
      • type class

fishで設定ファイルを一発で開くコマンドを書いた。導入したてのツールだとこまめに設定ファイルを編集したい。わざわざ.confgまで行ってあれこれするのが面倒なので、このコマンドを使うと幸せ。

function conf  --description 'この関数にハードコードした設定ファイル一覧からをfzfで選択してEDITORで開く'
    set -q EDITOR; or set EDITOR vim

    # パスはfishの組み込みによって解釈される
    # 相対パスに解釈される場合はXDG_CONFIG_HOMEを常に基点として扱う
    set -l configs \
        'fish/config.fish' \
        'fish/functions/conf.fish' \
        '~/.local/fish/init.fish.secret' \
        'ghostty/config' \
        'git/config' \
        'nvim/init.lua'

    # 名前一覧をfzfで表示
    set -l selected_path (
        printf '%s\n' $configs | fzf --prompt="Edit config> "
    )

    test -n "$selected_path"; or return

    # パス展開(~など対応)
    # https://fishshell.com/docs/current/cmds/path.html#normalize-subcommand
    set selected_path (path normalize "$selected_path")

    # 絶対パスでないならXDG_CONFIG_HOMEを前置
    if not string match -q --regex '^/' $selected_path
        set selected_path "$XDG_CONFIG_HOME/$selected_path"
    end

    # ファイルの存在確認をしてエディターを起動
    if test -f "$selected_path"
        $EDITOR "$selected_path"
    else
        echo "Config file not found: $selected_path"
        return 1
    end
end

2025-02-18

生成AIを壁にして議論することが不毛に感じる。自分で思考することを放棄して生成AIに言わせたいことを言わせるゲームになるのが不毛であるように感じる。あいつはぼくに質問をしてこなくて、なされるがままに僕の願いを叶えるようにチューニングされている。ぼくは議論を通じて思考を深めて問題領域の理解を深めたいが、そのための思考をあいつに渡してしまうことになる。俺が論じるからお前は俺の考えをできるだけ簡潔に論破しろ、とか言えばいいのだろうか。

試したらいい感じだが、体力が必要。

文句のつけようがない主張をすると、へりくつ捏ねる子になっちゃった。難しい。

去年のどこか暗いからTwitterの僕のTLとかその周りでWebアプリケーションのバックエンドのロールを作るためにイベントの概念にフォーカスすることが流行っているように感じる。

以下のようなバズワードが飛び交っている。

  • イベントストーミング
  • イベントベースなドメイン駆動設計
  • イベントソーシング
  • EDA (イベント駆動アーキテクチャ)
  • CQRS
  • 非同期処理

それぞれがどのレイヤ(プログラミングの工程)で使われる言葉なのかを分類すると以下のようになると思う。

  • 問題領域のモデリング
    • イベントストーミング
  • 問題を解決するためのシステム設計(システムのモデル作成)
    • イベントベースなドメイン駆動設計?
  • 永続化する際のデータ表現とその解釈
    • イベントソーシング
    • イベントベースなドメイン駆動設計?
    • CQRS?
    • 非同期処理
  • コンポーネント間での通信方式
    • EDA
    • CQRS?
    • 非同期処理

  • ソースはどこだよ!って感じなので文章をあさって明記したい。
  • 有効性は?
    • これらの考え方、開発手法、アーキテクチャはどんなときに有効で、どんなときにもっと普通で良い解決方法があるだろうか。

イベントを永続化して、それを発展させるための手法を紹介する書籍として、Versioning in an Event Sourced Systemがある。

エンジニアのフォロイーがTwitterで増えてきたように感じるので、RSSからTwitterに投稿するのをやっても良いかも。

以下の記事を参考にできそう。

https://efcl.info/2023/05/28/rss-to-twitter/

僕はブログを

  • 長めで
  • 自分の資産として管理可能な
  • 編集可能な

ツイートだと思っている。なのでTwitterrで宣伝するのはターゲットが合致して良いだろう。

2025-02-11

普通のGitHubのリポジトリのコードではパーマリンクをコマンドから取得できるのだが、GHESだと何かがうまくいかない。エラーメッセージは以下。

Failed to copy permalink: failed to parse Git remote URL

おそらくremoteのドメイン名がハードコードされているとかだろう。

該当のエラーメッセージを出力しているのはここみたい。

https://github.com/zed-industries/zed/blob/2e7bb11b7d5de6a79bef2491fa5ce8ecfd2bca15/crates/project/src/buffer_store.rs#L1673-L1675

そしてそこで呼ばれているのがこれ

https://github.com/zed-industries/zed/blob/2e7bb11b7d5de6a79bef2491fa5ce8ecfd2bca15/crates/git/src/hosting_provider.rs#L168-L184

pub fn parse_git_remote_url(
    provider_registry: Arc<GitHostingProviderRegistry>,
    url: &str,
) -> Option<(
    Arc<dyn GitHostingProvider + Send + Sync + 'static>,
    ParsedGitRemote,
)> {
    provider_registry
        .list_hosting_providers()
        .into_iter()
        .find_map(|provider| {
            provider
                .parse_remote_url(url)
                .map(|parsed_remote| (provider, parsed_remote))
        })
}

正しくURLをパースできるhosting providerが存在しないのでエラーになっていそう。Hosting providerは以下で設定されている。

https://github.com/zed-industries/zed/blob/2e7bb11b7d5de6a79bef2491fa5ce8ecfd2bca15/crates/git_hosting_providers/src/git_hosting_providers.rs#L11-L38

/// Initializes the Git hosting providers.
pub fn init(cx: &App) {
    let provider_registry = GitHostingProviderRegistry::global(cx);
    provider_registry.register_hosting_provider(Arc::new(Bitbucket));
    provider_registry.register_hosting_provider(Arc::new(Codeberg));
    provider_registry.register_hosting_provider(Arc::new(Gitee));
    provider_registry.register_hosting_provider(Arc::new(Github));
    provider_registry.register_hosting_provider(Arc::new(Gitlab::new()));
    provider_registry.register_hosting_provider(Arc::new(Sourcehut));
}

/// Registers additional Git hosting providers.
///
/// These require information from the Git repository to construct, so their
/// registration is deferred until we have a Git repository initialized.
pub fn register_additional_providers(
    provider_registry: Arc<GitHostingProviderRegistry>,
    repository: Arc<dyn GitRepository>,
) {
    let Some(origin_url) = repository.remote_url("origin") else {
        return;
    };

    if let Ok(gitlab_self_hosted) = Gitlab::from_remote_url(&origin_url) {
        provider_registry.register_hosting_provider(Arc::new(gitlab_self_hosted));
    }
}

ここでgithub.com以外の処理を諦めている。

https://github.com/zed-industries/zed/blob/2e7bb11b7d5de6a79bef2491fa5ce8ecfd2bca15/crates/git_hosting_providers/src/providers/github.rs#L111-L128

現在のプロジェクトがどのGitHostingProviderを使っているかを誰も管理していない(?)ぽくて、外部からそれに依存した操作をする際は、GitHostingProviderRegistryに登録されたもの全てを試してうまくいった結果を使う、としているのがよくなさそう。以下のように作りを変えると良いだろう。

  • まずはプロジェクトに対してGitHostingProviderを対応づけること
  • 外部からGit関連の操作をするときはRegistryを経由しないでプロジェクトをに登録されているGitHostingProviderを使うこと
  • 必要に応じて手動で対応づけや設定をできるようにすること

あるいは拡張機能としてねじ込むのが正解か?GitHubとGitHub Enterprise Serverの違いがどんなものか次第でもあるので、そちらの調査もしたい。

LSPサーバがある前提で、そのクライアントをZedに追加する。PythonのLSPクライアントの実装があるので、それを参考にbuf LSPを使えるようにする。

https://github.com/rgbkrk/python-lsp-zed-extension/blob/main/src/python_lsp.rs

何も理解してないけどローカルでクライアントをビルドして定義ジャンプを実行するところまではできた。次は何が起きているかを調べていい感じにする。 zedにマージするまでがゴール。

Zed extensionを理解して、gitのアレをextensionとして実現できないか判断したい。

吉祥寺.pmとBurikaigiに登壇参加した

1/31に吉祥寺.pmのLT、2/1にBuriKaigiのセッションで発表しました。カレンダー上で予定かぶっていないことだけしか確認せず勢いで楽しそうなカンファレンスの楽しそうな枠に申し込んだところ、発表の間の時間が12時間くらいしかなくて大変でした。とはいえそれぞれの発表に対して準備をして知見を得られたし、聴衆と意思疎通できたとも思っています。登壇できてよかった。

主催者のかた、参加者のかた、ありがとうございました!

この記事では発表したことにフォーカスして感想をメモしますが、参加者として発表を聴いたり懇親したりするのもとても楽しかったし刺さるセッションがいくつもありました。本当に参加できてよかった。

waiwai-aiを入社2ヶ月の エンジニア3人と作るための さいきょうのアーキテクチャ(スライド)では、昨年5月に新卒研修の一環(自分はメンター)で参加したお産合宿について話しました。

逆コンウェイの話をツイッターで指摘していただいたり、ブログで記事を参照していただいたりと反応を頂けて嬉しいです。

お産合宿は業務での開発が佳境な時期に参加しており、直前まで本当に参加できるかも怪しかったことを思い出します。翌日のBuriKaigiでwaiwai-aiを発展させたデモを3人の新卒エンジニアのうちの一人がしており、意外と長生きだなと思います。

CLIツール開発をProtocol Buffers スキーマで駆動する(スライド)ではHow to Design Programsを引用して、上手なプログラミングはどのように行うものであるかを主張しました。そこでは関数を実装するための上手いやり方を主張しており、それをWeb API開発やCLI開発に応用する(より大きな粒度のエンジニアリングに適用する)ために、具体的に何をすれば良いのかや、どのような障壁がありそれらはどう取り除けるのかを主張しました。

スキーマ駆動のこととCLIについての話をすることだけ先に決めており、How to Design Programsやそのアイデアを引用すると良いことに発表直前の月曜日に気がついたため準備が忙しかったです。今回の最大の収穫はその気づきを得たことだと考えています。学生の頃に取り入れた知見がまさかこんな形で役に立っていたとは思わずすっきりした気持ちになりました。

セッション直後に余った時間で2,3名の方から質問を頂けた(しかも芯を喰っていた!)し、ツイッターやブログでも感想をいただけたので主張は伝わったのだろうと感じています。嬉しい。

鰤しゃぶを初めて食べたのですがとてもおいしかったです。また食べたい。

また今回は資料作りについて裏テーマを二つ設けていて、それらがうまくいったのも嬉しかったポイント。

  1. スライドデッキの構成を決めてからスライドをつくる。スライド作成での手戻りを極力減らす
  2. 図を上手につくる

発表の準備に時間がかかること、疲れることがこれまでの課題だった。考えることに時間と体力を使いたい、思考の速度で準備したいのがモチベーション。今まではスライドデッキを作ってから「この主張をここでしてもしょうがないな」とか「この図はいらないな」が多少あった。それらを排除して不要なスライドを作成するのに労力を割かないようにするのが1個目の目標。

CfPがあるタイプのセッションだったので、発表内容が完成する前にタイトルとセッションの内容を決める必要があったのが効いたと思う。考えているうちにそれが本題ではなくなってしまったのだが、うまく話を構成するためにだいぶ主張と構成を練ることに繋がった。あと、時間が本当になかったのと完成度に対する欲求があったので、この目標を達成することが満足のいく発表をするための必要条件でもあったのだ。切羽詰まった結果実現できたパターンでもあったということ。

Google Slideの作図機能はそこまでリッチなわけではないし、どんなに頑張っても限界がある、表現力もそんなにという具合で、サクッと数分で準備をするには良いが気合いを入れるときに使うものではないと感じていた。出来上がる図も綺麗でもなければ図自体がわかりやすくなることはなかったと思う。全体的にいい感じに仕上げることは何度かできたけど。

draw.ioを試しもしたが、字が小さいとか矢印の扱いが難しいとかでしっくりきておらず他のツールをなんとなく探していたのだった。そんな中、発表直前の木曜日に自席に遊びにきていたデザイナの同僚から紹介されたFigJamがいい感じ。初めて紙で書くより上手に図を書けている。矢印が本当にいい感じになるし色んな微調整もしやすい。

学生の頃はこのあたりのテクニックなしで、発表の数日前からギリギリの顔をして資料作成にフルコミットすることで乗り越えていたが、今回は日中は仕事をしつつ準備を終えることができた。成長。

2025-01-26

/etc/hosts で以下のようにしてツイッターを封印している。

127.0.0.1     twitter.com
127.0.0.1     x.com

次の週末にある登壇資料を作っている。インターネットにある情報を拾う必要のあるケースもあるので、インターネットには繋がりたいが、ツイッターを開いた瞬間に全てが終わる。そんなぼくをがツイッターに吸い込まれるのを防ぐために、DNS問い合わせを潰している。だいぶ助けられている。

https://www.graco.c.u-tokyo.ac.jp/labs/morihata/presentation_memo.htm#o-enumerate これを読みながらやっている。学生の頃からチラチラ見ていたが、だんだん染み付いてきた。

2025-01-13

昨日は友達とキリンビール工場に行ってきた。500円のツアーがあってビール作りの概要を教えてもらいつつビールを飲ませてもらえる。だいぶ楽しかった。あの体験は優しさで成立していると思う。

原料となる麦やホップを食べさせてもらえたほか、ビール製造の中間生成物である麦汁の飲み比べをさせてもらえた。何より説明してくれるお姉さんがビール好きで、1つ質問すると厳選した3つを返してくれるのが良かった。一緒に飲んで欲しい。飲ませてもらったビールもめちゃくちゃおいしいし。併設されているレストランに行けていない(リサーチ不足でご飯を食べてから行ってしまった)のと、他にも見学コースがあるみたいなのでまた行きたい。

ホップを使ったリンスを買って使ってみたら、髪からフルーティ系なビールの匂いがして最高。

AIに仕事を奪われることはないだろう。とはいえ単に作業をするだけの労働はAIに奪われる。コードを単に書くのは作業であって、仕様からコードを生み出すだけならAIでやった方が早いし(今の相場なら)安いから。

とはいえそんな単純作業が仕事であることはなくて、将来のこととか仕様の考慮に入っていなかったことをコードを書きながら調整して主体として責任を持って成果を出すことは、社会がまだAIに対して認めていないように感じる。

誰もが優秀な部下を持つようになったが、人々は誰かに責任を持った主張をして欲しくいのだろう。ポジションをとって主張をし、ダメだったときは失落したり挽回することを人格に求めている。信頼をして仕事を任せる相手は人間じゃないと嫌だと社会が思っている。

そういうわけで人間は労働力としての生成AIを手に入れただけであって、人間社会で主体として認められたあらたな人格を手に入れたわけではない(今のところは)。成果を出すためには社会が理解できるポジションを取ることが必要で、そのロールモデルの振る舞いとして社会と交流しないといけない。どんな振る舞いをするのが良いか決めるために生成AIを駆使する仕事の仕方が増えるだろう。ロールモデルには矛盾なくとりうるアトミックな行動があって(思想とか哲学みたいなもの)、それを組み合わせることでその人らしい振る舞いが形成される。思想とか哲学とかに一貫性がないと社会から信頼してもらえない。一方で外部から同じ要求がなん度もくることはないため、それに応じた異なる振る舞いをする必要はある。思想や哲学から外部刺激に対して振る舞うことにはエネルギーとか思考とかが必要で面倒だから生成AIを使うと便利だろう。

これはプログラミングにも応用できる。アプリケーションのコアなロジックのインターフェースは綺麗に設計されてクライアントから受け入れてもらう必要がある。そこがブレると利用するのがそもそも大変だし、見出した価値がすぐに失われてしまうだろう。一方で、それを活用して振る舞いを追加したり修正することは生成AIがこなすだけで十分なのではないだろうか。振る舞いを追加することは、そのアプリケーションのコアな部分のインターフェースと世の中によく知られた技術要素のインターフェースを組み合わせて表現できるだろう。

外部からの要求に応答して振る舞いをしたりインターフェースを利用して新たな機能を提供する際に、コアな思想を見直してアップデートすることもあるだろう。とっているポジションをちょっと変えるということ。使う側からすると理解の仕方をちょっと変えないといけないのでこの変更が気に食わなかったり理解できなかったりすると嫌な感じがする。変化の速度が早すぎて理解が追いつかないとたとえ良い変化であったとしてもアンチになってしまい信頼をなくすことに繋がる。そのため人間に直接理解されるインターフェースは人間に合わせた進化をしないと社会に適合できなず、市民権を失う。

したがって生成AIはインターフェースを提供するソフトウェアエンジニアの職業を奪うことはない。一方でインターフェース設計に関与しない、定義されたインターフェースの中だけで作業をして、他人と相互作用をするインターフェースを定義しないエンジニアリングは生成AIのコストに負けて自動化されるだろう。

次に、他人と相互作用するインターフェースのあり方が変化するかが問題になる。これまで公開されて使われていたようなインターフェースは今後も必要だろうか。インターフェースを解釈するのが生成AIだけになれば、その変化が早くても理解が追いつくためわざわざポジションをとったり人間の理解速度に変化の速度に合わせる必要がなくなる。これは作り上げるものの抽象度の違いに依存するだろう。何かを作り上げたかったらその一段下の抽象度の言葉で構成を説明してほしい。妥当性を検証するために。そこから下は信じることにして(信じられる何らかの根拠を持つことになる、ここも何か困難があるかも、今は著名なOSSだからokとか言って信用することにしている)、欲しいものの一段下のレイヤで自分で納得がいけば良いものであると判断する。

そして、人間の思考とか議論のレイヤは高々10とかにおさまっており、それが生成AIの登場で変わるとも思わない。なのでインターフェースを人間が作ってポジションをとる必要性も今後変わらないと思う。根拠はなくて直感だし、多分僕の願望も入っっている。

良いインターフェースを定めるために、鍛錬を積む必要はあり、それは生成AIによって取って代わられる仕事でなされることが多い。生成AIを使って仕事をやる先端のインターフェース提供者と、そこから学べない後進が場所によっては生成AIがやる仕事をするローカライズされたインターフェースの提供者が並行して存在する世界になるだろう(生成AIに限らずこの状況はあるだろうが)。

2025-01-04

過去に何個か一人でCLIツールを作ったことがある。そのときに雰囲気で乗り越えてしまいストレスの少ない綺麗な書き方を知りたかった概念をあげる。

  • エラーハンドリング
  • 参照周りの型変換
    • 特にパターンマッチやforループ、関数定義で & 記号を書く構文特有の意味があるときがよくわからない
  • ライフタイム
    • 実用的に我々はどんな塩梅で書くのが良いかとか、誰が所有するのが良いかを判断するためのベストプラクティスを持っていない
  • トレイトの勘所
    • ユーザ定義型に機能を実装するときに、どういうインターフェースを持たせるか迷う。どのようなトレイトを実装するかを決められない。クライアントとしての標準を知らないのでサーバとして何を提供するか、常識をもとに判断できない

要件を定めてそれを保証する仕事がソフトウェアエンジニアの仕事になるだろう。それだと単発の仕事か。進み方を把握して、それを促進する作りにする必要はあるはず。

プログラムの開発(状態や環境に反応するソフトウェアの開発)自体は生成AIによって簡単になった。要求や要件を実現することしかまだ生成AIのブラックボックスに入れられていない。要求や要件の整理の道具として生成AIを利用してはいるが、

これからは生成したプログラムに対して保証された機能の制限が大事になってくるだろう。プロダクション環境で動くプログラムを見る人間は減り、その代わりにソフトウェア検証、パーミッションの制限で安全性を保証したり、デモで振る舞いを確認する未来がくるだろう。ソフトウェアを実装するコストが低くなり、つまりソースコードに向き合う機会が減り、コードの振る舞いを静的に理解しなくなっていく。あるいは言語を高級にするだろうか。言語にどんな性質があると幸せ?

生成して良い言語に良い性質を持たせることはありそうなアプローチ。

仕事は確かにたくさん奪われそうだけど、契約をデザインして(うまくそれを表現することを含む!)プログラムを作り上げる営みは楽しいからずっと続けると思う。

2025-01-03

https://dev.nfurudono.com/posts/go-errors-stacktrace に移転しました。

大掃除は年末にしたのだけど、コーヒーグラインダーを掃除し忘れていたのでやった。結構な量の粉が中から出てきて驚いた。豆を砕く場所と粉が出てくる穴の間に傾斜した通路があってそこに溜まっていた。

今日も餃子を作った。昨日たねを作りすぎたので。ちょうど買い足した餃子の皮を消費できた。蒸しと焼きの両方やって昨日と同じ感想だった。たねを作るときに白菜の水分を抜く工程を入れていたが次回は外してみようと思う。

明日は鮭のホイル焼きをしようと思う。衛宮さんちの今日のご飯に感化された。

  • 鮭・玉ねぎ・にんじん・しめじを適切に処理する
    • 鮭には酒と塩を振って5-10min放置してから拭き取る
    • その後酒に塩胡椒を振る
  • 玉ねぎ・にんじんを敷いて、その上にコンソメをかける
  • 全てを載せつつバターも添えてホイルに包む
  • 加熱する
  • パセリか何かをかけるらしい
  • わさびマヨがあっても良いとか

朝は納豆とかかな。卵も食べよう。 朝はサンドウィッチにする。ほうれん草、卵、ベーコンを入れたい。卵しかないので買い出しが必要。パンもない。

2024-12-25

関数の引数はそれぞれ何で、どんな性質を期待するかや、そのほかの事前条件を満たした上でこの関数を呼び出すと、その結果としてどんな返り値が得られてそれ以外にどんな副作用があるかを表明するのが関数の契約。文章を用いるのが簡単だし、伝えやすくするには図を用いても良いし、型とかバリデーションのための式で表現しても良い。何にしても契約を表明すると楽しくプログラミングできる。

この関数の呼び出し側はどんなふうにこの関数を使って処理を実現するだろうかとか、この関数を実装するときはどんなふうに作ろうかと考えるのがまず楽しい。みんなが幸せになれる契約をデザインするのが楽しい。ソフトウェアのテストは契約を守っていることを検証することだと思う。型を用いた表現は契約の表明で、型検査が検証(それも厳密な)である。

このように良い契約をデザインするのがプログラミングでまずやることだと思う。その次に自動で検証するためのコードを書くのがTDDの人だし、関数型の怖い人は型で契約を表現しようとするかもしれない。そのためにすごい表現力を持つ型システムを考えて勉強して使う印象がある。

TDDで最初から完成版のテストを書かないことからわかるように、契約を最初から詳細まで書く必要はない。そんな契約を満たす実装を書けるだろうかと思うこともある。なので最初はふんわり「ユーザの情報を返すAPI」とか決めておいて、IDが欲しいとか、シャーディングしてるから作成日時も欲しい、みたいな事前要件を足したり、ユーザ情報全部返すのはきついし呼び出しがわも幸せじゃないから、名前とメルアドだけ返すことにする、みたいな調整も入るだろう。課金が滞っているユーザに対しては普通の結果は返さない、代わりにエラーを返す、みたいな変更も実装したり呼び出しているうちにしたくなるはず。

結局のところ普通のプログラミングをしようと言っているだけなのだが、僕が強調したいのは契約と実装を分けて考えようということ。契約が先にあってそれに実装を合わせる(合ってない状態はバグってる状態)考え方でいたいし、僕と契約を共有する人には(その共有する契約のレイヤで)いて欲しいと思う。

僕はmac osのコードがどうなっているかを気にすることはなくて、普通にパソコンが動けば満足するし、実際動いているので不満はない。キーボード叩いたら文字が出るという契約を守ってくれている。でもosのapiを叩く友達はそもそもドキュメントが公開されてなくて辛い、みたいなことを言っていた。このように、自分が関心のあるレイヤの契約が問題になるのだと思う。

契約はプログラミングの細かいレベルだと変数の名前とか、改行の置き方によって表明されるもので、大きいレベルだとサービスやロールの責務として表現されると思う。サービスのAPIは代表的な契約だと思う。APIという言葉は契約と同じような意味だと思うけど、エンドポイントみたいな意味でも使われているし責務みたいな概念には適用されないと思っていて使わない。

僕たちが欲しいものは何かを表明しよう、というのが契約を表明しようということだと言い換えられる。使う側からしたらその実現方法は関係ないし、提供する側からしたら契約さえ満たせば何をやっても良い。 getterとsetterを提供するからと言ってそういうフィールドをよく知られた方法で提供しないといけないわけではないし、バッファリングとか遅延実行をしても良い。

未定義な状況とか意図しない状況はある。今と昔では状況が変わって、その頃は妥当に思えた契約が時代に合わなくなることもある。契約がないと実装が良くないで話が終わってしまうが、契約があれば仮定が違ったのだと結論づけられる。人の記憶があればその人の心に契約があって仮定が違ったと判断できるだろう。記憶を失ったりその人が失われたりする場合は契約を表明しておくべきだろう。

型はデータ構造やその不変条件を表現したりそれらに名前をつけることで、契約を表現する。そして型を用いて表明された契約は普通型検査によって契約が満たされていることを検証する。正しい場合には正しいと判定するし、正しくない場合には正しくないと判定する。さらに、ある程度ちゃんとした型検査器は、どのように契約が満たされなかったかを説明してくれる。

テストは契約を検証するためのコードで、そのテストが契約のどんな部分を検証するか、テストケースの名前として表明される。その表明を満たすようにテストコードが実装されて、テストランナーに呼ばれる。契約のどんな側面をそれぞれのテストケースで検証するか、検証すると幸せか(誰にとって?)を決めるのはテスト実装者のスキルに依存するだろう。契約の中で脆いところを普通は検証するのだろう。明らかに正しそうなやつは手を抜いてしまえるはず。

バリデーションも契約を表現する手段の一つ。契約を検証処理として実装して表明するのがバリデーション。型と同じようにすべての実行について契約が満たされるかを検証する。一方でテストと同じように実際に動くものに対して検証を行う。

実際に動かして試すのは何だろう。契約とはあまり関係なさそう。実装したやつがどんな感じになってるか微妙なので試して動作を観察するのがとりあえず動かしてみる目的。これは脇道だったな。ただし、あまりによくわからなくなっているときは分割統治をするときだと思う。自分の手の中にある対象をコンポーネントに分割して、それぞれに対して契約をデザインする。その契約を満たすように実装しつつ、その契約を期待して組み合わせて元々の目的を達成すれば良い。わからない部分が新しい契約の内側にはいれば小さくなった簡単な契約を満たすことに問題は帰着できたし、それらの契約を組み合わせることに課題があるなら詳細を忘れて便利な道具を手に入れられたのだからやはり問題は簡単になっているはず。うまく契約を設計することが難しいなら、それは楽しいから問題ない。ずっと取り組んでいればいい。

何にしても契約を表明することが何より先にくる。これだけでプログラミングが楽しくなる。その後に型、テスト、バリデーションを書いたり実装をしたりする。

そういう考え方が how to design programsにデザインレシピとして書いてあるのでよかったら読んでみてください。

プログラミング言語はこの辺りが優秀で、型システムの研究とかで契約を表明して保証する方法を検討しているし実際に生かされている。なので言語に守られているうちは割と安心できる。あとは怠慢にならなければいいだけ。

プログラミング言語に閉じられなくなるとき、例えばWeb APIを提供するときは急に難易度が上がる。Web APIでも契約を表明して検証するためにスキーマ駆動開発がある。契約を書き下すことを支援するのはもちろん、型とかバリデーションで表明することも支援する。テストツールの支援もある。

僕たちが求めているのは以下である。

  • 契約を表明すること
  • 契約を洗練すること
  • 契約を犯せないようにすること
  • 契約を犯しかけたらなるはやで誰かに教えてほしい
  • これらを簡単に実現できること

最初のやつは設計しようぜ!という話。次が設計技法とか良い設計みたいな話。三つ目は型とかバリデーション、テストの話。次もそう。最後のやつはそれら全てを支援するエンジニアリングの話。

契約の話をしたのでパラダイムの話をしたい。オブジェクト指向と普通のやつの話。どっちでもいいけど、契約を表明しやすいパラダイムが良いと思う。

オブジェクト指向な考え方だと、内部状態を持つオブジェクトがメソッドを受信してその結果内部状態を変えたり返信したりする。そういうふうに契約を表明して守っていくならオブジェクト指向を使えばいい。

関数型みたいな普通のやつは、仮定が与えられた状況で関数を呼ぶと結果を出す。そういう契約の書き方をするなら関数型みたいに書けばいい。

どちらも相互に変換可能だから力まず表現しやすい言葉遣いを使えば良いだろうと思う。

割と思いの丈をダンプした。これは就職したからできたことのように思う。学生の頃に培った理想が現実世界では必ずしも簡単に実現しないことを体験できた。自明だと思っていた領域の非自明な部分に気がついて思うところが出てきた。

プログラミングの楽しいところは、ロールを分けてうまく契約群を設計することにあると思う。フレームワークを作るのはそういう契約の集まりを定義することだから楽しい。一方でフレームワークを使うと契約を設計する機会を奪われる分楽しくないかもしれない。

その分他のレイヤに注力すればいいのだろうが。

自分が自由に設計したいレイヤで他人に契約を決められるとストレスだろう。本当につまらない。反対に自分が関心なくて誰かにうまくやって欲しいときには良い契約を強い人に決めて欲しいと思う。そういうレイヤを担当するフレームワークを使って欲しいし、技術を選定したい。

アーキテクチャ設計についても言及できそう。アーキテクチャは中長期的には変遷するものだが、短期的には変わらない。アーキテクチャに乗っかってここのコンポーネントを作り込む。ここのコンポーネントをストレスなく作り込みやすくするアーキテクチャが良いアーキテクチャなのだろう。

2024-12-13

  • kamakura.goの感想とかを書く

2024-12-12

We recommend that all third-party code generators be written as plugins, as this allows all generators to provide a consistent interface and share a single parser implementation.

https://protobuf.dev/reference/other/#plugins

はえ〜って感じ。Goのライブラリはだいぶ使い勝手良かったのでまあ確かにと思ってる。

2024-12-05

viperってinit使わないといけないのかな。 viperに依存性を注入するような使い方をしたい。Facadeを受け取ってCLIを返すようなCLIジェネレータを定義しようとしていて、CLIジェネレータを実装するためにviperの諸々をinitとかで終えようと思うと困る。実行時にfacadeを入れたいので。

2024-11-28

Reactのカスタムフックの心をわかっていなかったけど、クロージャに変数をキャプチャさせて、状態をもつクロージャ(の組)を返す関数がカスタムフックぽい。組と言ったのは、getterとsetterが別々に提供されることがあるから。例えば const [v, setV] = useState()v がgetterで setV がsetterと思える。

カスタムフックの呼び出しもとの再レンダリングのたびに返却する関数の実態が同じにするかしないかは、useCallback を用いて制御できる。例えば useStateuseCallback してると思える。

このようなプログラミングテクニックを用いると、振る舞いを実現するクロージャだけが定義されていて、それが裏で扱う状態遷移がフック定義の中で隠蔽されるのが嬉しい。

カスタムフックのモチベーションは単に状態を関数型っぽいやり方で扱いたいだけなのだと理解した。

OCamlでのmutable counterの実装例を見つけた。鉄板の例だと思う。僕はこれをイメージして状態を保つクロージャと呼んでいた。

2024-11-27

Branded typeはTSでnominal typingっぽいことをするためのプログラミングテクニックの一つ。Branded Typesを導入してみる / TypeScript一人カレンダー が詳しい。

僕はこんな感じに実装に入れてみた。https://github.com/naoyafurudono/naoyafurudono.github.io/commit/778270955b4c4e7672f50600fb28dff6c12b9fa0

全てがstringになりがちで不安になるけど、これなら安心安全。型の名前を信用できるようになって、名前をつける意欲も湧く。嬉しい。

makeって、ある種CLIのDSLみたいなものだが、helpを自動生成してはくれない。いい感じにやるための工夫を見つけたのでシェアする。

以下はconnectrpcのサンプル実装リポジトリにあったmakefileの一部

.PHONY: help
help: ## Describe useful make targets
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-30s %s\n", $$1, $$2}'


.PHONY: all
all: ## Build, test, and lint (default)
	$(MAKE) test
	$(MAKE) lint


.PHONY: clean
clean: ## Delete intermediate build artifacts
	@# -X only removes untracked files, -d recurses into directories, -f actually removes files/dirs
	git clean -Xdf
...

make help とすると、呼び出せるmakeのtarget一覧とその説明を出力してくれる。便利。コメントのフォーマットを定めておいて、helpを呼ぶときにはawkとかでmakefile自身を処理することでヘルプを出している。

2024-11-26

https://architecture-con.findy-tools.io/ これに来ている。

登壇資料のまとめがあるとのこと

これはあくまで僕のメモであって、発表とか僕がお話しした人がこのまま主張したわけではないです。変なところがあれば僕のせいだし、良い主張があれば彼らのおかげです。繰り返しですが僕のメモなので第三者が読んで何かに活かしたり議論の種にすることは、しない想定です。僕が便利なのでインターネットにおいておくだけ。

  • トレードオフ分析をすることが仕事
    • 最強ソリューションを出すことではない
  • トレードオフは絶対にある、ないと思ったらまだ見つかってないだけ
  • https://speakerdeck.com/findyinc/modern-trade-off-analysis?slide=15
    • デザインは挙動に関する議論であるがアーキテクチャは能力に関するものであるから、徐々に変えるのではなく最初からスパッとやらないといけない
  • フィードバックが早いのは良い。軌道修正はできる
  • ex マイクロサービスの粒度
    • 単一の責任だけでは曖昧で無理
    • 分ける要因と統合する要因を考えるべきだと主張
    • ハードパーツの本に書いてあったやつだな
  • 名前つけるのが難しいから、名前がつく粒度まで分解しちゃう、みたいな話が出てびっくりしてる。理にかなっている気もするがパッと受け入れられてない
    • メッセージングの件
  • ベストプラクティスは、状況に対して何をやれば良い、という提案。ベストなので判断の余地はない
  • 組織の目的は考える必要がある
    • 絶対壊れちゃいけない v.s. 要望からリリースまでの時間の短さ
  • 設計を繰り返すために定性分析して、結果的に定量分析しよう
  • 過去のベスプラが今野アンチパターンになるのはエコシステムがコンスタントに変わるから
  • それに追従するためにも分析を続けるのがよかろうということかな

感想: トレードオフとビジネス要求、をみて決めるのだなという気持ちと、無限に時間がかかるのでタイムボックスを決めてガッと決めることなのだろうと思った。それを何回も適宜行うイメージ。

saas: 業務のベスプラを提供するモデルテナント: 契約の提供を受ける単位のことコントロールプレーンとアプリケーションプレーンなるほど。コントロールプレーンはなるだけ作りたくないテナント、本当に必要なのか?は気になる。ここで主張されるテナントには何が含まれるのだったか。テナントの本存在するのか。

  • クライアントでブラウザを使わない、リアルタイムサーバがあるのがwebアプリとの違いっぽい
  • 専用ゲームサーバ: DGS, dedicated game serer
  • DBがやばかったのはspannerを使うことでなんとかなった

  • モブプロ

  • BDD

  • イベントソーシング

  • どんなコンポーネントがあって、どう連携するかを決める

  • vuca, ooda
  • 観察とか行動とかは具体的に何をするんだろう
  • マイケルポーター 競争優位
  • ask the speaker
    • 競合優位性でググろう、本を読もう
    • エンジニアがやっていくとスムーズそう
    • 増田さんの会社がワークショップを開催したり、本を出したりするかも

なんで全く新しく作らなかったのだろう

  • バンブーで1日かけて設計したとのことだが、どうやって決めた?意思決定プロセスが気になる。強い人?
    • 強い人が決めると決めてる。領域ごとに担当者がいる。これはknowledgeworkの意思決定プロセス(口頭でシュッと聞いただけなので、書いた内容は正確ではなさそう)
    • もちろんレビュー依頼などはする
    • それだと独裁になるのがいや。なのでこの会議で決めるとしている
    • そこまでに議題は共有されている。異論があれば準備しておく
    • 異論が出なければ決まる

scim: azureとかでユーザ作ったらsaasでもユーザ作るみたいなやつ

バッチとバックエンドはapi呼び出しで繋がってたのかな

IRでのシナリオ気になる。エンドポイントだけでなくシナリオを作ってるのかな

取り巻く環境の中で継続的な改善可能性をもつシステムを作る環境に合わせる話は大事変化を発見したときにちゃんとついていく。変化を捉えることは必要そう

  • 実現したいことをトッププライオリティにおく、ビジネスissueとしても重視する。それを実現する手段には拘らない。でもその分野についてのビギナーには手段が中心に見える。その目的が見えない。なんでその手段を取るかを理解するのは難しい
  • こうしたら良くなるの提案を頑張って説明する。自分の主張も大体間違ってると思ってドキュメントを事実ベースで論理的に書くと成功確率上がる。言語化して検証する。

  • いろんなところがconnect使ってる。layerx、knowledgework、flattが確か使っているとのことだった。
  • アーキテクチャの話を聞きにきたはずが意思決定の進め方とか社内での役割について質問していたし勉強になることが多かった。あとは共感できないか、もう知っていることが多かった

オフレコのつもりで話していた方もいるだろうからここには詳細書かない方が良さそうかな。知らない業種の話を聞けたり、一方的に存じ上げていた方のお悩みをお聞きしたのが印象的。また増田さんや他の登壇者の方に質問したり、そこから発展したお話し伺えて楽しかった。ドメインエキスパートどこにいるんだよ、いなくない…?みたいな話を質問した。他にも色々お話し聞けた。

増田さん、川中さんのお話が響いたし、発表後に質問に伺って教えていただいた知見が良かった。熱い気持ちになっている。そのほかのセッションではFlattセキュリティの内容が面白かった。ASM、そんなステップが中にあることを今まで全くイメージできてなくて、概要を知れたことが嬉しかった。 Webアプリケーションの構造を始めて学んだときみたいな気持ち。登壇者がラムダノートのWebブラウザセキュリティの本の著者だと聞いてなるほどな気持ち。

増田さんからはドメインモデリングと事業を進める話を学んだ。訳書である「ドメイン駆動設計をはじめよう」を読んで、今回の発表内容の結構な部分を腹落ちさせていたのだが、増田さんがどこをどういう形で支持しているかを知れたのが収穫。また、僕が抱えていた悩みとして「ドメインモデリングしたいが、ソフトウェアだけじゃなくてドメイン自体の設計も僕たちが結局やる必要がある。ではドメインをどう作っていくのが良いだろう」というのがあった。それを増田さんにぶつけてそれが真っ当な悩みっぽいと共感していただけた(と僕は思っている)ことと、それへの対処(競争優位を重視して作るとか、エンジニアから歩み寄ってディレクタとかと会話するとか)を引き出せたことが収穫。あと懇親会で色々お話し聞けて楽しかった。ここのお話しから収穫あったのはそうだけど、人柄を知れたのがでかい。

川中さんからはプロダクト開発における意思決定の進め方を学んだ。初期には対象範囲(バックエンドとかフロントエンドとか)を決めて強い人が決める、それに対して責任を持つ、範囲の境界の契約(APIスキーマとか)はちゃんと決めて厳格に運用する。まあ確かにシュシュっと決まりそうだし、なんとかする未来を描きやすそう。

その他の意思決定の仕方として、やはり強い人が提案をして決めにかかるやり方もあるそうだが、それだと独裁になっちゃうので最終決定を会議でするようにしてるとのこと。決める内容はあらかじめ共有しておいて、反論があれば会議までには用意する必要がある。会議で異論がなければ決まる。もちろんレビューを依頼することはある。

2024-11-25

  • それぞれの記事に「次の記事」と「前の記事」へのリンクをつける
    • 記事のレンダリングとは別にページの属性として前後の記事のURLかパスを持たせるように、テンプレートみたいにすると良い。計算フェーズを分ける

2024-11-20

  • proto2cliを実装する
    • やった
    • 名前を決める:connectはブラウザやgRPCと互換性のあるAPIを提供するのに必要なボイラープレートが必要なのを軽減してくれるやつ。
      • これはそれらにCLIをインターフェースとして加える。つまりローカルから、サーバを立てる事なく実行できるようにする。そういう立ち位置がいい。単にインターフェースを一個加えるだけ。実装はできるだけシェアしたい。
      • まずはconnectを採用するアプリケーションを一個用意して、それにCLIを入れる。ここで上手い入れ方を探る
      • 次にその入れる作業を自動化する。そのためのCLIがproto2cli
    • サブコマンドでサービス、位置引数でメソッド、フラグ引数(-d)でリクエストメッセージを受け取る。
      • サブコマンドと位置引数は最初は特に区別しなくていいか。 cmd <service> <method> -d <request message json> の形式で呼び出すだけ。
      • CLIへの入力はそのままサービス名、メソッド名、リクエストメッセージがそれぞれbyte列かstringのどちらかで得られる。それらをなんとかするのは一旦別のコンポーネントの役割にしよう
      • ここまでは普通にflagsパッケージとかを使うだけでいける
    • 次にリクエストメッセージのデコードを自動化する。
      • func unmarshalRPC(service, method, req string) (MessageInterface, error)
        • 対応する型のunmarshellerへのディスパッチとその呼び出しが責務
      • dispatchUnMarshelelr(service, method string) (func(byte[], MessageInterface) error, error)
        • ディスパッチだけでも良さそう
    • 次に、サービスの呼び出しを行う
      • connect サーバをclient経由で呼び出す
      • 単にサービスを呼び出す
        • インターセプタを通過できない、特にproto validateを通せない
      • インターセプタとサービスを合成する
        • できればhttpサーバの仕組みに乗っかりたい
        • でも無理がありそう、intercepter (unaryfunc) を受け入れてデコレートする感じにしそう

以下のようなprotoスキーマを定義する。

syntax = "proto3";

package nfurudono.sample.v1;

service SampleService {
  rpc Say(SayRequest) returns (SayResponse) {}
}

// SayRequest is a single-sentence request.
message SayRequest {
  string sentence = 1;
}

// SayResponse is a single-sentence response.
message SayResponse {
  string sentence = 1;
  bool dry_run = 2;
}

こんな定義があるときに

$ ./sample say --sentence "hello world" --dryrun
sentence: "I will say: hello world"

みたいなやりとりを定義するためのCLIテンプレート生成ツールを作る。あくまでテンプレートなので、生成ツールではインターフェースとかグルーコードだけ提供して、ユーザは以下のようなコードを書くことになる。

  • connectとかでサービスとサーバの起動を定義してmainからいい感じに呼ぶようにすると、gRPCサーバがたつのに対して、
  • CLIテンプレート作成ツールでサービスとCLIコマンドの呼び出しを定義してmainからいい感じに呼ぶようにすると、CLIから実行できる

package service

import (
	"fmt"
	
  sample "github.com/nfurudono/gen/go/sample"
)

type SampleImpl struct {}
// sample.SampleServiceはprotocとかが生成するようなinterface。gRPCとかconnectとかで使われているようなやつ。
var _ sample.SampleService = &NewSampleImpl()

func NewSampleImpl() { return SampleImple{} }

func (* SampleImpl) Say(ctx *context.Context, req *connect.Request[samplev1.SayRequest]) (*connect.Response[samplev1.Response], error) {
	s := req.GetSentence()
	d := req.GetDryRun()
	if d {
		return fmt.Sprintf("I will say: %s", s), nil
	}
	return fmt.Sprintf("%s!!", s), nil
}

package main

import (
	slog
	
	tool "github.com/naoyafurudono/good-tool"
	"github.com/naoyafurudono/sample-cli/service"
)

func main() {
	s := service.NewSampleImpl()
	// NewCLI()の結果(CLI)はサービスを登録される。
	// サービスを保持するCLIはサービスが契約するrpc(名前、入力、出力)を知っている。
	// これらはprotoの仕組みで生成される。protovalidateなどのプラグインもそのレイヤで対応できるはず。
	cli := tool.NewCLI().AddService(s)  // このあたりのインターフェースはもうちょい考えても良いかも?
	// Runがコマンドライン引数を読んで以下を半ドアリングする
	//   - 呼び出すrpcの判定(ルーティング)、サブコマンドの名前が対応する
	//   - rpcに渡す入力messageのデコード、サブコマンドへのフラグ引数が対応する
	//   - rpcの出力メッセージやエラー内容の出力、コマンドの標準出力、標準エラー出力、コマンドのステータスコードの出しわけが対応する
	if err := cli.Run(); err != nil {
		slog.Fatalf("unexpected input: %w", err)  // 予期しないサブコマンドが来たらエラーを返すのもまた一興かな。
	}
}

便利じゃない?

2024-11-13

fzfで表示される選択肢と選択した結果得られる値を分けられるようにしたいので作った。 yamlでkey-valueペアのリストを保持しておいて、そのキーの選択をfzfで行い、得られる値はvalueである、みたいな感じ。

#!/bin/bash

# ヘルプメッセージ
function print_help {
    echo "Usage: $0 <yaml_file>"
    echo
    echo "This script allows you to select a key from a YAML file using fzf, and outputs the corresponding value."
    echo
    echo "Options:"
    echo "  -h    Show this help message and exit"
    echo
    echo "Sample YAML format:"
    echo "  key1: value1"
    echo "  key2: value2"
    echo "  key3: value3"
}

# -hオプションのチェック
if [ "$1" == "-h" ]; then
    print_help
    exit 0
fi

# 引数チェック
if [ -z "$1" ]; then
    echo "Error: No YAML file specified." >&2
    print_help
    exit 1
fi

# 引数からYAMLファイルのパスを取得
YAML_FILE="$1"

# YAMLファイルの存在チェック
if [ ! -f "$YAML_FILE" ]; then
    echo "Error: File '$YAML_FILE' not found." >&2
    exit 1
fi

# キーをfzfで選択
selected_key=$(yq e 'keys | .[]' "$YAML_FILE" | fzf)

# キーが選択されていない場合
if [ -z "$selected_key" ]; then
    echo "No key selected." >&2
    exit 1
fi

# 選択されたキーに対応する値を取得
selected_value=$(yq e ".${selected_key}" "$YAML_FILE")

# 値を標準出力に表示
echo "$selected_value"
exit 0

上のコマンドを fzf-keyvalue-select という名前でパスを通しておく。その上で以下のような関数を登録しておくと便利。

function notion
    set url (fzf-keyvalue-select ~/.local/fish/notion.yaml)
    and open $url
end

2024-10-16

  • トピックをセクションのタイトル (hN要素) で宣言して、それを集約したページを勝手に生成するようにしたい。
    • about:<TOPIC_NAME> <TEXT> という名前のタイトルをヘッダにつけたら、/topic/<TOPIC_NAME> というページを生成して、  そこに <TEXT> - <DATE> みたいな名前のセクションを埋め込みたい。元記事へのパーマリンクも添えておくと良さそう。
    • 読書記録に使えそう
    • その他にも普通のブログではタグを記事につけるようなノリで使うのも可能。記事の単位だとタグによる分類は不便に思うのだけど、セクションくらいの粒度ならつけるときも読む時もちょうど良いだろうと思う

エンジニアリングの中ではプログラミングは割と得意なのかもしれないとここ1ヶ月くらいでなんとなく思うようになった。こういうプログラムの構成の方が良くない?みたいなことを理由込みでそれなりに説明・提案できることが周囲より多そうな気がしてきたので。

失敗できないように作るとか(設計、型の宣言)、失敗には早く気がつけるようにするとか(リント、コントラクト、バリデーション)、プログラムのあるべき振る舞いをテストするとかは似たような話に思う。先に挙げたものほどフィードバックが早くて良い。リントとかテストはそのプログラムそのものの性質ではなくて外からどうこうする点が特殊。テストではこういうふうに使うと確かにこんな感じに振る舞う、みたいな確認をする。リントではこういう感じの使い方をするとやばいからやめておいて欲しい、と怒る(この観点では型と一緒)。リンターのライフサイクルは対象のソフトウェアと一緒とは限らないのが辛いところなのかな。型システムは言語の一部だし、設計はプログラムの一部。でもリンターは一部とは限らない。一部になっている奴はだいぶ使い勝手が良いが、そうでないやつはいろんな人が勝手気ままに思想を入れるし、それらの互換性は比較的真面目には考えられないだろうから品質が悪くなりそう。

そういうわけでリンター難しそう。

2024-10-10

  • protobufとかsqlcでファイル生成をするツールを使ってチーム開発をしているとすごくコンフリクトして辛い。生成するファイルを分割して、例えばrpcとかmessage単位にファイル(パッケージではない!)を分ければgitのコンフリクトは避けられる。パッケージも一緒なので振る舞いには影響しない。

2024-10-06

LLMはコンパイラとかみたいに説明とか分析を出力してくれるものではあるけど、 LLMはコンパイラよりも人間に近いものだと思っている。コンパイラみたいな決定的な出力をするツールに対して良い入力を与えてその出力をそのまま共有することには価値がたくさんあるけれど、 LLMから得られた出力をそのまま「LLMに聞いたらこう返してくれました!」っていうのは(少なくとも現代使えるLLMのレベルでは)意味が薄いと感じる。

人間に対して質問して、その回答をそのまま人に共有することにも、場合によって価値がたくさんあったり薄かったり感じることがそれぞれある。質問を回答してくれる人間に対して信頼というか専門家としての信頼というかがあったら、そのまま回答を知りたいと思うが、その辺のただの人とか単に知識がたくさんあるだけな人だと、 (アンケート回答のデータとかなら別だけど)意見や情報としては価値を見出しにくい。そんな感じに、ぼくはLLMを専門家だとはまだ思えていない。単に知識がたくさんあってそれっぽい文章を生成するだけの(論理的思考の欠けた)出力をするやつだと思う。

とはいえ知識や経験がたくさんあれば結構な量の論理的思考は不要だろうことは段々わかってきた。なんのために考え事が必要なんだろうね。そして論理的思考とは何なのだろう。

今週は疲れた。先週の金曜から毎日飲み会だとか人と会ったりだとかのイベントがあった。それぞれは楽しいのだけど全てに参加していると大変。昨日はずっと寝ていたし、今日は家事をしていた。本を読む気力もない。体としては寝ても良さそうなのだが頭は何かをしたがっているので文章を書いている。本を読みたい気持ちもあるが、落ち着いて考え事をしたい気持ちもある。今その本を本当に読みたいのだったか、とか。

わかったつもり 読解力がつかない本当の原因 (光文社新書) に本屋で出会って読んでいるのだが良い。わかるとか理解する、みたいなことは一体何なのかは高校生の頃からのぼくのテーマの一つなのだが、それを一段深めてくれている。

ぼくの中での「理解する」とは、説明をつけることとか腹落ちしていることであった。論理とかは客観的なアレとして社会的に認められていたり、自然科学は実際問題役に立っているので市民権を得ているが、そんなことは「理解している」とは関係ないと思っている。理解しているか否かは主観的な問題で、腹に落ちた感じがするなら自分はそれを理解していると思うし、自分が同意できる説明を他者がするなら他者はそれを理解しているように感じる。そういうものだと思っていたし、今も思っている。

この本の説明ではぼくの解釈と矛盾しない中で理解の程度を論じているように思う。文脈とそれに対する解釈を持っている人間は、文脈を新たに獲得し明らかにすることで対象の解釈をより鮮明にする、みたいな主張だと今のぼくは大体思っているはず。鮮明にするというか、よりわかるというか。

これまでのぼくの理解への価値観には抽象度の違いがなかった。抽象解釈をするときにどれだけfineに解釈するかの違いが認識する文脈の違いに依存することをこの本に解らさられた。

この前ご近所さんとお話した影響で今日は八百屋に行ってきた。はじめて行くタイプの八百屋で、なんとカゴとレジは存在しなくて、床に陳列されている野菜を見ながら店員さんに口頭で欲しい野菜をクエリするタイプの買い方だった。ちなみに野菜の品質はそんなに良くなかったので次は他のところかなと思っている。安くはあった。

結局人は自分と近しい考えを読んでそれを楽しいと思うのだな、みたいなことを恩師が言っていたのを思い出した。ぼくもそう思う。そういう答え合わせみたいな読書は楽しい。

読書に限らずおしゃべりとかでもなんやかんや同調とか、似たような哲学のもとでの「議論」みたいなことをするときが楽しそう。「あいつはやばいから!」と嬉しそうに友達を紹介する人は、大体その友達と大差ないとかだとか。議論をするときに背景に共通点を見出して群れるのもそういうことだと思う。良し悪しは知らない。

named-letです。

2024-09-18

日記からtodo一覧を抽出して専用ページにtodoアイテムとその文脈を列挙する機能を実装した。この手の機能はtodoに限らず文章で考えや記録をつける人を幸せにするだろう。

例えば、読書メモをする場合、ぼくはそれを日記に書きたい。でもある本についての読書メモはまとめてみたい気持ちもある。そんなときに、その本に関する記述をまとめてみる機能があると幸せなはずだ。あくまでメモなので、その内容はその日の自分に依存する主張を持つ。なので、日記としての文脈は必要なはず。日記はぼくの考えたこととか記録を時系列でまとめたものであって、ぼくにまつわるいろんなものは時系列に沿って進んでいく。考えて、書くのも時間的な変化とともに進めていくものだし。なので書き出すフォーマットは日記が良い。楽だし、情報が失われにくそうなので。

その反面、読み方によっては他のアスペクトで抽出したりまとめたいこともある。それは日記を切りはりしたものとしてある程度表現できるはず。普通にぼくたちがあるアスペクトでまとまった記述をするときには、時間をかけて一つの側面から解釈しやすいようにする。文書を作成するときは反復して改善するものだし、推敲をするものでもある。では推敲をしない文書作成は、あるテーマについて日記を切り貼りしたものなのではないだろうか。

その切りはりをやるツールとしてtodo一覧の抽出みたいな機能を使えると思う。

セクションの単位でアスペクトを宣言できると良いだろうと思っている。あるいはAIでアスペクトを後付けしてもいいかもしれない。でも、どちらかというと、ぼくは普段の日記を書くときに後から見返す解釈を意識してかけたら楽しいだろうと思う。なのでアスペクトは明示的に日記を書く人が付けられるといいと思う。ふとアスペクトを思いついて、これまでの自分はどう思ってたんだっけと気になることもある。そのときには確かにAIに全部みていい感じにタグ付けしてほしい。

あと、今はunifiedを使って実装しているけど、pandocに移行しても楽しそう。型が辛いと思っているので。pandocはhaskell製なので型が弱くて文句を言いたくなることはないはず。

2024-09-16

  • 掃除
    • ルンバを起動したのでok
  • 外出
    • 電車乗るくらいの外出をする。秋物出たかな。あるいは外で使うと幸せになれるグッツを買うか。
    • ランニングパンツと靴下を買う。帰省でランニングのズボンを置いてきたのと、靴下が大体ボロボロになってきたので。
    • 靴下は買った。ランニングパンツはまあいっかと思って買わず。そのほかに秋に向けて服を見たけどピンと来なかったので特に買わずだった。
  • 本読む。k8sのあれ。あとは認証の技術気になるので学ぶ。認可も気になる。
  • todoをリストアップする拡張の実装
  • todoの拡張、出先でチェック入れたくなりそうなので、githubでの編集へのリンクをつけたい
    • やっぱりいいや。出先ではのんびりしよう。todoのことなんて忘れればいい。

https://diary.nfurudono.com/todos/に実装した。これでもう過去のtodoを忘れない。収集とレンダリングの両方が必要でだるかった。特にレンダリングはunifiedのアーキテクチャを理解してなくて手間取った。今の実装がunifiedのアーキテクチャに沿っているか自信がない。

本棚を作って設置したところ、そろそろキャパシティが限界だと気がついた。本棚を増やすためには引越しが必要。そろそろ減らしてもいい本も増えてきたので、 2年周期の引越しで問題ないとは思うが。今で3/4年か…、今年のうちに西側の探索をしたいな。今度友達とどこに行くか決めてないので、そっちの方に雑に行ってみて案内してもらおう。向こうが詳しいかは知らないけど。

寝たり本を読んだり景色をみたり、考え事をしたりする環境として電車で過ごすのが好き。年末は北国に電車に乗りに行きたいな。高校生の頃に一週間電車に乗りっぱなしの旅行をしたけど、あんな感じのことをまたやりたい。それでいうとシベリア鉄道は憧れる。

景色が変わるのがいいし、椅子しかないのも良い。なので新幹線みたいな机があるのはそれほど好きじゃない。横に細いサイドテーブルみたいなのはok。ものを置けるけどそこで何かやる感じではないのがいい。集中できるし、パッと休憩しようと思ったら外を見ればいい。なので電車に乗るのは日中がいい。夜は外が見えないので興醒めする。

家にいても景色が変わらなくてつまらない。外に出るのも良いが、それだと本読んだりできない。電車の中は家と同様に自分が暇なのに快適で、移動しているのがいい。

金曜日の昼過ぎに三連休だということを知った。なんと来週も三連休だということだった。この三連休は本棚を作り、あとは家でまったりした。こういうのもあり。

2024-08-15

日記をnextjsでビルドして、cloudflare pagesにデプロイするようにした。cnameの設定が効くようになれば、https://diary.nfurudono.comから見えるようになるはず。

cloudflareのアカウントを初めて作って設定したが、体験よかった。デプロイとか周りの開発のためにCLIツールやそれのgithub actionsバインディングが提供されていて、サクッとデプロイできた。記念すべき初デプロイの成功をメモしておくhttps://github.com/naoyafurudono/naoyafurudono.github.io/actions/runs/10399555684/job/28798614059

Hugoの設定をたくさん書いていても楽しくないのでNext.jsでなんでもやってみよう、というモチベーション。unifiedがいい感じで楽しいので動くところまで持って来れた。

ソースコードはhttps://github.com/naoyafurudono/naoyafurudono.github.io/tree/main/tools/ttにある。

2024-08-03

ソフトウェアを設計するときにはどこを変えやすくしたいか(どんな変更をしやすくしたいか)を把握したい。 Expression probremは必ずしも解決しなくてよいと思っていて、変更に必要な気合がどれくらいかを把握したうえでそれを許容できるかが論点だと思う。

もちろん使う気合が小さいのに越したことはないのだが、コード読み書きするのはみんな好きだろうし、嫌いなひとは割とAIに任せられる世の中なのだから、小手先のテクニックでなんでもできる設計とかにしておくうまみはあまりないと思う。

会社ではmacbook proを使っていて、家ではmacbook airを使っている。使っているソフトウェアとか設定は大体同じにできていて便利ではあるのだけど、今日は手ぐせで会社でよく触っているリポジトリにcdしようとして失敗するのを何回もやってしまった。 lsのノリでそのディレクトリにcdすることに辛さを感じる。

  • 飲み会の場所を抑える
    • ビールをたくさん飲めるところでそう遠くないところがいい
  • 健康料理
    • 野菜を食べたいです
  • 外出
    • 15:30を回ったが、まだ外に出ていない。お日様が欲しい
  • 洗濯
    • あとは干すだけ
  • 運動
  • ルータを吊るす
    • そういえば家の壁に釘打っても怒られなさそうな板が壁に付いているので、そこにルータをなんとかつけたい

今日は小学校4年生の頃に転校してきた友達の誕生日。ブルーアイズホワイトドラゴンをくれた、寡黙なやつだった。元気だといいな。

2024-05-12

社内外のrubyistの人たちとたくさん喋れた。明日ruby.wasmの話を聞けるのが楽しみ。質問するぞ!!1

2024-05-12

チャットを読み書きするのが大変なのではなく、それらを始めるのが大変という話。ラインが嫌いとかでは全然ないし、会話が嫌いなわけでもない。

僕はラインを手紙くらいの速度でしか見たくないと思うような付き合い方をしてしまっている。議論とかすり合わせをガッとする文脈になれば集中して通知を気にするようにはなれるのだけど、そうではなくて雑談とか、会話ではなく外部の処理に時間のかかるイベントの後処理とかをする文脈だとなかなか通知を見れないというか、そこに意識と返信の気合を割けない。

そもそもラインとか会話に限らず、返信とかリアクションを外部からの割り込み契機で行うのに辛さを感じる気がしている。例えば宿題出されてそれをやるのがしんどいのと同じイメージ。自分からこの辺の分野・技術を学んでみようと思ってやるのは何も辛くないし、むしろ他の辛さを乗り越えてでもやろうと思うが、それが外部から要求されると辛くなる。

おそらく原因は人から指図されることではなく、自分がそれをやる体制に入っていない状態で、やる義務を感じてもやる気にならないことにあると思う。宿題はやり始めて意義を感じたり調子が出たりすることでやるのが辛くなくなる。それが2,3週間かかるものであったとしても、体制に入れると辛くなくなる。

ラインの件も同じだと思っていて、普段僕は会話や事務処理をするモードではない。そのタイミングで人からその依頼が飛んでくると、会話に返事する義務を感じはするものの、処理するやる気は出てこない。

雑談はしてると楽しいし、事務処理も乗ってくると楽しいものではあるのだが、それらを始めるのに時間がかかるし、大変なのだ。これは子供の頃から変わらない(なんなら全人類そういうものなのではないだろうか)ので受け入れて自分の問題として迂回するなり利用するなりしていこう。

ちなみに仕事でSlack使うのは全然苦ではない。仕事するためにSlackでコミュニケーション取るのは有効だと思っているし、始業はすでに始めるインセンティブを持てているので苦なくSlackコミュニケーションは取れる。プログラミング集中してるときとかは通知に気がついてもちょっと返信したくないときがあるにはあるが、それくらい。基本的に仕事するときにはリアクションを優先するモードになっているのだと思う。コードレビューと同じ意識を持っていて、普段のあれとは異なる。そして、仕事する時間は決めていて休日にSlackの通知は切っているがそれが他の人に対しても共通の認識になっているのは良い。

ラインでも時間決めてプロフィールに書くとかするか?(あまり書きたくないけど)。休日の作業しない時間とかになりそうではある。ちなみに今がほとんどそんな感じの運用になっている。

感謝を伝えるのが苦手で、ご飯奢ってもらったりプレゼントをもらったときとかどういう顔をすれば良いかわからなくなる。

ラインでそれをやらないといけない状況ではなかなかヤバい。気がつくとなぜだかわからないが(ライン見ないからなのだが)伝えたい感謝が2,3個溜まり、ついでに謝りたいことも少しできてたりする。早めに、こまめに連絡するのが良いのだろうな。

感謝を伝えるのは単に技術の問題な気がするのでさっさと習得しよう。特に複数溜まった感謝の意を伝える能力が欲しい。

会話やチャットに文脈があるように、僕が日々過ごすことにも文脈というかモードというかがあるみたいだ。仕事、雑務、おしゃべり、勉強、家事、読書(小説)、読書(技術書)、外出、網羅的でも排他的でもないが、それぞれに飽きて数ヶ月やらなくなることはないが、数週間くらいならおろそかになるものが出てくる。

排他的ではない例として、仕事な雰囲気になっているときに雑務、おしゃべり、プログラミングは全然する。ただし、雑務やおしゃべりはプログラミングに集中しているときはできないし器用に行き来も無理。

このセクションは、だからどうというわけではないのだけど走っているときにそんなことを思ったのでメモ。

2024-03-20

Webアプリケーションのテストをどう実施したものかと最近考えることが多い。 Webアプリは雰囲気で変更したいはずで(ソフトウェアって大体そう?)、またテストは長持ちしてほしいと思う。

テストではなんらかの仮定のもとで実装がある条件を満たすことを検証する。その仮定を上手に置くことがテスト戦略を決める人の腕の見せどころだろう。

例えば関数の単体テストをする場合は、そこに渡す実引数を仮定して、その関数の出力が意図した通りになることを検証するし、モックを使うならそのモック対象の振る舞いを仮定することになる。 e2eではユーザの操作を仮定するのだろう。

いろんな仮定の置き方とその結果実現できる検証内容がある気がしていて、安定した仮定(覆るとテストを直さないといけない)を選びつつ、そこがクリアできれば安心と思える検証内容を取ることがテスト戦略の設計で目指すことなのだと朝の東横線で思ったのだった。

で、そういうお得さを出せるように実装するのも大事なんだろうなと思っています。

2024-02-26

人間失格の主人公はそんな失格っていうほどやばい人には思えないというのはあるあるだと思っていて、そういう感想を抱いたことで自分を許せるようになったと思う。そういう人も結構いるんだろうと思う。

太宰修がまともじゃない人間について描写したおかげで、それを読んだぼくみたいな他人がもっと救いのある解釈を手に入れられたのだ。当の太宰修は自殺してしまった(理由をぼくは知らないけど)が、彼の残した解釈のおかげでぼくはそれなりに幸せに生きているのでなかなか感謝している。昔は太宰修は愚かだと思ったけど、たたきを作った人は偉いし、その恩恵を自分は受けているのだった。

久しぶりにUbuntuでブログを書いのだけど、入力がキビキビしていて気持ちがいい。最近は会社や私物のmacを使っていた。何が違うんだろう。

2024-02-12

管理画面の設計について考えてみる。 Webアプリケーションでもろもろを設定する際のUI設計を考えている。

設定の初期化時や更新時でフローが異なるはずだ。

初期化のタイミングでは、氏名やメールアドレスの設定・認証や、オプショナルな事項(決済情報とか追加の契約事項とか)の設定が挟まり、最後に確認してよければコミット、ダメなら修正する。

更新では最初の設定で気に食わなかったところを修正したり、追加の設定項目をいじったりするだろう。

それぞれのタイミングで何を設定させるかや、どれだけサクサク入力できるかによってユーザの体験が左右されそう。例えば初期では認証情報だけをコミットして、その他の情報は更新で登録する手もあれば、ファストバスを登録時に持ってきてしまって、8割のユーザが最短で使用を開始できるようにするパターンもあるだろう。

ユーザが行うそれぞれのフローはアプリケーションというかシステムにどのような影響を与えるだろうか。というよりも、ユーザがそれぞれのフローの結果及ぼせる作用をどのようにデザインすると良いだろうか。

この作用をデザインするにあたって、アプリケーションで表現するモデルがどんなであるかを明らかにしておくと良いはずで、そのモデルに対する作用の一つの実現方法としてユーザが操作するフローがある、と思えそう。

ユーザによる操作じゃない作用としては、決済が行われたとか権限が時間経過で失効したみたいな作用がありそう。

データにもいろいろありそう。モデルを表現するためのデータと、作用を実現するために一時的に保持するデータは異なる。

例えばユーザが登録されているか登録されていないかしかないモデルでは、メール認証中にはユーザが登録されていないけど、メール認証のためのトークンとかはサーバにデータとして持っていないといけない。

もちろん、そういう一時的な状態もモデルに含めるてもあるはず。RDBで実装する場合delete操作が激しくなりそうだけど。セッションキーもそうかな。セッションキーはモデルを表すデータに持つことは少なさそう。モデルの表現には含まれないログイン状態として扱われるイメージがある。揮発性のあるデータストアで保持しそう。

全部モデル化してしまうのが教科書的なんだろうな。汚いとわかるならあえて汚いことをやる必要はないだろう。

モデルではないけど、DBMSの都合について説明する記事があったので貼っとくセッションの保存などにRDBMSよりもRedisやmemcachedのような、NoSQLが向いているのは何故ですか?他にNoSQLの用途として向いている(いない)処理にはどのようなものがありますか? (Quora)

TTLが欲しいよね、という感じか。確かにそもそもセッションキーにはTTLが欲しい気がするし、モデルを考える上でTTLはあまり意識したくない気もする(頭弾けそう)。

反面、TTLもうまく表現したら面白そうな気もするし、割と欠かせないんじゃないかという気もする。そのときに普段のモデルを表現するのに使うDBとTTLを複雑さを吸い取らせるために導入したDBが異なると不必要な複雑さが生じたりするかもなと思った。

今日たくさん寝て軽くランニングしたらなかなか幸せな時間を過ごせた。ただいまはそのクオリティが持続していない。夕食の目処が立っていないこととか部屋がちょっと寒いこと、姿勢が微妙なことが原因だろう。軽く座って作業する空間はやはり欲しい。机にがっつり向かうか後傾でノートパソコンを叩くか、床で作業するかの三択でQOLっぽい作業時間を過ごす空間がない。コメダで作業する姿勢を家でも取れるようにしたいイメージ。やはりベンチソファだと思うんだよな。僕のユースケースだとソファだけでなく机も欲しいことに気がついたのが今週末の成果。

あとは壁が寂しいことにも気がついた。なんか怖くないすっきりとした絵とか飾ればいいんだろうな。めんどいので誰かに決めてほしい。ああいうのってどこで売ってるんでしょうね。

2023-11-07

ドキュメントを読むときに参考文献が適切に使われていないと辛い。ドキュメントには2種類あると思っている。

  1. 水先案内
  2. 主張をするドキュメント

主張をするタイプのドキュメントで参照先を読まないと主張を理解できない場合は辛い、というのが今回の主張。

水先案内のドキュメントとしては、wikipediaの水先案内ページやgoogle検索の結果ページが該当する。水先案内のドキュメント自体は主張をしておらず、その水先案内ページに辿り着いた読者が適切なドキュメントにたどり着くためのサポートをする役割を持つ。

主張をするドキュメントとしては、この記事やAPIの仕様を説明するページなどが該当する。参考文献とか例を上げる目的で引用とか他のドキュメントへの参照を持つことはあるけれでも、そのドキュメントを全く読まないでも主張を理解できることが期待される。もしも読まないと理解できないのであれば、その文章は主張をできていないんじゃないかと思う。サーベイ論文は主張をするドキュメントだと思う。参照を探す目的で使うこともできるけど、対象をサーベイしてこういう歴史があるとか界隈はこういう感じになっているよねといった主張をすることが目的なはずなので。論文のアーカイブページは水先案内。

ドキュメントはそれ自体で完結していて欲しいので、参照先に主張の内容が書かれているはドキュメントとして不十分で読むのが辛い。内容ではなく根拠を委譲するのは良いし、よくある引用のスタイルだと思う。

2023-09-13

今家のトイレで気がついてんですが、冷蔵庫と自分の体にはどんな落書きしても人に迷惑かけないので落書きし放題です!! 何書こうかな…。

人生楽しくなってきた。今度人生つらそうな人を見たらこれを教えてあげつつ、鏡のある場所を教えつつ、マッキーをプレゼントしよう。

ちょっと前に買ったbowmoreが美味しい。味の表現はさておき美味しいからそれでいいんです。テイスティンググラスでストレートで飲んでいます。 aged 12 yearsと書いてあります。

350ml瓶を買ったんですが、このサイズの便が一番かっこいいです。他のサイズでかっこいいのはフロムザバレルくらい?

350のbowmoreはリュックの横に挿してもいいかなというくらいかっこいい。

会社ではあだ名で呼ぶ文化がある。それはなかなか楽しくて好きなんだけど、人生のほとんどを苗字呼びの文化で過ごしてきて、会社の飲み会で苗字よびをしてもらって、「ああ、こんな感じだったな」と昔の感覚を思い出した。新しく上の人から苗字呼びされる経験は僕にとって深いところに刻まれた体験なのかもしれない。

ホッピー師匠とも知り合えたことだし、今日の飲み会は僕にとっていいものだった。明日は走って帰るか。判断は夜にするとして、ランニングシューズを履いて、ジャージを持って出勤する。

まふまふの夢花火を久しぶりに聴いている。中学生に頃に友達にまふまふのCDを貸してもらって夢花火をしり、高校までめざましは夢花火だった。懐かしい思い出。

去年の暮れに会社の同僚がまふまふファンだと聞きちょっとテンションが上がったことを思い出した。今はまふまふの他にもdazbeeやado、co shu nieとかのアーティストが好き。オタクって感じがする。

オタクっぽくない歌手っているかと思うと、どのアーティストもそのアーティストが好きというと途端にオタクぽくなる気がするので気にすることではなさそう。 AKBもSMAPもheysayjumpも何もかも、アーティストが好きって言ったらおタックぽい気がする。

オタクっぽさを排除して「この曲が好き」みたいなことを表明しようと思うと、自身の音楽性に芯があるか流行りに乗っていくミーハーみたいになりそう。

そろそろ世間体について考えるのに疲れてきた。このくらいにしよう。僕がコモンセンスとして取れている自信を持っているのは、新劇場版のエヴァの最後のやつで「よかったねぇ」と思えたことです。ATフィールドは全ての人の間にあると思っているタイプの人間です。よろしくお願いします。

オフィスカジュアルっていうのやめません? 曖昧で、インターフェースで要求しているような感じがしつつ、実装する側にはその要件が伝わらない。コミュニケーションのための符号としてあまり良く機能していないように見える。

  • ジャケット
  • シャツ
  • パンツ

以上の四つについての要求を書いて欲しい気持ちが芽生えた。これらが指定されない限りは、どれだけフォーマルに寄っても、喪服まで行かない限りは文句言えないと思うし、喪服まで行かなくても服を着てくる側に対して不親切だろう。

ブログを分割したい

このブログは日記も開発っぽいことも両方書いてある。これらを別のサイトに分けようと考えている。

  • 開発の記事が日記に埋もれるのが嫌だから
  • 今の環境だと開発の記事を書きにくい・表現しにくいから
    • コードや数式を書きにくい・表示が微妙など
    • madoko使いたい

そのための準備としてnetlifyを試しに使ってみた。このブログのリポジトリを登録したら、特に細かい設定をしないでもシュッとデプロイできてしまった。すごい。DNSとかSSLとかの設定を試していく。

ところでデプロイの設定は何もわからないのでチュートリアルが必要。madoko使うなら設定ちゃんとしないとだろうし。

タスク分解と見積もり

見積もりとかについて真面目に考えてみる。

仕事をするときに、頑張ります!と意気込んで、目標を分解しひとつひとつこなしていくことはある程度できるし、途中で分解したタスクが違った方を向いていることに気がついて、自分がやることを軌道修正することもできる。

全部ではないけれど、ある程度のことは十分に時間があれば達成できるんじゃないかと思う。特に目標を具体的に描けていればできることは多い(できないことをなかなか目標として想像できないとか、そもそもできないことがある、みたいな話はそれはそうだけど一旦置いておく)。

仕事とかチームで動くときとかでは、歩みを揃えられることが大事なわけで、自分の好みで十分な時間を消費して良いわけではない。仕事では、目標に、達成する事項だけでなく期限がついてくる。目標を達成できそうかを判断するには、期限と見積もりを照らし合わせれば良い。

目標は期限と達成する事項のペアだと思うことにして、達成する事項のことはタスクと呼ぶことにしよう。つまり、目標はタスクと期限のペア。今まではタスクを分解して一個ずつクリアしていけば良かったが、仕事では目標を分割して、タスクをクリアする中で期限も一緒に守らないといけない。次元が増えるのだから難しくなるのは当たり前だ。

タスクの分解は、タスクをよく観察して論理的に推論すれば割と上手くいく。それに対して期限を含めてうまく目標を細分化するには、つまり見積もりをするには、自分の能力や環境要因、タスクの達成の確実性などを含めて考慮しないと考え切ることはできない。

見積もりは曖昧さを伴ったものになるはず。そこが難しいのかな。また、タスクを分解して軌道修正をするとタスクはそれで洗練される一方で、期限の方は純粋に遅れが生じるのも難しい。時間は巻き戻らないのだ。

見積もりを安定させるには、このように生じる遅れの量を最小化すれば良い。そのためには目標の分解を小さくして、細かい粒度で軌道修正すれば安定するはず。あまり細かく分解しないでガッと取り組みうまくいけば最速だし、細かく分解して検討を繰り返して良さそう良さそうと確認をたくさんするのは時間がかかる。それでも確認することを込みで見積もることはできるので、安定性の面ではやはり有利に働くだろう。この辺りは最急降下法とかで、一回のイテレーションでどのくらい進むのが良いか、みたいな話と似ている。

なんにせよ、今の僕は安定した見積もりをできていないので学習の意味を込めて、細かすぎるくらいのタスクの分解をするのが良いのだろうなと思った。

自分の性格と合うだろうか。

先ほどの段落で、一発でガッと仕事して上手くいけばそれが最速、みたいなことを言った。これが実際にありうるのは個人で仕事をしているときであって、チームで仕事をするときには普通以心伝心というわけにはいかず、解釈違いやすり合わせ、議論に会話が必要だろうし、それができるのがチームの強みのはず。

これをこまめに行うことは、多くのチームにとって課題だろうし、僕がチームに参加するときに度々足りていないなと思うところでもある。

タスクの分解を細かくすることでコミュニケーションの機会を増やせるだろうから、チームでの仕事には細かいタスク分解がプラスに働きやすそう。

dotfilesのセットアップスクリプトを書いた

dotfilesをGitHubで管理しているのだが、今までは設定ファイルの管理だけで、インストールは手動で行なっていた。設定ファイルを使いまわせるだけでだいぶ便利なんだけど、コンテナ環境の中で作業したくなると、手動インストールに耐えられなくなる。そこで重い腰を上げてセットアップを自動化した。

git のインストールと以下の実行でok。 nvimとかfishとかcargoとかが入る。

git clone https://github.com/naoyafurudono/dotfiles.git
bash dotfiles/setup.sh

test

arm環境かつubuntuだけでしか動かしていないが、dockerコンテナでセットアップスクリプトを動かして、正常に終了するかを確認するテストを書いた。

この手のセットアップスクリプトのテストって、世の中ではどのようにテストしているんだろう。以下の難しさがテストを大変にしている気がする。

  • 環境依存な部分をうまく吸収する必要があること
  • インストール失敗の判定が難しいこと

2023-07-01

envsubstを使うと標準入力の環境変数の参照っぽいところに環境変数の値を埋め込んだテキストを吐ける。 readmeにコマンドのヘルプメッセージを載せたいときに便利。例: https://github.com/naoyafurudono/tools/tree/main/cl

gitで管理しているファイルのパスが得られる。 git grepみたいに管理対象だけに興味があるときに便利そう。 fzfとの相性が良さげ。

2023-05-04

  • 昨日スクワットしてからランニングしたら、今日トレランに行った翌日みたいな感覚になっている。手軽に足の疲労感を感じられておとく。
  • この間オンライン飲み会をしたときに秋吉台ロゲに参加することを決めてしまった。 5/21に5時間走る予定。競技エリアが「秋吉台山焼きの実施範囲」とされていて絶対楽しい。 5時間走って新幹線に飛び乗り、翌日仕事できる体力をつけないといけない。まずはたくさん走ることに慣れよう。5/6の午前中にたくさん走ることにする。ロゲイン的な走り方をしたい。平野ではないけど山でもないところをのっぺり走り続けるようなスタイルをイメージ。

2023-04-28

今日は意味論の直感が少し生えたので機嫌がいい。寝て起きたらもう少しまじめに考えよう。

完全に忘れていた。一回捨てた継続渡しスタイルで考えるのがやはり良いだろうという直感のもとでの考えだった。細かいことは忘れてしまったが、少し考えれば再現できる程度だったと思う。継続フレームを生むときと、式を評価するタイミングを明示的にわけるとか、反対にそういうくくりで共通化することでこれまで見えていなかったアスペクトが表面化していい感じになりそう、みたいな直感だった気がする。

2023-04-27

人と語るわけでもなければ、熱狂的に推すわけでもないのに、僕はなにのためにアニメを見たり、小説を読んだり、音楽を聞いたりするのだろうか。アニメはほぼ毎日みるし、小説は人並み以上に読むと思う。漫画もそれなりに読むし、音楽もなんやかんや毎日聞いている。これまでそういう作品の良さをまともに語ったことはないし、積極的に人と共有したりもしない。物語のキャラクターを推したいと思ったこともない。アーティストを好きになることはあっても、エッセイを読みたいとはあまり思わなくて、あくまでその人の作品が好きだからアーティストを好きになっているように思う。

アニメや漫画は単に面白いからだろうか。少なくとも日常的に触れる作品はそういう毛色が強い気がする。たとえば、鬼滅の刃やかぐや様のアニメはおもしろいから見ている。その一方で、ゾクゾクする経験があって、それが好きだという側面もある。たとえば91daysは面白かったがそれ以上にゾクゾクしたから記憶に残っている気がする。 Fate heaven’s feelやヴァイオレット・エヴェーガーデンも僕にとってゾクゾク系。

音楽はゾクゾクするのを求める気持ちがより強い。Co shu nie には特にゾクゾクを求めている。その他アニソンやボカロ、ピアノ、その他jpopも、そのときの気分にあったゾクゾクを求めて聞いている気がする。横道だけど、900STを買ってから飛躍的に音楽を聞くのが楽しくなった。幸いなことにヘッドホンはまだこれしか買っていない。初手でいいものを買う戦略が功を奏した。昨日くらいから電車通勤で音楽を聞くことに良さを見出してしまい、ワイヤレスでノイキャンのついたいいヘッドホンが欲しくなってしまった。

話を戻そう。ふんわり楽しい時間を求めるのと、ゾクゾクするのを求めるのの、2つの欲求があってそれらを満たすためにアニメとか音楽とかを浴びているようだ。それらの限らず、僕の幸せはそのどちらかにあるような気がする。ゾクゾクするほうが刺激的で楽しいので、今後はそっち方面の体験を増やすために意思決定を進めようと思う。

散歩をしてきて、本当に音楽とかに限らない話だと思った。プログラミング言語や数学のことを考えたり、プログラミングをしたり、オリエンテーリングをするときに、僕が一番好きな瞬間でモチベーションになっている体験はやはりゾクゾクしたときのことだと思う。今挙げた分野でのゾクゾクは、ハイになって、理解のぎりぎりのところで間に合ってというか、手が届いて自分のものにできた感覚だ。それに対して音楽とかアニメとかでのゾクゾクは、与えられた気持ち良さですごく心地良い体験だったり、強く共感したり、よくそこまでいった!すごい!みたいな感動から来る気がする。どちらのゾクゾクも僕を幸せにしてくれるけど、なんとなくプログラミング言語と戯れているときみたいなゾクゾクのほうが欲しい気がする。

2023-04-03

オリエンテーリングの人たちと飲み会をした。社会人としての心構え()を教えて頂いた。今日の入社式から頑張って行こうと思う。

こういう書き方をするとふざけているようにしか見えないだろうけど、内心ではそれなりに不安に思っているし、しっかりとしたフィードバックも受け取れたと思う。

今日、明日で良い出会いをできるといいな。

2023-03-19

最近AIが流行っていて、精度がすごいと話題で、生活が多かれ少なかれ変わっていくのだろうなという感じがする。ああいう機械学習ベースのAIは学習で直感を鍛えて、それに基づく出力をするものだと僕は解釈している。人間が頭を使うときには直感を論理とか議論で検証して、主張の穴を見つけて改善するサイクルを回すはずだ。今の機械学習っぽいAIは直感で得た主張を論理で解釈しないだろう(NECがそういうことを考えていそう。それができればAIはもっとつよくなるはずだし、そういうAIを見てみたい。

実現するためにはAIの入出力に使う「言語」に解釈を入れることと、それをもとにして論証を行うことが必要だろう。今のAIは抽象構文木を操作の対象にしていて、それを意味を解釈するようにしたらいいんじゃないかという想像だ。

今ある論理が世の中の事象を扱うのに十分かはわからないし、多分結構不足しているはずだ。機械学習AIのための論理体系の研究とかあったら楽しいだろう。NIIとかでやってないだろうか?

おととい届いたBig Peatがとてもおいしい。明日の研究室飲み会にもっていこう。ちょうど二年くらい前に部活の先輩に勧めていただいたのだが、懐具合の問題で飲めずにいた。少し無理してでも飲んでおいたほうが良かったかと思うくらいには好き。ストレートで飲んでもおいしいし、ハイボールにしてもおいしい。天才か? ぼくはスコッチウイスキー?が好きなのかもしれない。

学部2年のころ、確率論基礎の試験の前日にウイスキーを飲む会に誘っていただいたとき、ラフロイグ・ロアを味見させていただいて半分感動したのを覚えている。あのころは二十歳になりたてでお酒のおいしさは今よりも分かっていなかったのだが、それでもいいかんじなことは分かった。それからラフロイグ・ロアには縁がなかったのだが今気になっている。数量限定なようで、毎年11月ころに発売されそうな雰囲気がある。今もアマゾンで売ってるが、転売価格に見えるので時期がくるまで我慢しよう。

ちなみにBig Peatと一緒に勧めていただいたジョニーウォーカーのグリーンラベルはすでに飲んでいて、 やはり好きな感じだった。

使い勝手の良いデスクトップ向けウィンドウマネージャが欲しい

使い勝手のよいウィンドウマネージャがWindowsとかMacに搭載されることはないだろう。使うアプリケーションやブラウザ、入力デバイスやその使い方によって使い勝手が大きく変わるだろうから。 OSが決め打ちで提供できるものでは無いんじゃないかと思う。なので自分でまじめに使い勝手の良いものを考える必要がある。

先日オリエンテーリングのインカレの配信のお手伝いをしたのだが、そこで使っていたスイッチャがなかなかデスクトップでのウィンドウマネージャの機能として魅力的に感じた。

スイッチャにはいろんなウィンドウ(カメラからの入力や、図、合成用のテロップなど)が接続されていて、すべてが画面の下部に控えめに表示される。それらを見ながらスイッチャのオペレータが放送するためのウィンドウを選択、合成する。放送されるウィンドウは画面上部に大きく表示される。放送されるウィンドウの右に同じサイズでプレビューウィンドウも表示される。これらの違いは放送されるか否かだけで、合成のテストとかに使える。

これを実現するためには操作用のデバイス(このデバイスをスイッチャというようだ)と、大きなモニタが必要だ。

デスクトップのウィンドウマネージャでもスイッチャのように

  • すべてのウィンドウを表示しておいて
  • 本番+alphaくらいのウィンドウをメインエリアに表示する

と便利な気がする。単純にはいかないだろうけど、いい線行きそうだ。

懸念事項は以下の通り:

  • ウィンドウの個数が多くなりそう
  • ウィンドウサイズが固定ではない(アスペクト比)
  • ウィンドウの動的な生成とその配置方法が非自明

エフェクトハンドラの良さと実用性について

エフェクトハンドラで継続や代数的エフェクトを扱う必要性は一ミリもなくて、実用的にそれらが欲しくなることはないか、あるいは限られていてそこまで一般的な機能を提供する必要はないんじゃないかと感じている。

このあたりを議論するために

  1. エフェクトハンドラの嬉しさ
  2. 意味論の歴史的経緯
  3. 改善ポイント

を考える。

なお、この記事はとくに裏付けもなく書いている。気が向いたら裏付けをしようと思っているが、この記事の目的は僕の考えの整理であって、世に主張をしたいわけではない。

記事の内容は不正確なことを留意されたい。

エフェクトハンドラが実際的 (practical) なプログラミング言語でエンドユーザに使わせたくなるのは

  • エフェクトシステムと相性のよい意味論
  • 動的束縛

を提供したいからではないだろうか。エフェクトハンドラを言語に入れれば、それで表現できる操作は自動的にエフェクトシステムで追跡できるし、ハンドラを用いることでエフェクトをローカルに使えるのは特筆するべきだろう。汎用性とlocal reasoningのしやすさはエフェクトハンドラのもつ良い性質だと思う。

エフェクトハンドラで実現できる動的束縛はとても使い勝手が良い上に、エフェクトシステムで追跡することで使い勝手が上がりそうだ。動的束縛のためだけのエフェクトシステムではなく、もう少し凝ったことができるエフェクトシステムがつくとなお幸せだろうから、エフェクトハンドラみたいな抽象度の比較的高いフレームワークで実現するのは幸せなんじゃないかと感じる。

エフェクトハンドラと呼ばずに “algebraic effects” とか “algebraic effects and handlers” とか呼ぶ流派、時代がある。歴史的には

  • algebraic effects
  • algebraic effects and handlers
  • effect handlers

みたいな流れで登場したはずだ。最初はハンドラはなくて、モナドとかの話をするような人たちが副作用にモナドではない別の表現を与えようとしたんだったか。ここでいうモナドはモナド則とかを真面目に考えるような数学のモナド。代数的エフェクトもその流れの中に(このころは)あったはず。そもそも代数的エフェクトの代数とは、操作が(0だか1こ以上)あって、それらに等式制約を課す。それを満たすようなモデルを持つのが代数 (algebra) である、みたいな世界だっと思う。群とか環は代数だけど、体は代数じゃないみたいな話を聞いたことがある。そういうのりの代数として、エフェクトを表現したらモナドの合成みたいなことを考えるときに幸せだ、という主張がことの発端だった気がする。

ここまでは数学とかモデル理論?とかの話によっていて、あまりプログラミング言語っぽい雰囲気がしない。ハンドラとか継続が入ってきた経緯はしらないが、多分、プログラミング言語に代数的エフェクトを入れるにあたって、モナドのbindやreturnみたいなものを定義するように、エフェクトに意味を与える仕組みとしてハンドラが考えられたんじゃないかと思う。このあたりは論文をまじめに読めば分かるはず。これが確か2014年くらいのこと。

2000年くらいだったかから考えられていたエフェクトシステムとの相性に目をつけたからか知らないが、「代数的エフェクトとハンドラ」を取り入れた言語が2014年ころに登場し始める。2017年くらいにでてくる印象がある。 EffやKokaはこのへんな気がする。このあたりで、エフェクトが代数的であることはとくに気にされなくなっていき、エフェクトシステムと例外ハンドラがうまいこと組み合わさる限定継続演算子くらいの気持ちで代数的エフェクトとそのハンドラが捉えられて、やがて代数的ではないことが気になる人々がエフェクトハンドラと呼ぶようになったのではないかと思っている。

限定継続は本当に必要だろうか。もっとやさしい概念を提供するのにとどめるのはいかがだろうか。ワンショット継続とかに限定する言語もあるが、それは正しい方向性だろうか。

僕たちがほしかったものは、local reasoningしやすいエフェクトシステムとそれで健全に管理できる意味論なんじゃないかと思う。エフェクトハンドラはその条件を満たすけど、もっと使い心地のよい意味論があるはずだと思う。

最後の文をメモしたくてこの記事を書いた。それ以外は文脈である。

軽いドキュメントを印刷するためのツールが欲しい

さくっと書いた文書を印刷したいことがある。ビジネスライクな手紙とか、その日のTODOリストなんかがそうだ。 LaTeXやMadokoを使うのは大げさな感じがして、諦めて手書きするか、Google Docsで済ませることが多い。とはいえ手紙の書き方を毎回調べたり、フォーマットを調整したり、PCで打ち込んだデータを手書きするのはつらい。

テンプレートと変数の宣言、UIの調整と文書のまともな処理をして印刷(A4)できるものが欲しい。A4のPDFに変換できればよい。それぞれの文書のソースはマークダウンのちょっとした拡張くらいの文法で書きたい。エディタで編集したいのでGoogle Docsとかはなしで。テンプレートの作成方法はテキストにこだわらない。いじりやすいと嬉しい。

問題が以下のように分割できるはず。

  • テンプレート作成
  • ソースの文法
    • Markdown拡張
  • テンプレートへのソースの埋め込み
  • PDFへの変換

HTML/CSSやlatexを勉強してMadokoでくっつければなんとかできる気はするが、大変そうだしあまり楽しくない。文書作成ツールを自作するか?とりあえず、HTML/CSSで手紙を表現できるようになるところから始めるのが良さそうか。自作マークダウン拡張(というより処理系)はまれに欲しくなるのでやっても良いだろう。Hugoもそんなに快適じゃないし、Madokoはいじりにくいので。

  • 自分でコードをいじりやすいこと
  • メタな文書処理がしやすいこと
    • 識別子や文書の変数への束縛、正規表現やCFGベースのテキスト置換など
    • この辺はMadokoが強い
  • そういえばMadokoはPDFの生成でHTMLを使わずにlatexを使っていたな…

ここまで来て、Paper CSSという良さげなリポジトリを見つけた。 Qitaでこのライブラリを使って帳票を作る例が解説されている

まだそれぞれをあまり読んでいないのであとで確認する。このあたりの技術に合うように出力することにして、それを生成するマークダウンエンジンを用意すればok?

やはりしんどい気がする。GUIでなんとかする方法を探すのが楽だろうか。あらためて考えよう。

Google Docs APIを利用するのはどうだろうか。 APIはあまりリッチではなくて、create, update, pullができるのみ。文書構造の編集はJSONをごりごりいじることで実現する。JSONスキーマが定義されているので、これを見ながら必要な変換を定義すればよい。

テンプレートをGoogle DocsのGUIで作成して、それをAPIでpullした上で、コンテンツを注入したドキュメントをcreateすれば、やりたかったことを実現できそうだ。テンプレートの置き換え箇所の指定方法はどうするのが良いだろうか。

(開始記号)名前(引数リスト)(終了記号)を文書に埋め込む。これがひとかたまりの文書オブジェクトとして認識されることが必要。また、これにスタイリングを適用した場合、埋め込み後もそのスタイリングが保たれるようにする。引数に他の名前が出現しうることに注意する

テンプレに埋め込むテキストを定義する側では、埋め込み内容の定義リストを作成する:

def name(args: list[str]) -> str:
  return f"""\
ここに置換後の文字列を書く。
ここにも埋め込みの出現を許す。
"""

埋め込み処理では、JSON形式のテンプレのすべてのテキストについてマクロ展開をすればよい。

リブロワークスからCSSで組版するノウハウをまとめた本が5/12に出るらしい。途中までをオフィシャルが公開している。 Vivliostyleというソフトを使って、MarkdownとCSSで書籍を作るらしい。その手のソフトは他にもあるようで、比較サイトを先の書籍で紹介されていた。

こう思うとmadokoはだいぶ良いものだなと感じる。適用範囲を限定した置換とlatexはなかなか強い。 latexとcssを完全に理解すればmadokoが最高かもしれない。

HugoでタグをつけるためのTips

車輪の再発明ではあるだろうけどメモしておく。archetypes/hugo newで生成する.mdファイルのテンプレを置くことができる。そこにありうるすべてのタグを書いておけば、記事を書くときに関係ないタグを消すことで、関連するタグを忘れずにつけることができる。

僕は以下のようにフロントマターを設定している。

---
title: "TODO"
date: {{ .Date }}
author: "Naoya Furudono"
draft: true
tags: [
    "daily"
    ,"PL"
    ,"tech"
    ,"ubuntu"
    ,"alexa"
    ,"book"
    ,"idea"
    ,"python"
    ,"tool"
]
---

Local File Transfer

近距離でのファイル交換はあまり洗練されていない印象がある。 Apple製品間ではAirdropが使えるし、Windowsにも似たような機能があったはずだ。でも汎用的に(たとえばOSを気にせずに)使える機能は見かけない。そういうときにはGoogle DriveやDropBoxみたいなクラウドサービスを使うか、USBメモリを使うのが一般的だろう。 Slackとかメールに頼ることもある。

インターネットに頼るのは不便だし、USBメモリが刺さらないデバイスも多い。 Blootoothを基本の通信方式として、それが使えない場合にインターネットを経由するのはいかがだろうか。

通信技術は既存手法を組み合わせるだけで良いだろう。難しいことはないだろう。一方でアプリケーションのUIには工夫が必要なのではないだろうか。

  • どこにファイルを保存するか
  • OS間でのファイルの互換性
  • 送信先の選択
  • 受信の制御

これらの選択に一般的な回答は存在するだろうか? 他のアプリに組み込む形がよいかもしれない。例えばローカルの会議で各自が自身のPCで文書や画像、図面などを編集するアプリがあったとして、参加者間でのデータ共有のために今考えているものを使う。このときUIはアプリの特性から決まるだろう。

この例に対して、スマホやPCのファイルシステムは一般的すぎて設定を決め打ちできないのではないだろうか。そうすると、ファイル共有の実行時にユーザが設定をあたえることになる。大変不便だろう。

設定ファイルの編集やディスパッチの機能をつければ楽になるか? ルールエンジンとかは大げさだろうか。