『エンジニアのためのマネジメントキャリアパス』を読んだ

更新が滞っていました。リハビリとして今日読んだ本の感想を書きます。

www.oreilly.co.jp

本書は、技術系マネージャーとそれを目指すエンジニアに向けて、IT業界の管理職に求められるスキルを解説する書籍です。テックリードからCTOになった経験を持つ著者が、管理職についたエンジニアが歩むキャリアパスについて段階をおって紹介します。

特段昇進を熱望しているわけではないですが、プロジェクト単位でマネジメントしたりメンター的なことをしたりする日々の中で、マネージャの視点を体系的に読めそう、読みやすそう、評判が良さそうな本書に手を出しました。テックリードから始まり、章が進むに連れて徐々に広い範囲の役職について言及され、最後にはCTO、そして組織文化のマネジメントまでと、マネジメントキャリアのラダーにそって書かれています。

原著者のCamille Fournierさんは、Rent The Runwayというアメリカのベンチャー企業のCTOです。今年春に大型の資金調達をしていました

感想

「いいマネジメントとはどんなものか」や「上位のマネージャが何を考えているか(考えるべきか)」の一例をみることができました。著者の過去の失敗を開示していて、理想論に閉じず、かといって個別の事象にもよりすぎず、一般論を現実的にわかりやすく説明されていました。訳も自然で読みやすかったです。

また、実際にマネージメントをする人に限らず、マネジメントされる側の視点においても、「なんとなくやりにくい」と感じてモヤっている人や、逆に「いまのマネジメントにまったく不満がない」という人こそ一読の勝ちがあるかもしれません。課題が言語化され、自分がパフォーマンスを最大化する環境について考えるきっかけにもなりそうです。

自分はまず技術をがんばりますという気持ちになりました。

技術だいじ

マネージャの職位があがるにつれ、勤務時間に占めるコーディング時間は減っていきます。それでもなお、あくまでエンジニアのマネージャであるかぎりは小さくともコードを書き続けるべきだとし、また技術力不足でキャリアが頭打ちになるケースを実体験として挙げています。「まだ早いと思うなら引き受けるな、技術に専念せよ」という旨まで書いてあります。

職位が上がる、つまりマネジメントする対象が広がるに連れて、課題に対する抽象度が上がり、意識すべき責任範囲が広がるということです。技術に関する知識・理解の深さと対立するものではなく、(自分の体感としても)正の相関に近いのかもしれません。

オープンドアより1on1

メンバーとマネージャの間で、プロジェクトあるいはその他の相談、質問、議論のインターフェイスとして、オープンドアと1on1を対比して後者を推しています。オープンドアというのは、「いつでもなんでも聞いてOK」と門戸を開いておくスタイルで、1on1は、定期的にミーティングを設けるスタイルです。

オープンドアは一見なんとなく良さそうですが、エンジニアも人間なので、上司にネガティブな話をするのは心理的負担が少なからずあります。プロとして必要ならやるべきという考え方もあるかもしれません。でも、心理的負担は小さいに越したことないです。

三大美徳

エンジニアならだれもが知る、Larry Wall大先生が唱えた三大美徳「怠惰」「短気」「傲慢」についてです。これらがマネジメントにおいても有効だと説明されています。もちろん「短気=すぐに怒る」みたいなことではないです。プロジェクトに対して、「なるべく楽に、速く終わらせるにはどうすればいいか?」という視点を持つべきです。

行動規範として皆さんに今すぐ実践してほしいのが「今すぐ重要なことを見極める」と「帰宅する」なのです。(p.160)

パワープレイで問題を解決しようとしたり、考える前に行動して時間を無駄にすることは、当人にとってもマネージャにとっても会社にとっても望ましくないです。勤務時間という制約の中で最大の成果を出すことを目指し、そのために考え抜くのが知的労働におけるプロフェッショナリズムといえます。

好奇心を大切に

本書では一貫して、「好奇心を持て」と説かれています。「本書を通じて」というところが重要で、メンター、テックリードからCTOに至るまで、(少なくともエンジニアに対する)マネジメントのあらゆるフェーズで、好奇心が価値を持つとのことです。

メンターは、メンティーをサポートする立場ですが、逆にメンティーの視点を通して世界をみることで好奇心を刺激してもらう機会でもあります。メンティーの悩みをとおして組織の課題に気づいたり、質問をとおして自身の理解不足に気づくかもしれません。また、テックリード以上の職位においては、ある技術領域において自身よりもメンバーのほうが深い知識を持っていることが往々にしてあります。その場合に理解を諦めるのではなく、メンバーに時間をとってもらって教えてもらうなどでプロジェクトの計画精度を高めると同時に、エンジニアとしての成長機会にもなります。

参考

ググるといい書評がいっぱいでてきたので貼っておきます。このへんをみるとだいたい内容はわかります。さらに気になったら本を読んでみるといいと思います。

京都でレガシーシステムのはなしをした

2/22(金)にLegacy Meetup Kyotoで発表してきました。

speakerdeck.com

