はてなキーワード: Dependencyとは
CLAUDE.md や rules / skills みたいな形で、重要なコーディングルールはあらかじめかなり固めておく。
たとえば repository 層や Entity 層は具体的にどう書くのか、テストケースはどういう書き方をして、どういう観点で項目を洗い出すのか、みたいな AI への指示は最初から用意しておく。
あと、linter や ArchUnit、dependency-cruiser みたいなアーキテクチャ制約も、自分なりの定石を持っておく。
割と過剰なレベルでガチガチに固める感じで、アーキテクチャルールも「◯◯は XXX に依存できない」みたいなブラックリスト式じゃなくて、「◯◯は XXX だけに依存できる」みたいなホワイトリスト式の方が良いと思っている。
ts 前提だと eslint や tsconfig は一番厳しい水準に設定する、流石にきつい部分でてきたらそこだけ緩める、という運用
おすすめなのは、何かしらの小規模案件や個人開発アプリを1つオーバーエンジニアリング上等でガチガチ構成で作っておく。
そこで出てきた linter 設定やプロンプト設定を、別案件に横展開する感じ。
正直、ガチガチすぎると MVP とかレベルだとコード量は増えるけど、メンテする前提の案件ならバイブコーディング時代だと普通にペイすると感じている。
アイディアを思いついたら、AI と壁打ちしながら仕様を洗い出していく。
手書きでドメイン図を書いて、それを写メ撮って画像認識で仕様整理、みたいなのも割とアリだと思っている。
どういう画面があって、どういう入力項目や表示項目が存在するか、バックエンドはどういうエンドポイントが必要か、この辺りは最初に一通り洗い出しておく。
それに加えて、ユーザーが初めてトップページを開いてから登録・ログインして実際にサービスを一通り使うまで、みたいな流れをそのまま Playwright のシナリオテストに落とせそうな形で何パターンか仕様書にしておく。
フロントエンドで、DDD における集約みたいな概念がそのまま当てはまらない領域についても、設計時点で洗い出せているなら Entity 的なものやドメインサービス的なロジック用のレイヤを作って、ドメインオブジェクトとして実装していく。
最初に作った基本設計をベースに、◯◯Entity、XXEntity、△△Entity……を作るためのプランとチェックリスト形式の TODO を 1つの md ファイルに吐き出してもらう。
フェーズごとにフォーマッタ、linter、アーキテクチャルールなど一括実行したコマンド実行させて失敗してたら成功するまで修正繰り返させる。
ある程度わかりやすい単位で AI に依頼する感じで、出来上がったコードをレビューする前提なので、実装プランの md 自体はよほど分かりやすいツッコミどころがない限り細かくレビューしない。
mdのフォーマットは skills 側で事前に用意しておく。
フロントエンド用、バックエンド用の両方でドメイン層のファイルを作る。
当然、足りないロジックは後から絶対に出てくるけど、最初から完璧は目指さない。
TODO 一覧の中から自分の認知負荷が許す単位で「チェックリストのここからここまで実装して」と指示を出し、実装が終わったら TODO 項目のチェック状態を更新してもらう、mdファイルもコミットに含める。
コミット前にはlint ルールを無効化していないか、意図通りの実装になっているかは git diff の差分で必ず確認する。
git worktree を使うことが多い。
よくやるのはフロントエンドの画面モック作成とバックエンド実装の2並列で行う。
実装プランを考えてもらうときは「◯◯画面を実装プラン考えて」くらいの単位で依頼する。
実装プランの md ファイルを作るときのプロンプトには、基本設計の〇〇画面の項目一覧をベースに、◯◯のアイテムコンポーネント、リストコンポーネント、◯◯のボタンコンポーネント、Information コンポーネント、外部通信用の ◯◯Gateway を実装する、◯◯コンポーネントは既に ◯◯ 機能で実装してあるからそれを使って、◯◯は処理が膨らみそうだからドメインサービスで実装して、みたいな感じで頭の中のふんわりしたイメージを伝える。
バックエンドも同様で、◯◯のエンドポイントを作って、Gateway がこれこれ必要だから実装して、これはインターフェースと実装分けてね、Entityへの変換処理は関数分けて、◯◯の処理は Usecase 層で、◯◯の処理はドメイン層で、Usecase が膨らみそうだから ◯◯ の処理は独立したクラスにして、あ、似たようなのが ◯◯ 機能にあるからそれを参考にして、くらいの粒度で指示を出す。
フロントエンドの実装を待っている間に、バックエンドのプランを考えたり、タスク粒度を調整したり、リファクタリングプランを考えたりする、またバックエンドのAI待ち時間はフロントエンドのことをする。
フロントエンドオンリーの実装とかで作業が競合するリスクあるときは並列作業しない。
チェックリスト更新が終わるごとに差分を確認して、問題なければコミットメッセージを提案してもらってコミットする。
細切れにするコストよりも、レビューする人間の認知不可が許すレベルであればある程度まとまった単位でレビューして実装速度を優先する派。
テストは、ある程度実装が進んでリファクタリングが辛くなってきたタイミングで作ることが多い。
カバレッジやミューテーションテストなど、定量的にテストを評価できる仕組みは導入する。
バックエンド側のテスト実装は正直かなり楽で、行数や認知的複雑度を厳しく制限して単一責務の原則を守って実装しておけば、AI がかなり高精度なテストを出してくれる。
これもテストファイル実装プランを作ってもらって「ここからここまでのテスト20ファイルを実装してね」をレビュー挟んで繰り返す感じ、例えばミューテーションテストのkill率100%ならそんなに詳しくは見ない。
フロントエンドはテストの定量指標での評価が難しいので、そこはその分レビューを頑張るしかない。
自分はこんな感じでやっている。
感覚としては、優秀だけどシステムのアーキテクチャ全体の責務を負ったことはない経験不足の2年目やSESの部下を扱うEMに近いのかなぁ。
周りの話を聞いていると、もっともっと AI に自律的にいろいろやらせているようにも聞こえる。
これでも 1日1人で数万行レベルはコードを書けてるので、AIない時代に比べると数ヶ月分の成果を1日とかで出してることになるが、もっと本気出せるのかなぁ。
「全機能分プラン作ってね!そこから良い感じの粒度でコミットも自分でやってね!」みたいな指示を良い感じに出せたとしても、指示がでかすぎると、脆弱性盛々になったり、lint エラーループでパニクって linter オフにし始めたり、テスト通すためにエラー握りつぶして assertTrue(true) し始めたりする。
それは流石に許容できないレベルじゃない?が紛れ込むリスクが上がりすぎるんじゃないかなぁ。と思ってるんだがどうだろうか。。。
あとツールはあんま入れてないねkiroとかspec-kitとか、ガチガチ細切れで仕様書作るメリットもあんま感じなかった。
mcpもserenaくらいしかいれてないや、トークン節約してレートリミットの猶予伸ばした方が結局開発早くなるかなって。
いろいろ入れた方がいいんだろうか。
完全にオレオレでこんな感じでやっているんだけど、みんなspec駆動開発というものをどんな感じで、具体的にどうやっているのかが知りたい。
Update:男性の比率はもはやフラットではありません。2024年以降のデータは、若い男性が右傾化していることを示しています。最近の調査はすべて同じ結果を示しています。若い男性は今、より積極的に保守的になっています。私の解釈では、女性が最初に捕らわれたのは、コンセンサス圧力を受けやすかったからです。その捕らわれの過程は急速に進みました(2007年から2020年)。男性は影響を受けにくく、捕らわれた制度にあまり根付いていなかったため、より長く抵抗しました。しかし、その格差が目に見えるようになり、文化的に顕著になり、「男性こそが問題だ」というメッセージが主流のメッセージとして明確に伝わり、嘘によって男性が社会から排除され始め、男らしさ、つまり男性を男たらしめるものそのものが有害になったため、男性は対抗し始めなければならなかった。
受動性は反抗へと変化しつつある。引きこもりは積極的な拒絶へと変化しつつある。これは、男性が今や「正しい」とか「自由」になったという意味ではない。単に、女性の合意ではなく男性の不満を汲み取るための最適化された別の仕組みに捕らわれているだけなのかもしれない。アンドリュー・テイト(注:Andrew Tate アメリカの右翼的・保守的な思想、特に「マノスフィア(Manosphere:男性至上主義的なネットコミュニティ)」やMAGA(Make America Great Again)運動の一部から支持を受ける、物議を醸しているインフルエンサー)はどこからともなく現れたわけではない。マノスフィアも同様だ。それらもまた補足システムであり、単に異なる心理的弱点を狙っているだけだ。
グラフは今や、反対方向に分岐する2本の線になっています。2つの異なる機械が、2つの異なる人口統計を2つの異なる故障モードへと引っ張っているのです。これは単なる教育の問題だと言う人もいるでしょう。女性は大学に進学することが多く、大学はリベラルな人間に育つ、それだけのことです。確かにその通りです。しかし、2007年以降、なぜ格差がこれほど急激に拡大したのか、またなぜ教育制度が大きく異なる国々でこのような現象が起きているのかは説明できません。
経済的な問題だと言う人もいるだろう。若い男性は苦境に立たされており、憤りは保守的になる。これも部分的には真実だ。しかし、男性の経済的な苦境は近年の右傾化以前から存在し、女性の左傾化は女性の経済的成功が高まっていた時期に起きた。男性ならテート、女性ならテイラー・スウィフトといった文化人の例を挙げる人もいるだろう。しかし、これらは原因ではなく症状だ。彼らはマシンーメカニズムが作り出したニッチを埋めたのだ。マシンーメカニズムを作ったわけではない。
多因果モデルの方がより適切である。生物学的基質(合意形成に対する感受性の違い)+技術的トリガー(スマートフォン、アルゴリズムフィード)+制度的増幅(大学支配、女性優位の分野)+経済的インセンティブ(結婚の崩壊、国家への依存)+イデオロギー的ロックイン(サンクコスト、離反に対する社会的処罰)。単一の原因はない。複数の原因が絡み合い、それがたまたま一方の性別に他方よりも早く、より強く影響を与えたシステムである。
Here's the update: the male line isn't flat anymore.
Post-2024 data shows young men shifting right. Recent surveys all show the same thing. Young men are now actively moving more conservative.
My read: women got captured first because they were more susceptible to consensus pressure. The capture was fast (2007-2020). Men resisted longer because they were less susceptible and less embedded in captured institutions. But as the gap became visible and culturally salient, as "men are the problem" became explicit mainstream messaging, as men started being excluded from society because of lies, as masculinity, or the very thing that makes men men became toxic, men had to start counter-aligning.
The passivity is converting into opposition. The withdrawal is becoming active rejection.
This doesn't mean men are now "correct" or "free". It might just mean they're being captured by a different machine, one optimized for male grievance instead of female consensus. Andrew Tate didn't emerge from nowhere. Neither did the manosphere. Those are capture systems too, just targeting different psychological vulnerabilities.
The graph is now two lines diverging in opposite directions. Two different machines pulling two different demographics toward two different failure modes.
Some people will say this is just education: women go to college more, college makes you liberal, simple as that. There's something to this. But it doesn't explain why the gap widened so sharply post-2007, or why it's happening in countries with very different education systems.
Some will say it's economic: young men are struggling, resentment makes you conservative. Also partially true. But male economic struggles predate the recent rightward shift, and the female leftward move happened during a period of rising female economic success.
Some will point to cultural figures: Tate for men, Taylor Swift for women. But these are symptoms, not causes. They filled niches the machines created. They didn't create the machines.
The multi-causal model fits better: biological substrate (differential sensitivity to consensus) + technological trigger (smartphones, algorithmic feeds) + institutional amplification (captured universities, female-dominated fields) + economic incentives (marriage collapse, state dependency) + ideological lock-in (sunk costs, social punishment for defection).
No single cause. A system of interlocking causes that happened to affect one gender faster and harder than the other.
英国の精神分析家ウィルフレッド・ビオン(Wilfred Bion)は、集団(グループ)には
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
現実の課題を遂行する「ワーク・グループ(作動グループ)」と、
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
無意識的な情緒動因に支配される「基底想定グループ(基本想定群)」
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
基底想定グループにおける3つの主要なパターンは以下の通りです。
1. 依存(baD: Dependency)
集団が、一人の全能なリーダーによって保護され、支えられているかのように振る舞う状態です。
特徴: メンバーは受動的になり、リーダーにすべての答えや安全を求め、理想化します。
心理: リーダーが期待に応えられない(完璧な救済者でない)とわかると、強い失望を感じ、新たな「救世主」を探そうとします。
集団が、共通の「敵」や脅威から身を守るために、攻撃するか逃亡するかのどちらかしかないかのように振る舞う状態です。
闘争 (Fight): 特定の個人や集団を標的にして非難したり、攻撃的なリーダーの下で結束したりします。
逃走 (Flight): 核心的な問題を避け、無関係な雑談や遅刻、スケープゴートの排除などによって本来の課題から逃げようとします。
心理: 「見えない敵をやっつけなければ自分がやられる」という迫害的な不安に基づいています。
3. つがい(baP: Pairing)
集団の中にいる「2人の人物(ペア)」から、将来的にすべてを解決してくれる「救世主(新しいアイデアやリーダー)」が生まれるという幻想を抱いている状態です。
特徴: 2人のメンバーが熱心に対話している間、他のメンバーはそれを傍観しながら「この2人のおかげで何かが良くなる」という淡い期待を抱きます。
心理: 現在の困難と向き合うことを避け、未来への希望を抱き続けることで現状の痛みを否定します(躁的否認)。
まとめ
つがい 将来の希望 まだ生まれていない救世主(期待そのもの)
これらの基底想定は、本来の課題遂行を妨げることもありますが、時には集団の結束を助けることもあります。重要なのは、集団が今どの状態にあるかを自覚し、本来の「ワーク(作業)」に戻ることです。
研究者たちは、まず*Messor ibericus*の働きアリが非常に高いヘテロ接合性を示すことを発見しました [6]。これは、遺伝子解析によって、*M. ibericus*の働きアリ(164個体)が、女王アリや他の4種の女王アリ・働きアリ(127個体)と比較して、43,084の多型部位において平均で15倍も高いヘテロ接合性(平均0.797対0.047)を持つことが示されたためです [6, 7a]。この高いヘテロ接合性は、*M. ibericus*の働きアリが**雑種である**ことを強く示唆しています [6]。第一世代雑種を検出するための分析も、すべての*M. ibericus*の働きアリを雑種であると特定しました [6]。
雑種である働きアリの起源を特定するために、母系遺伝するミトコンドリアゲノムの系統解析が行われました [7]。その結果、すべての雑種働きアリが*M. ibericus*の有性生殖個体と同じミトコンドリアゲノムを共有していることから、**母系は*M. ibericus*である**ことが示唆されました [7]。次に、雑種ゲノムの母系および父系アレルを分離し、核DNAの系統解析を実施したところ、すべての父系アレル(164個体)が*M. structor*の個体と強固なクレードを形成し、**父系は*M. structor*である**ことが確認されました [7]。さらに、5,856遺伝子(44,191変異)を用いた集団構造分析では、*M. ibericus*のコロニーの働きアリが、*M. ibericus*と*M. structor*からほぼ等しい集団祖先割合(それぞれ平均0.49と0.51)を持つことが明らかになり、彼らが第一世代雑種であることがさらに裏付けられました [8, 7a]。
これらの結果は、*M. ibericus*が働きアリの生産において**異種交配に依存している**ことを示唆しています [8]。これは、女王アリが別の系統や種の精子を利用して働きアリを生産する「精子寄生 (sperm parasitism)」の既知の事例と同様です [8, 9]。しかし、*M. ibericus*の場合、この依存は**厳密に*M. structor*のオスに限られており**、この2種は系統的に遠く、非姉妹種であることが指摘されています [9, 11c]。
さらに驚くべきことに、これらの2種は正確に同じ分布域を共有していません [8, 10, 11]。地中海地域を含む南ヨーロッパの広範囲で、父系種である*M. structor*が全く存在しないにもかかわらず、*M. ibericus*の雑種働きアリが発見されています [9, 17b]。特に、イタリアのシチリア島では、最も近い*M. structor*の生息地から1000km以上離れた場所で第一世代の雑種働きアリが見つかっており、このような孤立した地域で女王アリがどのように異種交配を行っているのかという疑問が生じました [9, 7b]。この謎を解明するために、研究者たちは*M. ibericus*のコロニーから得られたオスを詳細に調査しました [8]。
形態学的および分子学的分析の結果、*M. ibericus*の女王アリは、働きアリの生産に必要とされる**M. structorのオスも産んでいる**ことが明らかになりました [5]。26の*M. ibericus*コロニーから採取された132匹のオスを調査したところ、顕著な形態的二型性(pilosty)が観察されました [10, 11a, 11b]。サンプリングされたオスの44%は毛深く(*M. ibericus*に属する)、残りの56%はほとんど毛がありませんでした(*M. structor*に属する) [5]。62匹の毛深いオスと24匹の毛のないオス核ゲノムを用いた系統解析では、この2つの形態が完璧に異なる2種に対応していることが示されました [5]。毛深いオスはすべて*M. ibericus*に、毛のないオスはすべて*M. structor*に属しており、これら2種は500万年以上前に分岐した非姉妹種であることが推定されています [10, 11c]。
1. **共通のミトコンドリア**: *M. ibericus*の巣で発見された*M. structor*のオスは、*M. ibericus*の巣の仲間と同じミトコンドリアを共有しており、コロニー全体の共通の母親が*M. ibericus*であることを示しています [12, 13]。このような核-ミトコンドリアゲノムの不一致は、*M. ibericus*のコロニーで発見されたオスに特有のものであり、*M. structor*が自身の種のコロニーで発見された場合には観察されませんでした [12]。
2. **卵の遺伝子型解析**: 5つの*M. ibericus*実験コロニーから採取された286個の卵または幼虫の遺伝子型を解析したところ、11.5%が exclusively *M. structor*の核ゲノムを含んでいました [12]。16匹の女王アリを隔離し、24時間後に産んだ卵の遺伝子型を解析した結果、9%の卵が exclusively *M. structor*のDNAを含んでいることが確認されました [12]。
3. **直接観察**: 1匹の*M. ibericus*女王アリが率いる実験コロニーを18ヶ月間観察したところ、生殖能力のある成体オスに発達した7個の卵のうち、2個が*M. structor*(毛なし)のオス、3個が*M. ibericus*(毛あり)のオスであることが確認されました [14]。これらのオスは形態的・遺伝子的に確認されており、母親女王アリのゲノムは exclusively *M. ibericus*と一致していました [14]。
ハチ目昆虫のオスは通常、受精していない卵から母親の核ゲノムを受け継ぎますが [15, 16]、*M. ibericus*の女王アリは自身の核ゲノムを伝達することなくオスを生産できることが示されました [15]。この観察は、オスが胚の核遺伝物質の唯一の供給源となる「**アンドロジェネシス(雄性発生、すなわちオスのクローン性)**」を示唆しています [15, 17]。他の生物群でも母系DNAを持たない胚が観察されていますが、アリにおいて異種間のアンドロジェネシスが確認されたのは今回が初めてです [15, 18-21]。これは、交配嚢に貯蔵された他種由来の精子からのオスクローニングが種を越えて起こることを意味します [15]。この説明と一致して、*M. ibericus*の女王アリは多配偶者性であり、*M. ibericus*と*M. structor*の両種のオスと交配し、両種の精子を交配嚢に貯蔵していることが確認されました [15]。
働きアリ生産のための義務的な異種交配と、異種間クローニングの組み合わせは、次のようなシナリオを示唆しています。まず、*M. ibericus*の女王アリは他種の精子を貯蔵し、その後、この精子からオスをクローンとして生産し始めたというものです [22]。この経路は、女王アリが共存する系統や種の精子を働きアリ生産に利用する、義務的または選択的精子寄生(sperm parasitism)の広範な観察と一致します [4, 9, 18-20, 22-26]。
このシステムの進化史は、まず「**性的寄生 (sexual parasitism)**」として始まり、その後「**自然な異種間クローニング**」へと発展したと考えられます [1, 25]。祖先的な状態では、*M. ibericus*は共存する*M. structor*のコロニーから精子を搾取していました(図3a) [15, 16a, 21]。これは、他の*Messor*種でも観察されている現象です [12, 22, 27]。しかし、進化した状態では、*M. ibericus*の女王アリは、自身が依存する種を直接生産するようになり、その結果、***M. ibericus*のコロニー内で*M. structor*のクローン系オスが維持される**ようになりました(図3b) [15, 16b, 17, 84c]。
このクローン系オスの出現を確認するため、*M. structor*の核ゲノム系統樹の2つの主要な下位区分が調べられました [17, 16c]。予想通り、一方の下位区分はクローン系に相当し、*M. ibericus*のコロニー内で見つかった、ほとんど同一の*M. structor*のオスのみで構成され、すべて*M. ibericus*のミトコンドリアを持っていました(24個体) [17, 16b, 16c, 80]。対照的に、「野生型」系統は、自身の種のコロニーで見つかったすべての*M. structor*の階級をグループ化していました(53個体) [17, 16a, 16c, 80]。
ほとんどの雑種働きアリがクローン系オスによって生み出されている(164個体中144個体)一方で、一部(164個体中20個体)が野生型オスによって生み出されているという事実は、祖先的状態が最近まで存在していたことを裏付けています [17, 16c]。祖先的状態の事例は、両種がまだ共存する限られた地理的地域(例:フランス東部)に限定されていました [17, 7b, 84b]。対照的に、進化した状態の事例はヨーロッパ全域に広まっており、クローン系オスを維持することで、*M. ibericus*が*M. structor*の本来の生息域を超えて急速に拡大できたと考えられます(例:地中海ヨーロッパ) [17, 7b, 84c]。この経路は、*M. ibericus*が*M. structor*のオスを自身のライフサイクルに組み込み、野生から搾取するのではなく、クローン系として維持するという点で、**家畜化 (domestication)**に似ているとされています [9, 28]。
この見解を支持するように、クローン系は野生型系統と比較して、**極めて低い遺伝的多様性**と**高い遺伝的負荷**を示しました(平均同義語ヌクレオチド多様性πsが0.00027対0.0014、非同義語対同義語ヌクレオチド多様性πn/πs比が平均0.43対0.21) [23, 29]。このパターンは、クローン種や急速な生息域拡大後、または人間によって維持される家畜化された系統で典型的です [23, 30-35]。興味深いことに、クローンオスは形態的にも異なっていました。*M. ibericus*の巣の仲間と異なるのと同様に、野生型の*M. structor*オスと比較しても毛が少ないように見えました [18, 11, 16d, 16e]。
クローンオスが野生のメスと交配することで「家畜化された」状況から脱出できるかどうかを評価するために、45の*M. structor*ゲノムの詳細な分析が行われました [24]。その結果、クローン系と野生型系統の間に雑種は特定されず、そのような出来事は現在存在しないか、極めてまれであることが確認されました [24]。しかし、系統解析や集団遺伝学的構造分析など、さらなる分析は、クローンオスが依然として*M. structor*の**家畜化された系統**であるという考えを支持しています [24]。全体として、これは*M. ibericus*のメスが、形態的にも遺伝的にも異なる最大3種類のオス(*M. ibericus*オス、「家畜化された」*M. structor*オス、「野生の」*M. structor*オス)と相互作用し、そのうち2種類を産み(図2)、3種類すべてと交配している(図3)ことを意味します [24, 36, 37]。
異種出産への移行は、寄生-共生連続体における性的進化の結果と考えられます [25]。*M. ibericus*は、他の数種の収穫アリと同様に、まず義務的な精子寄生へと移行しました [9, 12, 23, 25, 40]。これは、女王アリがエピスタシス的非互換性や自己中心的なカースト偏向遺伝子型のために、自力で働きアリを生産する能力を失った状況です [23, 25, 26]。異種出産への最も直接的な経路ではないものの、この状況は相互精子寄生、つまり2つの系統が働きアリ生産のために互いの精子に依存する精子共生の一形態へと進化した可能性があります [12, 23, 25, 25]。単純な寄生であれ相互寄生であれ、他種のオスへの依存は女王アリにとって最適ではありません。なぜなら、2種類の異なるオスと交配する必要があり、コロニーの地理的範囲が宿主のそれに制限されるためです [25]。しかし、*M. ibericus*は**自身が求める種のオスを自らのコロニー内で生産する**ことで(図3b)、明確な利点を得ました。これにより、義務的な異種交配を維持しつつ、それに伴う固有の制約を最小限に抑えることができたのです [21, 84c]。
クローンオスは、精子を利用する種のライフサイクルに囚われながらも、*M. ibericus*の生殖努力と育児を通じて自身のゲノムを伝播させます [10]。ある意味で、クローンオスは「**完璧なオス寄生体**」と見なすことができます。なぜなら、彼らはメスの宿主にとって不可欠でありながら、メスの卵を犠牲にして繁殖するからです [10]。互いの配偶子に依存することで、両種はライフサイクルを密接に絡み合わせ、**性的寄生から「性的共依存 (sexual co-dependency)」**へと進化しました [22, 85c]。にもかかわらず、メスはこの関係の条件をコントロールしているようです。卵の遺伝子型解析データは、メスがオスの卵の発達と成熟のタイミングを課していることを示唆しています [10]。このような状況は、*M. ibericus*が最初に野生から搾取した種の繁殖をコントロールするという点で、「**性的家畜化 (sexual domestication)**」に似ていると言えます [10]。
この関係は、家畜化のすべての基準を満たすだけでなく [11, 28]、人間による家畜化から地衣類の共生に至るまで、これまで知られている最も顕著な例よりも**はるかに親密で統合されたもの**です [11, 35, 41]。これらの例とは異なり、両パートナーは**義務的な交配相手**であり、家畜化する種は自身の卵細胞質を利用して家畜化される種を直接クローン化しています [11]。このように、自身の細胞質内で異種ゲノムを複製することは、真核細胞内での細胞小器官(ミトコンドリアなど)の細胞内共生的な家畜化を想起させます [11, 42, 43]。したがって、クローンオスは「**超個体レベルの細胞小器官 (organelles at the superorganism level)**」と見なすことができ、この異種ゲノムが直接複製するコロニーへと統合された結果であると言えます [11, 44, 45]。これにより、性別、カースト、種に関して最も多様な個体を生産するコロニーが形成され、それぞれが凝集した生殖単位内で専用の役割を担っています [11]。
このように、**ある種が別の種をクローンとして産む必要のある生殖様式**を明らかにするだけでなく、この「**2種からなる超個体 (two-species superorganism)**」は、**個体性の通常の境界**に挑戦しています [11]。個体性における主要な進化的転換は、異なる実体が統合された高次の単位へと進化する際に起こります [11, 46-48]。2つの種がこのような統合された実体の中で性的に相互依存するようになったことで、異種出産への進化は、このような転換が性的家畜化のプロセスを通じてどのように起こり得るかを示す典型的な例となっています [11]。
日中の生産性は、夜の過ごし方、特に「就寝」というクリティカルなタスクをいかに成功させるかにかかっている。本記事では、つい夜更かししてしまうエンジニアのために、早寝を「技術」として体系化し、再現性のある形で実践するための具体的な手法を探求する。これは精神論ではない。あなたのQoLと生産性を向上させるための、実践的なスリープエンジニアリングだ。
我々エンジニアにとって、夜は不思議な魅力を持つ時間だ。日中の喧騒から解放され、思考は冴えわたり、ゾーンに入りやすい。しかし、その魅力的な時間は、往々にして「早寝」という、人間の生存に不可欠な基本プロセスを犠牲にすることで成り立っている。
「リファクタリングが楽しくなってきた」
これらの探求心はエンジニアの美徳であるが、同時に我々を「睡眠負債」という深刻な技術的負債へと導く。本稿は、この負債を返済し、持続可能な開発(と生活)を実現するための「早寝」という技術に焦点を当てる。
早寝を実装する前に、まずは現状のアーキテクチャに潜むアンチパターンを特定しよう。
就寝前のスマートフォンは、まさに同期的なブロッキングI/Oだ。SNSの無限スクロール、動画プラットフォームの自動再生、チャットアプリの通知。これらは我々の意識というシングルスレッドを完全に占有し、本来実行されるべきsleep()プロセスへの遷移を妨げる。
深夜まで続くコーディングや問題解決は、脳を極度の興奮状態にする。ベッドに入っても、アドレナリンやコルチゾールといったホルモンがCacheに残り続け、CPUがクールダウンしない。shutdown -h nowを叩いても、プロセスが終了しないのだ。
「夜更かしの供」として注入されるカフェインやアルコールは、一見するとパフォーマンスを向上させるように見える。しかし、これらは睡眠の質という重要なmetricsを著しく劣化させる、誤った依存関係だ。特にアルコールは、入眠を助けるように見えて、実はレム睡眠を阻害し、睡眠のアーキテクチャ全体を不安定にする。
不規則な就寝・起床時間は、体内時計という最も重要なCronジョブを破壊する。毎日異なる時間に実行されるジョブが安定した結果をもたらさないのと同様に、不規則な睡眠スケジュールは、日中のパフォーマンスを予測不可能なものにする。
では、どうすればこれらのアンチパターンを排除し、安定した早寝pipelineを構築できるのか。ここではSleep as Codeの概念に基づき、具体的なプラクティスを紹介する。
毎晩、同じ手順で就寝プロセスを実行することで、入眠を自動化する。
- PC/スマホのシャットダウン: 最も重要なステップ。物理的に電源を落とすか、手の届かない場所(別のコンテナ)にdeployする。
- 入浴: 38〜40℃のぬるめのお湯に15分ほど浸かる。これにより深部体温が一時的に上昇し、その後の下降とともに入眠が促される。これはHot-swapならぬHot-bathによるクールダウンだ。
静的コンテンツの消費: 激しい思考を伴わない、静的な情報(紙の読書など)に切り替える。電子書籍ではなく、紙媒体が望ましい。
ストレッチ: 軽いストレッチで、日中のcommitで固まった体をreleaseする。
すべての準備が整ったら、ベッドという本番環境にデプロイする。余計な思考はgit clean -fdで強制削除し、呼吸に集中する。
例:「夕食後のコーヒーが原因だった」→「カフェインの摂取は15時までというSLAを設ける」
早寝は、単に体を休める行為ではない。日中の高いパフォーマンス、明晰な思考、そして創造性を維持するための、最も効果的で再現性の高い「技術」だ。
我々はインフラをコードで管理し、CI/CDでデプロイを自動化するように、自身の睡眠もまた、技術と工夫によってコントロールできる。今夜、あなたのwhile(true)なループをbreakし、持続可能なパフォーマンスを手に入れるための第一歩を踏み出してほしい。
Happy sleeping!
日中の生産性は、夜の過ごし方、特に「就寝」というクリティカルなタスクをいかに成功させるかにかかっている。本記事では、つい夜更かししてしまうエンジニアのために、早寝を「技術」として体系化し、再現性のある形で実践するための具体的な手法を探求する。これは精神論ではない。あなたのQoLと生産性を向上させるための、実践的なスリープエンジニアリングだ。
我々エンジニアにとって、夜は不思議な魅力を持つ時間だ。日中の喧騒から解放され、思考は冴えわたり、ゾーンに入りやすい。しかし、その魅力的な時間は、往々にして「早寝」という、人間の生存に不可欠な基本プロセスを犠牲にすることで成り立っている。
「リファクタリングが楽しくなってきた」
これらの探求心はエンジニアの美徳であるが、同時に我々を「睡眠負債」という深刻な技術的負債へと導く。本稿は、この負債を返済し、持続可能な開発(と生活)を実現するための「早寝」という技術に焦点を当てる。
早寝を実装する前に、まずは現状のアーキテクチャに潜むアンチパターンを特定しよう。
就寝前のスマートフォンは、まさに同期的なブロッキングI/Oだ。SNSの無限スクロール、動画プラットフォームの自動再生、チャットアプリの通知。これらは我々の意識というシングルスレッドを完全に占有し、本来実行されるべきsleep()プロセスへの遷移を妨げる。
深夜まで続くコーディングや問題解決は、脳を極度の興奮状態にする。ベッドに入っても、アドレナリンやコルチゾールといったホルモンがCacheに残り続け、CPUがクールダウンしない。shutdown -h nowを叩いても、プロセスが終了しないのだ。
「夜更かしの供」として注入されるカフェインやアルコールは、一見するとパフォーマンスを向上させるように見える。しかし、これらは睡眠の質という重要なmetricsを著しく劣化させる、誤った依存関係だ。特にアルコールは、入眠を助けるように見えて、実はレム睡眠を阻害し、睡眠のアーキテクチャ全体を不安定にする。
不規則な就寝・起床時間は、体内時計という最も重要なCronジョブを破壊する。毎日異なる時間に実行されるジョブが安定した結果をもたらさないのと同様に、不規則な睡眠スケジュールは、日中のパフォーマンスを予測不可能なものにする。
では、どうすればこれらのアンチパターンを排除し、安定した早寝pipelineを構築できるのか。ここではSleep as Codeの概念に基づき、具体的なプラクティスを紹介する。
毎晩、同じ手順で就寝プロセスを実行することで、入眠を自動化する。
- PC/スマホのシャットダウン: 最も重要なステップ。物理的に電源を落とすか、手の届かない場所(別のコンテナ)にdeployする。
- 入浴: 38〜40℃のぬるめのお湯に15分ほど浸かる。これにより深部体温が一時的に上昇し、その後の下降とともに入眠が促される。これはHot-swapならぬHot-bathによるクールダウンだ。
静的コンテンツの消費: 激しい思考を伴わない、静的な情報(紙の読書など)に切り替える。電子書籍ではなく、紙媒体が望ましい。
ストレッチ: 軽いストレッチで、日中のcommitで固まった体をreleaseする。
すべての準備が整ったら、ベッドという本番環境にデプロイする。余計な思考はgit clean -fdで強制削除し、呼吸に集中する。
例:「夕食後のコーヒーが原因だった」→「カフェインの摂取は15時までというSLAを設ける」
早寝は、単に体を休める行為ではない。日中の高いパフォーマンス、明晰な思考、そして創造性を維持するための、最も効果的で再現性の高い「技術」だ。
我々はインフラをコードで管理し、CI/CDでデプロイを自動化するように、自身の睡眠もまた、技術と工夫によってコントロールできる。今夜、あなたのwhile(true)なループをbreakし、持続可能なパフォーマンスを手に入れるための第一歩を踏み出してほしい。
Happy sleeping!
テスト対象は大小さまざま。OSの保守だったり、アプリだったり。レガシーだったり、モダンだったり。個人だったりチームだったり。GUIだったりCUIだったり。
GでもCでもUIはまた別
結論としては書かないほうがいいと思った。
そういうこともある
全然小さいというか書くためと変更のコストがクソデカなら何か間違ってる
結局、テスト対象も変わってしまうし、プロジェクト設定も変わるし、Jenkinsも変わるし、人間の頭の中も変えないといけない。
まあそれはないだろう
それはデバッグの一環のような
一番よくあるやつ
そこのバランス考えないと
バックエンドのビジネスロジックを担当するがっちり仕様が決まっていて勝手に変更されてはいけないものなんかをやる
悪いね
テストコードを書くと、テストしやすいクラスの実装をするようになる。それは美徳とされているが、実際には直感的でない長くて複雑なプログラムになっている。
例えばテストコードを書くためにDependency Injectionとか言って外から内部を変更できるようにすると
メンバ関数でやるべき処理が実際にはクラスの外にある、となる。最初は面白く感じたり達成感があるかもしれないが、しばらくして見返すと酷い状態だ。
DIはSOLIDに入ってるくらいで基本だし今時のフレームワークなら普通に使うよね
上にも書いたけどパーツがでかいのでは?って「直感的でない長くて複雑なプログラムになっている」とのことなのでやっぱりでかいんだろう
テストコードを書いたほうが早い時もあったけど、トータルで考えれば、テストコードを完全にやめたほうがシンプルなコードで早く完成する。
要件が固まらない、毎週変わるようなのとか、システムが絡むテストでコストが凄く高いもの、UIのマイナーな変更なんかは書かない方がいいけど
ネット上ではテストコードを書かないのは低レベルな開発者という風潮だ。
10年以上、テストコードを書く開発と書かない開発の両方を経験してきた。
■前提
・テスト対象は大小さまざま。OSの保守だったり、アプリだったり。レガシーだったり、モダンだったり。個人だったりチームだったり。GUIだったりCUIだったり。
結論としては書かないほうがいいと思った。
・テストを書くためのコストが小さいなんて妄想もいいところだ。クソデカである。
結局、テスト対象も変わってしまうし、プロジェクト設定も変わるし、Jenkinsも変わるし、人間の頭の中も変えないといけない。
・100人以上かかわる巨大プロジェクトでも「テストコードを書かなかったので破綻した」、とかはなかった。
・テストコードを書くと実装の見落としが見つかってありがたいことはあった。
・git pushするたびに毎回走っても全くの無意味だった。
・テスト対象が変わるとテストを書き直さないといけないのがサイアクだった。非効率化の極みだ。人生の無駄。
・その次にサイアクだったのは、テストコードの実行が失敗したときテストコードのバグであることが大半であったことだ。
・GUIソフトとテストコードは相性が悪いが、そもそも世の中のソフトウェア開発の大半はGUI開発である。
・テストコードを書くと、テストしやすいクラスの実装をするようになる。それは美徳とされているが、実際には直感的でない長くて複雑なプログラムになっている。
例えばテストコードを書くためにDependency Injectionとか言って外から内部を変更できるようにすると
メンバ関数でやるべき処理が実際にはクラスの外にある、となる。最初は面白く感じたり達成感があるかもしれないが、しばらくして見返すと酷い状態だ。
テストコードを書いたほうが早い時もあったけど、トータルで考えれば、テストコードを完全にやめたほうがシンプルなコードで早く完成する。
Microsoft「Dependency Injectionは卑猥なので禁止」
たとえば、DI(Dependency Injection)で検索すると、すごい数の解説記事が出てくる。それも、プログラミング初心者向けではなく、開発者向けに。
だけど、ぶっちゃけDIなんて、解説が必要なほど難しいこととも、内容のあることとも思えない。
これって、アレと同じなんだよな。数学でいつまでたっても、(-1)×(-1)=1になるたとえ話とか、0.99...=1の説明とかに夢中になってる人たち。普通に数学ができる人は、そんなのはさっさと卒業して内容のあることやるものなんだが。
おそらく、理解力の低いプログラマと、コードは書けないがオブジェクト指向は大好きなポエマーの相乗効果で、こういう話題が盛り上がったんだろうなー。
そういうわけなので今日は公開資料を中心にリリース失敗の技術的な要因を分析してみたいと思います。
ドワンゴアカウントシステムはScalaのコードだけで22万行を越え、ドワンゴ社内で最大のScalaリポジトリとして知られています。
ドワンゴのユーザーアカウント基盤は明らかに破綻しています。 10 年以上にわたり、ガラケー時代から今に至るまで多くの業務をコードに落としていくことは極めて難しい作業であったと思います。そうはいってもやってるうちに一回なんとか出来なかったのかとは思うわけです。やっている当人たちがテンションを上げているほどには開発効率が出ていない、むしろ足を引っ張っているという可能性はかなり高いと思います。
ニコニコ生放送(以下「生放送」)ではバックエンド・フロントエンドのサーバーを建てる環境として、2016年からDocker Swarmを採用し始めています。
Docker Swarm Mode については私も検証をしたことがあり、非常に優れた思想をもった将来性のあるプロダクトであると感じていました。個人的な検証はずっと続けています。まず swarm mode の何が優れているかと言えば、コマンド体系の分かりやすさです。開発者は何のストレスを感じることもなくクラスタを扱うことができます。さらに、サービスディスカバリ層を極めて扱いやすい形(サービス作ると公開することを指定したポートがクラスタ内の全マシンで公開されるので、あとはクラスタ全台に向けてロードバランシングするだけでいい事実上のゼロコンフィグレーション)で実装したことは素晴らしいと思います。しかし、残念ながらこの素晴らしい思想を持ったプロダクトは砂上の楼閣でした。その肝心なサービスディスカバリは安定しておらず信頼できません。またマスターがコケてそのままクラスタ全部が機能を停止するだとか、ノードが気づいたら行方不明だとかはざらです。こうした問題は 2016 年末から現在に至るまで残念ながらあまり改善されていません。
私は kubernetes が嫌いです。 Google 製品は開発者の UX を考慮しないからです。しかし、 2016 年においても、 2017 年の今においても彼のプロダクトが商用環境における事実上唯一の選択肢でした(ついでに言うならば docker service コマンドで kubernetes いじれるようになるので UX 問題も解決する)。正直、 2016 年から swarm mode を仕事で使おうとしたのは、深刻なソフトウェア検証能力の欠如を感じます。
実は分散ファイルシステムも独自に開発しました。もともと既存のオープンソースのファイルシステムを使っていたのですが,それだと期待する性能が出ないことがわかり,独自に調査開発を進めることにしました。
こちらの記事を読んでいただければわかりますが、配信基盤の再構築を行うにあたって
ということが分かります。
触れない話: 事実上全然稼働しなかった CTO 、北の将軍様
パブリッククラウド、特に CDN を採用することは開発負担の軽減に多いに貢献するように考えられます。実際「 akamai 使えよ」みたいなこと言ってるユーザーは結構いるわけです。ではなぜ彼らがそうしないのか、その意思決定の理由をここでは探ってみます。
動画ストリーミングサービスとして遅れているというのは恥ずかしいことではありますが、ハードウェアや使っている回線の影響もありますので、どのサービスも最終的には同じになると思っています。その差をつけられることはこの先はなくなると思っています。
ようするに CDN 屋だろうが自前だろうが最終的に同じようなところに落ち着くだろうという予測を彼らは立てているということです。しかし現実問題として現在競合他社との差は大きく、新配信基盤のリリースの目途は立っていません(半年以上の遅れというのは通常そういうことでしょう)。ではなぜ彼らは最終的に差は無くなると予測するのか。私はこの点において彼らが空元気をふりまわしているとは思いません。
CDNのトラフィックエンジニアリング:CDNの現状とSDNの可能性
要するに CDN 各社は現在逆ザヤで出血を続けながら戦闘しており、 DDoS 対処を中心としたセキュリティサービスにより最終的な帳尻を合わせている状態です。自前で動画配信インフラを構築した経験のあるドワンゴは CDN 大流行の早い段階から「成立するビジネスではない」という見通しを立てていたであろうと思います。
ただしこの点において今後もビジネス環境、技術環境が現在のように推移するのかは、私にはよく分かりません(誰にも分かってないでしょう)。結局同じようなところに落ち着くならありもの使っとけよとは思わなくはない。
まあもう無理でしょいろいろ
依存性地獄( Dependency Hell )かな。https://en.wikipedia.org/wiki/Dependency_hell
An application depends on many libraries, requiring lengthy downloads, large amounts of disk space, ...
(アプリケーションがたくさんのライブラリに依存していて、長時間のダウンロードや大量のディスク容量が必要で、...)
app depends on liba, which depends on libb, ..., which depends on libz. This is distinct from "many dependencies" if the dependencies must be resolved manually (e.g., on attempting to install app, the user is prompted to install liba first. On attempting to install liba, the user is then prompted to install libb.).
(アプリケーションがAを必要としていて、そのAはBを必要としていて、(中略)Zを必要としているような場合。ユーザーが手動で依存性を解決しなければいけない場合には、先ほどの例とは違い、ユーザーは「アプリケーションをインストールしようとしたらAが必要と言われ、AをインストールしようとしたらBが必要と言われる」目に遭うことになる)
私はコミットログの書き方に悩む英語の苦手な人間である。実際、似たような人は世の中に結構いるようで、頻出単語を集計したりまとめたものは既にあって役に立つのだけれど、これらはあくまで単語の話であり、具体的な文を構成する過程でやっぱり困る部分がかなりあった。
要するに、どういう時にどういう文が使われているのか、ということを示した例文集が欲しいのである。ググると他にも「例文集があればいいのに」みたいな声はあるくせして、しかし誰も作ろうとしない。何なんだお前ら。それじゃ私が楽できないじゃないか。
ここで挙げているコミットログは全て実際のコミットログからの転載である。当然ながら各コミットログの著作権はそれぞれの書き手にある。いずれも各英文でググれば出てくるし、フェアユースの範囲なら許してくれるだろうと考え名前とプロジェクト名は割愛したが、ここにお詫びと感謝を述べておきたい。
抽出条件だが、参考にできそうなコミットログを多く含んでいそうなリポジトリをGitHubのSTARの多い方からざっと目で見て適当に選び、それぞれ最新コミットから5000件抽出した(あわせて前処理として、コミットログ冒頭のタグ情報は消去した)。
atomのみ5400件抽出していたため、計25400件のコミットログがベースである。このうち、以下の条件に合致するものは参考例にすべきでないとして一律排除した。
こうして残った8540件を眺めながら、適当に切り出したのがこの用例集である。個人的に「うーんこの」と思った表現も、散見される場合は載せた。
ということで、以下用例を羅列していく。
以上の用例をふまえ、今回の参考ログ8540件から先頭の単語を出現回数で並べると次のようになった。
| Add | 1149 |
| Fix | 1014 |
| Update | 584 |
| Remove | 566 |
| Use | 382 |
| Don't | 260 |
| Make | 228 |
| Move | 178 |
| Change | 103 |
| Rename | 85 |
| Improve | 76 |
| Avoid | 68 |
| Allow | 65 |
| Implement | 60 |
| Handle | 58 |
コミットログの基本形はもちろん動詞 + 名詞である。名詞は固有名詞、複数形、不可算名詞が多いが、単数形の場合の冠詞は a が使われるか、あるいは省略される。the はまず使われない。
何かを追加した、という表現では非常に広く Add が使われる。メソッドからテスト、ドキュメントに至るまで大概これでまかなえる。
一方、何かを修正した、という表現では広く Fix が使われる。「何か」は typo や crash といった単語からメソッド名まで幅広い名詞を取るが、動名詞はあまり取らないのと、that節は取らないのでその点は注意が必要である。
Fix は「何かが正しく動くようにした」ことを示し、正しい動作内容が何かを説明しない。そこで正しい動作内容に言及したい場合は Make sure が使われる(こちらはthat節が取れる)。ただし Fix よりもニュアンス的に重い表現と思われ、Fix を使わず Make sure ばかり使うのはちょっとキモいのではないかと思う(Ensure はさらに重い表現っぽい)。
また、Fix は typo 以外でのドキュメント修正に対して使われることは稀である。対して Update はドキュメント、コメント、テストに使われ、本体のコードの修正に対しては使われない。本体コードの修正にあわせてテストも更新したなら Update が使われる。ただ、テスト機構それ自体のバグを修正したなら Fix である。
無駄な何かを単純に除去したなら Remove を使う。これまでのもの(A)から別のもの(B)に切り替えたのであれば Use B instead of A か Change A to B が使われる。新たに何かを利用するようにしたのであれば Use を、利用を取りやめた場合は Don't use を使うことが多い。
何かをしないようにしたなら Don't を、内部実装の効率化なら Make A + 比較級/形容詞 か Improve が使われる。
中身の変更を伴わない単なる名前の変更なら Rename A to B、コードや機能の論理上の場所を移動させたなら Move A to B である。
この辺はリファクタリングと呼ばれる行為と思うが、Refactor というぼんやりした動詞はあまり使われず、このように変更内容の種類に応じて動詞が使い分けられている。
コミットログにはWhyを書くべきだ、というのを何かで見かけたので because とか since を使ったログがどの程度あるかを調べたが、8540件のうち22件だった。基本的に短く、シンプルに、一目で意味が取れるログが好まれる傾向がある。例えば get rid of とか2件しか使われておらず、圧倒的に remove である。
一方で、シンプルな単語だけど開始単語としては使われないものもある。例えば次のような単語である。Expand(9)、Extend(8)、Print(5)、Optimize(5)、Publish(4)、Append(4)、Modify(3)、Manage(2)、Revise(2)、Dump(2)、Insert(2)、Migrate(2)、Enhance(1)、Edit(1) 。いずれもカッコ内は8540件に対する冒頭での登場回数である。結局、より一般的で平易な単語で表せたり、Refactor同様に抽象度が高すぎると使われないのだろう。
8000件もログを見たおかげで、迷いなくコミットメッセージが思いつくようになったのが個人的には今回書いてて最大の収穫だった。たぶんカンニングペーパーを作る行為それ自体が効率のいい学習になるという話と同じだと思う。
このまとめも100以上用例を転載してあるので、それを読むだけでも多少は効果があるんじゃないかと思う。同じようにコミットログ書きたくねぇなぁ英語わっかんねぇなぁと思っている人にとって、何か役に立つところがあれば幸いである。
Qiitaに書こうかと思ったけど、言いたいことも言えない、こんな世の中じゃ。
モバイルファースト、APIファーストな文脈でハイブリッドWebをやってきた目からすると、サーバーサイドでHTMLを生成してページ遷移させるなどという90年代調のクラシカルな発想を基本に据えるフレームワークはとても斬新に思えました。HTMLをゴリゴリ生成するなんてよほど特殊な最適化をしようとするのでなければそもそも発想として出てこないです。それでいてDSLやメタプログラミング等のテクニカルな技法が宝石のように鏤められている様はまるでエジプト時代の骨董品を見るかのような趣がありました。turbolinkなどは、かつて表計算ソフトに出しゃばっていたイルカを思い起こさせる味があります。かつて慣れ親しんできたSPAが星のように遠い存在になりました。
Web界隈の人々がモデルだとかアクティブレコードだとか"MVC"だとかを非常に具象的に話す様を見るにつけ、お前らどんだけPofEAA読み込んでるんだよと畏怖していた時期が僕にもありましたが、どうやら彼等はRailsのクラスやディレクトリという特定の実装について話していただけだったようです。Modelという概念もこれだけ肥大化してしまったら、オリジナルな概念で彼等と会話するのは諦めるべきかなと思いましたし、Railsの"MVC"をアンクォートして語るのはもはや害悪であるとすら感じました。
Rails界隈の人がよく「Railsの流儀」や「正しい"MVC"」というのを口角泡を飛ばして議論しているのを目にするのですが、おそらく外に広がる不条理で火傷を負って快適なRailsの世界に引き篭もった結果としての一種のストックホルム症候群なのだなと思いました。いまやAjaxとかWebsocketとかWebRTCとかを組み込もうとする至極真っ当な方法論がとてつもない高難度に見えてきます。設定よりも規約、というのも一つの方向性だと思いますが、ドメインやサービスレイヤの名前空間を構築しようとしたりコードジェネレーションしようとしたりしただけで地獄のようなCircular Dependency罰を受けてしまったので、自分がとても間違った事をしているような気がしてしまいました。とはいえConcernsに特別な名前や役割を与えられても正直しんどいので、皆が皆libにゴミを放り込んでいく様子にも納得がいきました。
RailsをAPIサーバーとして使おうとするとまずビューが無くなってMとCだけになりますが、いわゆる"MVC"の文脈で育ったエンジニアがなぜ息を吸うようにFat ControllerやFat Modelを作ってしまうのかという事が良く分かりました。多くのRailsのリファクタ手法と称されているものはクラスを書くファイルを分割する事以上のものでは無いように思えたので、Rails使いを大きめなAPIサーバー案件に回すときはセットポジションでDDDの青本を投げつける必要が有るなと思いました。
ビューとコントローラを結合させた場合、結合テストはCapybaraとかのBDDでマークアップサイドとの干渉を恐れながら強い気持ちでメンテしていくしか無いのかなと思いました。おそらく脳に電極を埋め込んでいるか、緑色のランプを見るだけでハイになれる特殊な人にしか生き抜けない闇が垣間見えました。コントローラを薄くしてサービスレイヤを挟めばその辺りもうまくいけそうな気がしましたが、ビューからヘルパーやモデルがいくらでも透けて見えてしまうという状況では裏側の完全性に自信を持つ事は難しそうでした。
ビューがRubyを叩いて永続化レイヤと直接コミュニケーション出来るというのはとても生産性が高いのだろうとは思いましたが、こうして出来たパーシャルやら何やらをデザイナーとどうやって共有するかを考えると頭痛が痛くなりました。おそらく適当に切り出して綺麗な空間をassets以下に構築した上でpublicにRPCのような窓口を備えたゴミを量産していくのかなと思いましたが、もっと綺麗な方法はあるのかもしれません。でもきっとRails案件に関われるデザイナーはRubyもバリバリ書けるに違いないはずなので、ここが問題になる事は無いのだろうなと思いました。
RESTはとても美しいパラダイムではありますが、そもそもHTTPがさほど美しくないので歪んだ空間には目を背けるか勝手解釈を与える事で人は初めてRESTfulを名乗る事が出来るのだと思います。GETがbodyを(公式には)持たないという事について美しい説明を与える事は出来ないでしょう。サーチAPIはどうしますか。ステータスコード足りなくないですか。401エラーはどうしますか。そしてRESTはあくまでリソースを抽象化する美しい概念なので、アクションや副作用については貧弱です。動詞が足りないですし、一般動詞に狭義の意味を与えてドキュメントするのは二度手間にしか見えません。PUTには冪等性があるべきみたいなこだわりは家の猫にでも説教してればいいと思います。というわけで、REST的な設計を拝借することはよしとしても、「○○はRESTでは無い故云々~」みたいな注文はやめて頂きたいものです。
とか言わないで欲しいです。こういう時にセットでPHPをディスって悦に浸るのは知る限りRubiestとPythonistaと中学生だけです。それにこれはあくまでサーバーサイド初心者の感想なので、想像するにこれ系のFWは多かれ少なかれ似たような不満を抱えるものなのかなと思います。というわけで、おそらくこれから選択肢がある限りはRailsを使い続けると思います。
[admin@sakura2 ~]$ uname -a Linux sakura2 2.6.9-67.0.4.ELsmp #1 SMP Sun Feb 3 07:08:57 EST 2008 i686 athlon i386 GNU/Linux [admin@sakura2 ~]$ cat /etc/issue.net CentOS release 4.6 (Final) Kernel \r on an \m
# yum update # yum remove emacs emacspeak emacs-leim emacs-common # yum remove NetworkManager # yum remove bluez-bluefw bluez-hcidump bluez-libs bluez-utils # yum remove cups cups-libs # yum remove irda-utils isdn4k-utils pcmcia-cs wireless-tools # yum remove wpa_supplicant gpm xinetd # yum remove ppp nfs-utils lksctp-tools autofs # yum remove xorg-x11-libs # yum remove selinux-policy-targeted # yum remove vsftpd # yum clean all
[admin@sakura2 ~]$ uname -a Linux sakura2 2.6.9-67.0.7.ELsmp #1 SMP Sat Mar 15 06:54:55 EDT 2008 i686 athlon i386 GNU/Linux
# rpm -Uvh http://mirror.centos.org/centos/5/os/i386/CentOS/centos-release-notes-5.1.0-2.i386.rpm \ http://mirror.centos.org/centos/5/os/i386/CentOS/centos-release-5-1.0.el5.centos.1.i386.rpm [root@sakura2 admin]# cat /etc/issue.net CentOS release 5 (Final) Kernel \r on an \m # yum update glib procps udev iptables # rpm -Uvh --nodeps http://mirror.centos.org/centos/5/os/i386/CentOS/initscripts-8.45.17.EL-1.el5.centos.1.i386.rpm \ http://mirror.centos.org/centos/5/os/i386/CentOS/mkinitrd-5.1.19.6-19.i386.rpm # rpm -Uvh http://mirror.centos.org/centos/5/os/i386/CentOS/e2fsprogs-1.39-10.el5.i386.rpm \ http://mirror.centos.org/centos/5/os/i386/CentOS/e2fsprogs-libs-1.39-10.el5.i386.rpm \ http://mirror.centos.org/centos/5/os/i386/CentOS/e2fsprogs-devel-1.39-10.el5.i386.rpm
# rpm -Uvh http://mirror.centos.org/centos/5/os/i386/CentOS/kernel-2.6.18-53.el5.i686.rpm
[admin@sakura2 ~]$ uname -a Linux sakura2 2.6.18-53.el5 #1 SMP Mon Nov 12 02:22:48 EST 2007 i686 athlon i386 GNU/Linux # yum clean all [root@sakura2 admin]# yum --version Loading "fastestmirror" plugin 2.4.3 [root@sakura2 admin]# rpm --version RPM version 4.3.3
# yum update Error: Missing Dependency: python-abi = 2.3 is needed by package python-elementtree
# vi /etc/ssh/sshd_config # /etc/init.d/sshd restart
# vi /etc/yum.repos.d/dhozac-vserver.repo
# yum update kernel # yum install util-vserver{,-core,-lib,-sysv,-build}
[admin@sakura2 ~]$ uname -a Linux sakura2 2.6.22.19-vs2.3.0.34.1 #1 SMP Mon Mar 17 05:32:04 EDT 2008 i686 athlon i386 GNU/Linux
# yum update bash screen rsync # /etc/init.d/iptables save # /etc/init.d/iptables start # cat /etc/sysconfig/iptables # Generated by iptables-save v1.3.5 on Mon Mar 24 19:57:07 2008 **filter :INPUT ACCEPT [1067:96557] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [63680:6208436] :e0 - [0:0] -A INPUT -i eth0 -j e0 -A e0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A e0 -p icmp -m icmp --icmp-type 8 -j ACCEPT -A e0 -p tcp -m tcp --dport 22 -j ACCEPT -A e0 -p tcp -m tcp --dport 80 -j ACCEPT -A e0 -p tcp -m tcp --dport 443 -j ACCEPT -A e0 -j REJECT --reject-with icmp-port-unreachable COMMIT # Completed on Mon Mar 24 19:57:07 2008 # Generated by iptables-save v1.3.5 on Mon Mar 24 19:57:07 2008 **nat :PREROUTING ACCEPT [179:10642] :POSTROUTING ACCEPT [213:13895] :OUTPUT ACCEPT [251:16220] -A PREROUTING -s ! 10.0.0.0/255.255.255.0 -p tcp -m tcp --dport NNNN -j DNAT --to-destination 10.0.0.1:22 -A POSTROUTING -s 10.0.0.0/255.255.255.0 -d ! 10.0.0.0/255.255.255.0 -j SNAT --to-source AAA.BBB.CCC.DDD COMMIT # Completed on Mon Mar 24 19:57:07 2008
[root@sakura2 ~]# /usr/sbin/vserver-stat CTX PROC VSZ RSS userTIME sysTIME UPTIME NAME 40013 27 301.5M 73.8M 30m36s31 56m38s90 11d06h56 one 40015 5 10.8M 4.4M 0m28s33 0m12s68 9d04h23 two 40016 2 4.2M 1.3M 0m00s47 0m00s64 0m01s97 three
Visual Studio 2005しかインストールしてない場合、Python 2.5だとdistutilsが正しく動かないっぽいので、どうにかしたいYO!
distutilsでVisual Studioを使うときのコンパイル環境は、sysモジュールのversionプロパティを参照して環境を選択をしているようです。Pythonのインタプリタを起動して、以下のような命令を実行してみると、sys.versionプロパティが確認できます。
import sys;print sys.version
Python 2.5.2だと、以下のようになっています。Visual Studio 2003の環境が使われるようです。
2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)]
Python 2.6a1だと、以下のようになっています。Visual Studio 2008の環境が使われるようです。
2.6a1 (r26a1:61155, Mar 1 2008, 12:11:56) [MSC v.1500 32 bit (Intel)]
以上から察するに、Python 2.5.2とPython 2.6のどちらでも、Visual Studio 2005の環境が選択されることはないっぽいです。うーん、困った!
「Python 2.6とVisual Studio 2008をインストールしよう!」というのを真っ先に思いつきましたが、あんまり環境を変えたくないんだよなー。というわけで、環境の変更を最低限に抑えてどうにかしてみました。簡単に言うと、distutilsだけの置き換えをしました。
Python 2.6の公式ダウンロードページから、Windows版のインストーラーをダウンロードして、適当な場所にインストールしてください。
"Python-2.5.2/Lib/distutils"を別の場所に移動し、"Python-2.6a1/Lib/distutils"を"Python-2.5.2/Lib"以下にコピーしてください。以降はPython 2.6は必要ないので、アンインストールして構いません。
上記の2点の変更を行います。distutilsディレクトリに、以下のパッチをあててください。
Index: msvccompiler.py =================================================================== --- msvccompiler.py +++ msvccompiler.py @@ -170,6 +170,7 @@ if majorVersion == 6: minorVersion = 0 if majorVersion >= 6: + return 8 return majorVersion + minorVersion # else we don't know what version of the compiler this is return None Index: msvc9compiler.py =================================================================== --- msvc9compiler.py +++ msvc9compiler.py @@ -128,7 +128,7 @@ "sdkinstallrootv2.0") else: raise KeyError("sdkinstallrootv2.0") - except KeyError as exc: # + except KeyError, exc: # raise DistutilsPlatformError( """Python was built with Visual Studio 2008; extensions must be built with a compiler than can generate compatible binaries. @@ -172,6 +172,7 @@ if majorVersion == 6: minorVersion = 0 if majorVersion >= 6: + return 8 return majorVersion + minorVersion # else we don't know what version of the compiler this is return None @@ -455,7 +456,7 @@ try: self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) continue elif ext in self._mc_extensions: @@ -482,7 +483,7 @@ self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) continue else: @@ -495,7 +496,7 @@ self.spawn([self.cc] + compile_opts + pp_opts + [input_opt, output_opt] + extra_postargs) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise CompileError(msg) return objects @@ -520,7 +521,7 @@ pass # XXX what goes here? try: self.spawn([self.lib] + lib_args) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LibError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) @@ -598,7 +599,7 @@ self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) - except DistutilsExecError as msg: + except DistutilsExecError, msg: raise LinkError(msg) else:
python.exeと同じディレクトリに、以下のXMLを"python.exe.manifest"として保存してください。
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> </dependentAssembly> </dependency> </assembly>
これで終わりです。
以上のような組み合わせで出くわした困ったことと、その解決策をメモしておきます。
Python was built with Visual Studio 2003;
extensions must be built with a compiler than can generate compatible binaries.
Visual Studio 2003 was not found on this system. If you have Cygwin installed,
you can try compiling with MingW32, by passing "-c mingw32" to setup.py.
setup.pyに.iファイルとか.cppファイルを記述して実行すると、こんな感じのエラーメッセージが表示されました。うーん、困った!
http://labs.cybozu.co.jp/blog/mitsunari/2007/08/vc2005boostpython.html
上記のページを参考にして、"%Pythonをインストールしたフォルダ%/Lib/distutils/msvcompiler.py"を以下のように修正してみたら解決できました。ありがとうありがとう!
--- msvccompiler.py 2007-04-04 17:17:12.000000000 +0900 +++ @@ -126,7 +126,7 @@ self.set_macro("FrameworkDir", net, "installroot") try: if version > 7.0: - self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1") + self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv2.0") else: self.set_macro("FrameworkSDKDir", net, "sdkinstallroot") except KeyError, exc: # @@ -252,7 +252,10 @@ def initialize(self): self.__paths = [] - if os.environ.has_key("DISTUTILS_USE_SDK") and os.environ.has_key("MSSdk") and self.find_exe("cl.exe"): + if self.__version >= 7.1 or ( + os.environ.has_key("DISTUTILS_USE_SDK") and + os.environ.has_key("MSSdk") and + self.find_exe("cl.exe")): # Assume that the SDK set up everything alright; don't try to be # smarter self.cc = "cl.exe" @@ -288,10 +291,16 @@ self.preprocess_options = None if self.__arch == "Intel": - self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' , - '/DNDEBUG'] - self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX', - '/Z7', '/D_DEBUG'] + if self.__version >= 7.1: + self.compile_options = [ + '/nologo', '/Ox', '/MD', '/W3', '/EHsc', '/DNDEBUG'] + self.compile_options_debug = [ + '/nologo', '/Od', '/MDd', '/W3', '/EHsc', '/Z7', '/D_DEBUG'] + else: + self.compile_options = [ + '/nologo', '/Ox', '/MD', '/W3', '/GX', '/DNDEBUG'] + self.compile_options_debug = [ + '/nologo', '/Od', '/MDd', '/W3', '/GX', '/Z7', '/D_DEBUG'] else: # Win64
setup.pyを実行するとcl.exeが見つからないみたいなエラーが表示されました。これは、アレだ。「パス通せ!」ということですね。bashを起動するときのバッチファイル(たぶん"cygwin.bat"とか)で、以下のような行を入れてやれば解決しました。
call "%VS80COMNTOOLS%vsvars32.bat"
d:\python25\include\pyconfig.h(189) : fatal error C1083: include ファイルを開けません。'basetsd.h': No such file or directory
setup.pyを実行すると、上のようなエラーが表示されました。
http://d.hatena.ne.jp/ousttrue/20070531/1180556273
上記のサイトを見るとインクルードパスが通っていない場所に"basetsd.h"があるのが原因なので、"cygwin.bat"にインクルードパスの設定をしておきました。
call "%VS80COMNTOOLS%vsvars32.bat" set INCLUDE=C:\Program Files\Microsoft Platform SDK\Include;%INCLUDE%
link: extra operand `/INCREMENTAL:NO'
詳しくは `link --help' を実行して下さい.
これは、cygwinのほうのlink.exeが実行されてるのが原因でした。スマートな解決策ではありませんが、cygwinのほうのlink.exeをリネームして解決。パスの設定順序とかでどうにかできるといいんだけど、どうすればいいんかな。
MSVCR80.dllが見つからなかったため、このアプリケーションを開始できませんでした。アプリケーションをインストールし直すとこの問題は解決される場合があります。
SWIGが生成した.pyファイルをimportしたら、こんな感じのエラーダイアログが表示されたよ。うーん、困った!
http://d.hatena.ne.jp/moriyoshi/20070525
上記のページを参考にして、"%Pythonをインストールしたフォルダ%/python.exe.manifest"として以下のようなファイルを新しく作ったら、解決できました。ありがとうありがとう!
あとこれ、bashから実行したらエラーダイアログが表示されず、importするモジュールが見つからないみたいなエラーメッセージが出力されるだけだったよ。
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> </dependentAssembly> </dependency> </assembly>