はてなキーワード: Dependencyとは
研究者たちは、まず*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>