ここ1年くらいでやってきた、レガシーシステムの改善に関する3つのプロジェクトを紹介し、その過程で考えたことを少し整理してお話しました。レガシーシステムと相対する人類にとって少しでも参考になれば幸いです。

Q&A

懇親会でいくつか質問をいただきました。まともに話す時間もなく答えきれなかったものを、書いておいてみます。本人に届く可能性は極めて低くとも。

Q:受託開発の場合、顧客をどう説得するか?

自分は経験がなく想像もあまりできないのでわかりません。というと終了するので、想像で答えると、説得しなくてよいのではないでしょうか。どうしても説得したければ、説得に足る情報を集めて判断してもらえばよいのでは。発表の中にある「合意」に必ずしも正しさ・清さを包含しません。人間はわかりあえないという前提のもと、自分にとって都合がよく、かつ後々不利益を被らない情報を恣意的に提供すればいいと思います。

Q:巨大すぎる技術的負債にどう立ち向かうか?

立ち向かわなくてよいのではないでしょうか。疲れるし。どうしても立ち向かいたい理由があるなら、まずはどれくらい巨大かを把握しようとしてみては。本当に巨大だったら諦めもつくでしょう。意外とそんなに巨大ではないかもしれません。そしたらラッキーですね。

Q:技術的負債はまだ残っているのか?

個人ブログなので詳しくは書きませんが、言えるとすれば、今回の内容は「レガシーシステムの端の端の末端の端っこを少しなおしてみた」ということでしかないです。「コードは書いた瞬間から技術的負債になる」ってだれかが言ってました。

様子

会場は古き良き町家をリノベーションした建物です。リノベーションといっても、畳敷きの和室はそのままです。長机と座布団を並べたその空間は、寺子屋あるいは習字教室を彷彿とさせました。「皆様、足を崩して楽な姿勢でどうぞ…」のアナウンスをもって完全に法事と化しました。

発表者の立場としては、とても話しやすかったです。東京で社内/社外、お仕事/プライベートでいくつか発表をしたことがありますが、今回はとりわけ快適でした。勉強会のテーマが特定の技術によらないエンジニアリングの共通項だったことに加え、前述のとおりリラックスできる場の共有が少なからず寄与していると思います。初対面なのに内輪ともいうべき不思議な雰囲気でした。

他の登壇者の発表もおもしろかったです。ヤフーの山本さんの発表からは新たな技術や未知を楽しむ""つよさ""を感じましたし、はてなの id:t_kyt さんの発表からは並々ならぬ""やっていき""を感じました。資料は勉強会のconnpassページにリンクがあるので、ご興味ある方はそちらをどうぞ。

懇親会では各自のレガシーどうよみたいな話をできて、「みんな大変そう」という圧倒的に深い考察を得ました。おぢさんたちが和室に集ってレガシーシステムを追悼する様子は、まさに法事そのものでした。

余談

本題です。

勉強会が金曜だったので、翌日は京都をぶらぶらし、もう一泊してから帰りました。京都オヒス近辺(徒歩5分圏内)でお店を発掘しました。オススメ3選を共有します。使命感の為せる技です。

  • Weekenders Coffee : コーヒースタンド。パーキングの奥のほうに茶室みたいな外見の建物があります。自分が学生だったころは元田中にあったのが、移転したらしいです。
  • Tato : スペイン料理。ビールがたくさんあって、スペインの家庭料理が激ウマです。狭めの店内に、スタンディング席とテーブル席があります。店主が異常に陽気です。
  • OIL : バー。雑居ビルの奥の奥にあって心理障壁がすごいです。中は意外と広くてゆっくりできます。メニューがないわりに良心的なお値段です。

f:id:kyabatalian:20190302183524j:plain
Tatoで食べたパエリア

そのほか、高倉二条のラーメン、わたなべ横丁とかキセノンという定番立ち呑みから、翌日サウナの梅湯築地など、サブカル定番コースでまったりしました。

まとめ

なにも予定がなく、なにもやりたくないとき、ひとまず川にいける京都。最高。

『レガシーソフトウェア改善ガイド』を読んだ

本を読むと何かをやった気になってしまって良くないです。でも、新たな知識を得るのは楽しいです。娯楽だと思うことにします。

どんな本?

レガシーなソフトウェアを改善するためのガイドです。たぶん。

www.shoeisha.co.jp

著者はThe GuardianのSenior DeveloperであるChris Birchall氏。訳者の吉川邦夫さんという方は、元SEで現在は翻訳を主に手がけられているっぽいです。翻訳リストをみると心なしかMS周りの技術書に多く関わられているっぽいです。

おなじ翔泳社から出ているレガシーコード改善ガイドとシリーズ物かと思いきや、全然別物です*1

なぜ読んだのか

勤務先の技術ブログに、レガシーシステムの改善に関する記事を書きました。その中で本書を紹介していたのですが、その段階でまったく読んでいませんでした。まったく読んでいない本を紹介することに対し、一定の罪悪感が拭えなかったため、渋々読むことにしました。

上記の記事で書いたこと以外にもいわゆる技術的負債と言われる領域に手をつけていく中で、もうちょっとまじめに取り組んだほうがいいよなあ、という思いが強くなってきました。やってきたことやより大きな技術的負債に対してどう立ち向かっていくべきか、指針を得られればと思いました。また、前述の『レガシーコード改善ガイド』ではなくソフトウェアのほうを選んだのは、コードベースを改善するにはまずそれ以前にソフトウェア全体やその開発プロセスの土台が必要と感じているからです。富士山よりも高い意識。

感想など

3部構成になっており、それぞれ「なにが課題なのか」「どうやって解決するか」「そのための環境づくり」について言及されているように感じました。

まず、ソフトウェアの実装に関することは想像以上に、というかほぼ書かれていません。レガシーは人間から生まれるので、必然的にそうなるのかもしれません。ビッグリライトはやめとけ(意訳)とか、マイクロサービスに走るな(意訳)とか、安易にレガシーを正す主張を並べるのではなく、理路整然と価値ある判断ができるように導いてくれています。レガシーソフトウェアと対峙し感情が荒ぶりがちなエンジニアは、一度エディタを閉じて深呼吸し、帰宅して本書を一読することをおすすめします。

具体的なレガシーソフトウェアの例を示し、改善に至るまでの考え方をストーリー仕立て紹介されている箇所があり、大変わかりやすいです。「何がダメで、どうしたいのか、そうすると何が嬉しいのか」を、十分すぎるくらいに説明してくれます。知識を詰め込んだ技術書というよりは、読者にとって読みやすいように配慮されていると感じます。

最後の第3部では主に自動化を主眼に、いかにレガシーを生み出さないかに言及されています。その中で、Ansible、Vagrant、Jenkinsといった具体的なツールを使った環境整備が書かれています。このへんは疲れてきてあんまり読んでません。すみません。個人的には本書は第2部までで十分その価値を持つ、第3部は必要な人だけ読んだらいいという印象です。直近のお仕事でCIをがんばりたい所存なので、まあ、がんばろうという決意を新たにしました。

本書を通じて私は「レガシー」(legacy)を、何か悪い言葉のように扱ってきたが、そうする必要はない。望むと望まないとに関わらず、我々は次世代の開発者に遺産(legacy)を残すのだから、できるだけのことをして、誇らしい遺産にしよう。

やっていきましょう。以下ではときめいた箇所とそれぞれ思ふことをメモっておきます。

「負債」には「利子」がつく

技術的負債がやっかいなのは、ただ存在することがデメリットであることです。テストがなく仕様が曖昧なコードは、その周辺の挙動を知るために読み解く手間がかかります。また、設計が使用に沿わずレガシーとなったデータベーススキーマが存在すれば、それに適応するためにアプリケーションコードが必要以上に複雑になり、新たなレガシーを生み出します。レガシーなソフトウェアを放置すると、エンジニアや組織は利子を払い続けることになります。その意味において、技術的「負債」という言葉は、事象のメタファーとして非常に優れていると感じました。

レガシーカルチャをリファクタする

レガシー「ソフトウェア」というタイトルから、レガシーコードよりは広い領域だろうな、という想像をしていましたが、本書ではさらに開発プロセスや組織のカルチャにまで言及されています。レガシーなカルチャとして、「変化への畏怖」と「知識の孤立」を挙げています。それぞれについて、個別に取りうる方策を説明しています。使われていないはずのコードを消す恐怖を和らげるためにはアクセスログをみればいいですし、いま記録されていないならまずログを出すところが第一歩です。

本書では言及されていませんが、自分の経験からいうと、技術的負債の返却に対して、組織的・長期的なメリットだけでなく、個人のインセンティブとリスクを取れる文化が必要と感じます。新規開発のプロジェクトと比較して、ユーザよりも開発者にとっての課題のため、それに取り組むモチベーションが内発されにくいです。組織における評価者がソフトウェアの状況を理解し、長期的な価値をふまえた高度な評価をする必要があります。

まずは触ってみるしかない

この「未知への恐れ」を克服する最良の方法は、そのコードに飛び込んで、いじり始めることだ。

レガシーなソフトウェアをみた人間に内発されやすい感情として、「恐怖」と「フラストレーション」が挙げられています。自分の経験とも一致します。これらが開発効率やソフトウェアの品質にもたらす悪影響を評価することは極めて難しいですし、少なくとも定量化は困難と思われます。少なくともいい状態ではないのでなんとかしたいわけですが、なぜ自分が怖かったりイライラしたりするかと考えてみると、「知らないから」というのが多分にあります。なので、そのコードを読んで、何をやっているかを把握することが、解消に繋がります。

そのために本書では、「調査的リファクタリング」が紹介されています。何をやっているかを把握しながら、簡単なリファクタを進めていく、という手法です。人間の心理として調査自体は何かを生産している気にならずコストにみえますが、そのついでに少しでもソフトウェアを改善することで、ある意味で正当化できます。例えば、もう使っていないメソッドや参照を削除することでも、それが残り続けることに比べれば大きな前進です。まずは、小さなリファクタを始めましょう。使っていないクラス、メソッド、変数、参照をみつけたら、削除しましょう。

レガシーの源泉を紐解く

結局、最初は「醜悪な実装」に見えたコードが、実は「複雑な仕様」だった、という場合が多く、それについては、大きな改善が望めない。

複雑なコードが存在するとき、それが必要な複雑さなのかは考える必要があります。そもそもの仕様が複雑ならその実装が(エンジニアにとって)複雑であっても、妥当な複雑さです。さらに一段上のレイヤを考えて、実現したいことが複雑ならその仕様の複雑さも妥当です。ただし、ほとんどの場合、過剰な複雑さだと思います。その場合は、要件の掘り下げが足りていない可能性があります。その場合、リファクタすべきはコードではなく仕様です。

段階的にできるものはそうする

モノリスなアーキテクチャを運用するチームは、世の潮流と自身のギャップを感じ、「マイクロサービスにするぞ!」と士気が高まりがちです。しかしその間はとんでもない距離があり、いざやるとなると不相応にしんどいです。まずはフロントエンドとバックエンドを切りわける、その次にSOAに取り組む、その上でさらに必要ならマイクロサービスを検討する、というふうに進めていけるはずですし、ほとんどのケースでマイクロサービスまでやる必要はないはずです。「マイクロサービス化」を目的としてしまうと、本来の課題が解決できない恐れがあります。

また別の観点として、機能の改善とリファクタリングは切り分けるのが定石です。機能をなおしてからリファクタするのか、リファクタしてから機能をなおすのか、どちらになるかはプロジェクトの性質に依存しますが、いずれにしても同時にやるべきでないことは確かです。

すべてはユーザのため

最も重要なのは(コードについて言えることの、どれよりも、はるかに重要なのは)ユーザーにとって価値のあるソフトウェアを作ることだ。

技術的負債が負債たりうるのは、ユーザに害があるからです。エンジニアがストレスを感じ、必要以上に時間を浪費し、開発速度が落ちて新たな価値を届ける速度が落ちます。また、バグの温床にもなります。ユーザのために技術的負債を返却せねば。

*1:原著のタイトルはそれぞれ"Working Effectively With Legacy Code"と"Re-engineering Legacy Software"であり、出版社も異なる

PostgreSQLアンカンファレンスに参加した

あと発表もしました。ので日記を書きます。

pgunconf.connpass.com

日記

人の話をまったく聞けない人間なので、勉強会は基本的に発表目的あるいは発表ドリブン学習目的で参加することにしています。ただ、今回は諸々が立て込んでおり発表を諦めていました。

PostgreSQLアンカンファレンスは、「会場の入口に空のタイムテーブルが張り出され、参加者がその枠内に付箋で発表内容を貼り付ける」というスタイルでコンテンツが決まっていきます。

参加者の割に枠がけっこう空いていたのと、まあせっかく来たしっていうのと、いまから自分を追い込んだら発表までいけるのでは?というゲーマー精神により、とりあえず付箋を貼っつけました。

そこから2時間くらいで資料を作成しました*1。内容は、昨年のPostgreSQLアドベントカレンダーに書いた以下の記事をベースに、宣伝とかを散りばめました。

kyabatalian.hatenablog.com

ディスプレイケーブルの不調などありつつも(手間取ってごめんなさい)、なんとか発表は無事に終わりました。強いエンジニアの方々からご質問やご意見をいくつもいただきました。PostgreSQLの実装にまで食い込んだ議論になり、楽しかったです。ありがとうございました。

最後のセッションでは、参加者がこれまでに遭遇したクソ趣のあるクエリを共有してみんなで解決策を考える、という会が催されていました。アンカンファレンスとは別かもしれませんが、これはこれで独立した会としてあってもおもしろそうと思いました。

終了後には懇親会があったのですが、持ち前のコミュ障を遺憾なく発揮して、普通に帰宅しました。次回もしあればがんばって参加できるようにコミュ力を鍛えておきます。

ふりかえり

勢いで発表してよかったです。人前で話すのが苦手なのでよい経験になりましたし、強いエンジニアの方々と議論もできました。発表のハードルを下げることにも寄与できたと思います。

一方で、やっぱりちゃんと準備せなアカンと思いました。まず前半はスライドづくりに必死で、他の方の発表をまともに聞けていないです。すみません。また、資料の推敲や発表練習などもできておらず、全体的に荒くなってしまっていたと思います。内容としても勉強不足を感じました。発表するにしても目的とそれに応じた準備期間を設計すべきでした。承認欲求と人生に対する焦りからか、アウトプットに意識が寄りすぎていました。勉強します。

発表を聞いてくれた方、コメントしてくれた方、運営のみなさま、ありがとうございました!!!

*1:あえて公開はナシで

『エンジニアの知的生産術』を読んだ

意識高そうな本を読んで意識が高まったので書いています。たぶん寝て起きたらもとに戻っています。

どんな本か

gihyo.jp

仕事をするうえで,どのように学び,整理し,アウトプットするのか。ソフトウェアエンジニア向けに,プログラミングと執筆を具体例として,知的生産の方法を解説した書籍です。

とのこと。著者は西尾泰和さんという方で、現在はサイボウズ・ラボにお勤めで、コーディングを支える技術の著者でもあります。平たく言ってめっちゃデキる人間のようです。昨年8月に発売され、かなり話題になっていました。

なぜ読んだか

知的な生産性をあげたいからです。自分はオッサンに分類される年齢ですが、エンジニアを名乗るにはあまりに能力が足りないと自覚しており、やるべきこと、やりたいことが山積みです。それらを愚直にやっていくには人生が足りなさすぎますし、若者たちに淘汰されて終了しそうです。本書は特にエンジニア向けに書かれているとのことで、目次をチラ見してこれはイイゾとなったので読みました。

読んでどうだったか

良かったです。どこかでみたことあるような…という内容も多い気がするものの、ある程度学術的に意味のあるリファレンスと紐付いて各手法が紹介されています。また、著者が本書を書くにあたって実践した内容もあわせて紹介されており、読みやすく有益な内容にまとまっています。とはいえ、これらを実践していかないと意味がないです。ついついこういう意識高い本を読んで満足しがちなダメ人間なので、今回こそ実践していきたい気持ちでいっぱいです。

以下、印象に残った箇所のメモや感想など。

やる気のでるタスクを設計する

知的生産性の研究者である著者が、学習のサイクルを回す原動力を「やる気」というエモい言葉で表現しているのが印象的でした。その上で、脳に報酬を与えてやる気を維持するタスク設計について理路整然と書かれています。

明確な目標設定が重要です。例えば「Pythonをマスターする」とか「DDDを理解する」というのは曖昧な目標であり、やる気を阻害します。仕事など必要に迫られるのがベストですが、そうではない場合にも「ブログを書く」「人に説明する」など、アウトプットという形で達成したか否かが計測可能な目標を設定します。ここで、目標自体が大きい場合、さらに分割します。例えば、「○○という本を読んで得た知識をブログに書く」という目標の前段階として、「得た知識を付箋に100枚書き出す」という過程の目標を置きます。これがいいのは、タスクが小さいことと中断可能なことです。このように、やる気を維持するには、「達成したいこと」に対して、闇雲に向かうのではなく、タスク設計をちゃんとやる必要があります。

自分がよくやってしまうのは、「○○を検討する」とか「○○を整理する」みたいな、達成点が曖昧なことをぼんやり頭に残っている状態です。信じられないくらい進捗が無になります。時間で区切ったり、だれかに説明したり、社内共有のドキュメントにまとめたり、なるべく具体化する作業をやるべきです。頭ではわかっていますが、それ自体がだるかったりします。ちゃんとやります。

全体像を把握する

技術書を普通に通読するとかなりの時間がかかります。そこでボトルネックとなっているのは、ページ送りや目の動きではなく、脳の理解であり、さらには「理解の組み立て」です。この組み立てを効率よく行うために、まず目次を把握するという方法や、ページをパラパラと読んでキーワードを抜き出す、など、全体を把握する読み方が有効だとしています。これはコードを読む場合も同じで、READMEやドキュメントを読み、ディレクトリ構造を把握してからコードを読んだほうが効率的です。自分も本に応じて、また読書の目的に応じて、読み方を変えたいです。すぐ通読しようとしてしまいます。グッと堪えます。

自分は小~中学生のころけっこう本を読む人間でしたし、その後も主に小説を好んで読んでいたりして、通読するクセみたいなものがついている気がします。あと、脳が負荷を避けているのもありそうです。目次を読んで頭に入れたり内容を想像するのは、トータルでみると効率を上げるはずですが、思考疲れというか、文字を追うだけの読書に逃げている感覚です。その意味で、学習のための読書はかなり消耗することを自覚し、ちゃんと休みましょう。

いったんぜんぶ書き出す

「GTD」というメソッドが紹介されています。この文字列はどこかでみたことがあったのですが、内容は初めて知りました。Getting Things Doneです。「やる気が出ない人の65%はタスクを1つに絞れていない」らしいです。わかる。人間の脳はマルチタスクができないように作られていないみたいですし、自分は特にそうです。コンテキストスイッチは想像以上に消耗します。タスクを絞るためには全体を把握します。

GTDはDavid Allenというひとが開発したメソッドで、なんと日本版公式サイトもあります。概要はそちらをどうぞ。超絶雑にいうと、「いま気になっていることを全部書きだし、それを上から順番にやっていく」です。一般的なタスク管理と違うのは、「タスクかどうかにかかわらず気になることを全部書く」という点と、「優先順位をつけない」という点です。それら自体が重い作業なので、放棄する、というものです。

タスク管理はそれ自体が目的になって、きちんとやりたくなってしまいますが、そこにかけるコストを自覚してバランスをとっていきたいです。タスク管理をあまりがんばらないようにします。仕事ではいまはAsanaを使っています。一日の頭にタスクを整理する時間をとっています。この前段階としてGTDをやる時間をとってもいいかもと思いました。

不確かなときは楽観的に

GTDで優先順位をつけないとはいえ、現実にはそれぞれのタスクには時間的な制約があり、優先順位をつけざるを得ない場面がほとんどです。優先順位付けというタスクが重いのは、不確定要素のためです。「不確かなときは楽観的に」というのは、ポジティブバンザイ脳ではなく、ちゃんとした根拠があります。強化学習の領域だと「探索と利用のトレードオフ」と言われたりしますが、超絶雑には以下のとおりで、2つの勘違いは対称ではない(悲観的な勘違いのほうが深刻)ということです。

  • 楽観的な勘違い:実際に行動するため、結果をみて悪い選択だと気づける
  • 悲観的な勘違い:その選択をしないため、結果が得られず悪い選択だと気づけない

とはいえ、不確かさがなるべくない状態での判断が一番確実で負荷も少ないため、なるべく不確かさを減らす努力もするべきかもしれません。

記憶のために知識を使う

人間の脳の記憶は、よくコンピュータの記憶媒体に例えられるためか、「ファイルを保存」みたいなイメージを持ちがちです。ところが実際はむしろ、筋力トレーニングに近いらしいです。つまり、単一の知識についてインプットとアウトプットを複数回おこなうことにより、記憶が定着していきます。

人間の脳に海馬という部位があります。この中にあるニューロンという神経細胞で起こる、長期増強という現象が、記憶を司っていると言われています。その内容についてはWikipediaとかをみればいいとおもいます。重要なのは、「記憶は繰り返し使うことで増強される」ということです。とにかくアウトプットです。復習のためのテストを自分で作りそれを解くことをオススメされています。AdaBoost的な発想です。

モチベーション的にも記憶的にも、「必要なことを学ぶ」と、必然的にアウトプットするので、学習の効率がよさそうです。遠い将来を追いかけるよりもまず目先の課題と向き合おうと思いました。ごめんなさい。必要に応じて学んだ知識を体系化してまとめておくことも自分には必要だと思いました。本書でいうところの「復習のための教材をつくる」的なことです。本を読んだり、技術的な何かをやったら、咀嚼・言語化してブログに書きます。自分のために。

手作りで温もりのあるMSBuildプロジェクト

あけましておめでとうございます。

最小限のMSBuildプロジェクトファイルをテキストエディタで書いてみる回です。本当に知りたい方はこれを読むより公式ドキュメントのチュートリアルを読んでもらうのが一番いいです。おつかれさまでした。

MSBuildとは

The Microsoft Build Engine is a platform for building applications. This engine, which is also known as MSBuild, provides an XML schema for a project file that controls how the build platform processes and builds software. Visual Studio uses MSBuild, but it doesn't depend on Visual Studio. By invoking msbuild.exe on your project or solution file, you can orchestrate and build products in environments where Visual Studio isn't installed.

MSBuild - Visual Studio | Microsoft Docs

ということで、アプリケーションをビルドするためのMicrosoft製のエンジンです。.NET Framework 2.0から同梱されていて、それまで使われていたNMakeの.NET Framework版みたいなもんです*1

.NET Framework 1系までは、Visual Studioでのビルドは、IDE組み込みのdevenv.exeがビルドしている一方、コマンドラインからのビルドはcsc.exeやvbc.exeを直接使っていました。コンパイラオプションを指定するのが大変だったり、ビルド以外の処理が複雑でした。これらをまとめてスクリプト化したのがMSBuild及びプロジェクトファイルです。

例えば、Visual Studioで作ったプロジェクトをJenkinsなどのCIツールでもビルドしたいとき、そのままプロジェクトファイル(.csprojとか)を入力にしてMSBuild.exeを実行すれば同様の成果物が生成されます。便利ですね。

Why 手作り

前述のとおり、通常?はVisual Studio様がご創造なされますが、細々とした設定をしたいときや、ビルド環境によって切り替えたいとき、またコンソール実行で設定を渡したいときなど、けっこう触る機会があります。少しでも手を出そうとすると、結局MSBuildが何をするかを把握しておかないといけません。こういう場合、往々にして既存のプロジェクトファイルをいじるところから始めてしまって結局無為な時間を過ごしてしまいがちです。でした。私が。

主にプロパティ、項目、ターゲット、タスクという独特な概念を理解する必要があります。ドキュメントを読んで理解できるならそれで十分ですが、実際に動かすのが一番だと思います。のでやってみた次第です。

Let's 手作り

あえてテキストファイルでプロジェクトファイルを作ってみます。MSBuildでビルドする最小限からはじめて、少し遊んでみます。OSはmac OS Mojave 10.14、MSBuildは15.6.0.0ですが、超基本的なことしかやってないので、各自の環境でも再現できると思います。

最小構成でMSBuild

最小限のC#のコードを書きます。ファイル名を helloworld.cs とします。

using System;

class HelloWorld  
{  
    static void Main()  
    {
        Console.WriteLine("Hello, world!");  
    }
}

最小限のプロジェクトファイルを書きます。ファイル名は Helloworld.proj とします。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Compile Include="helloworld.cs" />
  </ItemGroup>
  <Target Name="Build">
    <Csc Sources="@(Compile)"/>
  </Target>
</Project>

XMLで記述します。根本は <Project> 要素です。 <ItemGroup> 要素は、MSBuildへの入力となるファイルを指定します。ここでは helloworld.cs というファイルを、Compileという種類のItem(=項目)にIncludeしています。 <Target> 要素は、MSBuildが順次実行する処理(タスク)をまとめたものです。Targetの名前をBuildとしています。BuildというTargetを実行すると、配下のタスクが実行されます。ここでは、 Cscタスクに対してCompileというItemを渡しており、ItemGroupで指定したhelloworld.csのみが渡されます。Cscタスクはcsc.exeをラップしており、実際のビルド処理はこのタスクが行います。

この状態で、MSBuildを実行します。 -t スイッチでTargetを指定します。

$ msbuild Helloworld.csproj -t:Build
Microsoft (R) Build Engine version 15.6.0.0 (xplat-master/ca830585 Sun Mar 25 19:24:09 EDT 2018) for Mono
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 1/5/2019 9:50:17 PM.
Project "/Dev/msbuild/HelloWorld/Helloworld.csproj" on node 1 (Build target(s)).
Build:
  /Library/Frameworks/Mono.framework/Versions/5.10.1/lib/mono/msbuild/15.0/bin/Roslyn/csc.exe /out:helloworld.exe helloworld.cs
Done Building Project "/Dev/msbuild/HelloWorld/Helloworld.csproj" (Build target(s)).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.01

これでhelloworld.exeが出力され、実行できます。これで最低限のビルドができます。Visual Studioが自動生成するプロジェクトファイルに比べるとかなりシンプルです。

ビルドプロパティの追加

最低限のビルドはできるようになったので、もう少し細かい制御をしてみます。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>  
   <AssemblyName>MSBuildSample</AssemblyName>  
    <OutputPath>Bin\</OutputPath>  
  </PropertyGroup>  
  <ItemGroup>
    <Compile Include="helloworld.cs" />
  </ItemGroup>
  <Target Name="Build">
    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
  </Target>
</Project>

<PropertyGroup> 要素は各種のプロパティを設定します。ここでは、出力するアセンブリ名と出力先のディレクトリを指定しています。合わせてBuildターゲットにおいて、Cscタスクの前に出力ディレクトリの作成と、Cscタスクにおいて出力アセンブリ名を指定しています。

この状態でMSBuildを実行すると、 Binディレクトリが作成され、その配下にMSBuildSample.exeが作成されます。

ビルドターゲットの追加

Build以外に、CleanとRebuildというターゲットを追加します。また、プロジェクトのデフォルトのターゲットを指定します。

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <AssemblyName>MSBuildSample</AssemblyName>  
    <OutputPath>Bin\</OutputPath>  
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="helloworld.cs" />  
  </ItemGroup>
  <Target Name="Build">
    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
  </Target>
  <Target Name="Clean" >  
    <Delete Files="$(OutputPath)$(AssemblyName).exe" />  
  </Target>
  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />  
</Project>

Cleanターゲットでは、Deleteタスクを用い、Buildターゲットで生成したアセンブリを削除します。RebuildターゲットはCleanとBuildのターゲットをこの順序で実行します。

この状態でCleanターゲットを実行してみます。

$ msbuild Helloworld.csproj -t:Clean
Microsoft (R) Build Engine version 15.6.0.0 (xplat-master/ca830585 Sun Mar 25 19:24:09 EDT 2018) for Mono
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 1/5/2019 10:21:19 PM.
Project "/Dev/msbuild/HelloWorld/Helloworld.csproj" on node 1 (Clean target(s)).
Clean:
  Deleting file "Bin/MSBuildSample.exe".
Done Building Project "/Dev/msbuild/HelloWorld/Helloworld.csproj" (Clean target(s)).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.42

Bin下のMSBuildSample.exeが削除されています。また、MSBuildを-tスイッチなしで実行すると再度MSBuildSample.exeが作成されます。

インクリメンタルビルド

ターゲットが依存しているファイルのタイムスタンプを見て、変更があった場合にのみビルドします。BuildターゲットにInputsとOutputsを指定します。

  <Target Name="Build" Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe">>
    <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
    <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
  </Target>

この状態で msbuild -v:d を実行します。ビルドの詳細を出力するスイッチをしています。

Skipping target "Build" because all output files are up-to-date with respect to the input files.
Input files: helloworld.cs
Output files: Bin/MSBuildSample.exe

入力ファイルhelloworld.csに変更がないので、Buildターゲットがスキップされています。

ビルドしない

ここまでくるとわかるかと思いますが、上記のプロジェクトにおいて、実際にビルドを実行しているのは結局Cscタスクであり、その前後は付随する処理でしかありません。つまり、MSBuildが行うのはビルドだけでなくその前後を含めたプロセスといってよさそうです。ビルドしないMSBuildプロジェクトもありえます。

例として、まったく意味のないプロジェクトを作ってみます。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="Greeting">
    <Message Text="Hello" Importance="low" />
    <Message Text="World" />
    <Message Text="!!!!!" Importance="high" />
  </Target>
  <Target Name="Copy">
    <Touch Files="File1.cs;File2.cs" AlwaysCreate="true" />
    <Copy SourceFiles="File1.cs" DestinationFolder="Bin\" />
  </Target>
</Project>

GreetingターゲットとCopyターゲットの2つがあります。まずGreetingターゲットは、Messageタスクを使って、文字列を出力するだけです。実行してみます。

$ msbuild NoBuild.csproj -t:Greeting -v:d
(略)
Target "Greeting" in project "/Dev/msbuild/HelloWorld/NoBuild.csproj" (entry point):
Using "Message" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
Task "Message"
  Hello
Done executing task "Message".
Task "Message"
  World
Done executing task "Message".
Task "Message"
  !!!!!
Done executing task "Message".
Done building target "Greeting" in project "NoBuild.csproj".
Done Building Project "/Dev/msbuild/HelloWorld/NoBuild.csproj" (Greeting target(s)).
(略)

「Hello」「World」「!!!!!」が出力されています。HelloはImportanceがlowなので、 -v:dオプションがないと出力されません。

次に、Copyターゲットを実行してみます。Touchタスクを使ってFile1.csとFile2.csを作成した上で、CopyタスクでFile1.csをBin配下にコピーします。

$ msbuild NoBuild.csproj -t:Copy
(略)
Project "/Dev/msbuild/HelloWorld/NoBuild.csproj" on node 1 (Copy target(s)).
Copy:
  Touching "File1.cs".
  Touching "File2.cs".
  Copying file from "File1.cs" to "Bin/File1.cs".
Done Building Project "/Dev/msbuild/HelloWorld/NoBuild.csproj" (COpy target(s)).
(略)

まとめ

MSBuildプロジェクトファイルを0から手で書いてみました。ほとんど公式チュートリアルの丸パクリです。本年度のブログのハードルを下げていく方針なので大成功です。

Visual Studioを使って普通に開発を進めていくと気づいたらプロジェクトファイルが巨大になっていて面くらいがちです。でもやっていることは単純なことがわかります。基本的に手で書くものではないですが、上記内容くらいは知っておいて損はない気がします。他にもいろいろなタスクがあったり、条件指定ができたり、細かい制御ができます。そのあたりはぜひリファレンスを参照ください。

*1:MSBuildの開発コード名は「XMake」でした

2018年の振り返り

帰省中です。雪だし寒いしもうダメです。

2018年の振り返り

技術ブログ

このブログだと、2018年は技術関係のエントリが5本だけでした。残念の極みです。2019年は5000本くらい書きたいです。また、勤務先の公式ブログに記事を書きました*1。はてブのホットエントリになった、ということを聞きました。そこそこ褒めてもらえたので、たぶんいいことなのだと思います。

勉強会

技術勉強会は発表側にならないと何も学ばず時間を浪費してしまう自覚があるので、だいたい発表前提で参加します。2018年は勉強会自体にほとんど参加しませんでした。ただ、こちらも初めて勤務先オフィシャルな場で社員として登壇しました*2。中身は課題だらけ過ぎて忘れたいです。

技術書典

ノリで応募して勉強しながら書きすすめましたが、結果的に楽しく充実した体験ができました。BOOTHにも出品しており、現時点で126冊のご購入をいただいております。ありがとうございます。次回は春頃に開催されるはずです。一般参加よりもサークル参加を強くおすすめします*3

kyabatalian.hatenablog.com

扁桃切除手術

扁桃切除の手術をうけるため、10日間の入院をしました。以降、扁桃炎にはなっていないのですが、手術による改善はまあそれほど体感できていません。食べ物が飲み込みやすくなったような気がします。入院中にキングダムを読破し、中華統一への思いが高まりました。

kyabatalian.hatenablog.com

旅行

宿泊を伴う観光でいうと、京都と石川に行きました。京都へはGWと夏(祇園祭の直前頃)の2回行きました。常に最高です。石川は和倉温泉に行きました。技術書典の前日かつ台風が来ていて怖かったです。こちらも最高でした。2019年は海外に行きたいです。

kyabatalian.hatenablog.com

お笑い

趣味です。2018年は主にド地下のライブに足繁く通っていたのですが、2019年はわりとメジャーどころも観に行くようになりました。推しの単独ライブ、最高でした*4。直接みにいったライブに限らず、キングオブコントやM-1グランプリも楽しみました。2018年の私的ベストは、5月にルミネでみた、かまいたちの漫才でした。異次元の面白さでした。

kyabatalian.hatenablog.com

人生

このブログを書くにあたり、1年間のツイートをさかのぼってみたところ、前半はかなりつらそうでした。お仕事がしんとかったのか、何かあったのだと思うのですが、まったく思い出せないので、人生そんなものなのかもしれません。後半は今後の人生について考える機運が高まり、それはそれでハードでした。2019年は行動にうつしていきたいです。

2019年の抱負

技術をちゃんとやります。自分がもし第三者だったらいまの自分をみて「いいから黙ってコード書けよ」と言いたくなりそうなので黙ってコード書きます。

そのためには健康第一です。来年もよろしくおねがいします。良いお年を。