What makes a good engineering culture? http://www.theeffectiveengineer.com/blog/what-makes-a-good-engineering-culture よいまとめ。こういう文化を築くことを実践したいものだ。
あと、「3. Build the right software abstractions」で、(我々の翻訳した)“Software Abstractions” (邦訳: 『抽象によるソフトウェア設計』) から正しい抽象化の重要性が引用されていた。
“Pick the right ones, and programming will flow naturally from design; modules will have small and simple interfaces; and new functionality will more likely fit in without extensive reorganization. Pick the wrong ones, and programming will be a series of nasty surprises: interfaces will become baroque and clumsy as they are forced to accommodate unanticipated interactions, and even the simplest of changes will be hard to make.”
邦訳:
「抽象化を適切に行えば、設計から自然に流れるようにプログラミングを行える。モジュールは単純明解なインタフェースを持ち、新しい機能を大規模な再編なしに組み込めるだろう。適切でない場合、プログラミングは不快な驚きの連続になる。予想外の相互作用に適合させるためにゆがんだ不自然なインタフェースになり、ちょっとした変更も簡単にはできない。」
Software Abstractions: Logic, Language, and Analysis
http://www.amazon.co.jp/dp/0262017156
抽象によるソフトウェア設計−Alloyではじめる形式手法−
http://www.amazon.co.jp/dp/4274068587
正しいコードに向かってリファクタリングをしていく事で、正しい設計に辿り着く、というのが設計とコーディングの典型的な関係と思うのですが。
ただ、既存コードのリファクタリングの場合にしても、より良いと思う設計を実現するためにリファクタリングをするわけで、その設計が適切な抽象化に基づいていることが重要であり、適切でない場合にプログラミングが困難になる、という点では変わらないと思います。
自分の場合リファクタリングを行う時にはだいたいゴールは無くて、なんか嫌な感じがする所をリファクタリングブラウザでいじったりundoしたりの試行錯誤すると、たまに「スポッ」ときっちりはまる感じになる、このハマる感じを積み重ねると設計が決まり、どういう抽象化が行われるかが決まる、というのが通常のフローです。
考えてから手を動かすのでは無くて、適当にマウスで突付いて結果を幾つか見てから考えてます。
プログラミングという営みの中には良い抽象を選ぶという事が含まれてして、しかもそれはとても大きな領分を占めていて、それをプログラミングから切り離す事は出来ないんじゃないか。
抽象の選択を固定してプログラミング側だけを動かす、というのはおかしいような気がします。そのプログラミングとはなんぞや!?
ただ、私の場合、リファクタリングでは「このモジュールがこのモジュールの機能を直接利用しているのはまずいから、別のモジュールの機能を拡充してそっち経由で利用するようにしよう」とか、「この機能は使い勝手が悪いけれど、ある機能と別の機能の組合せに分解すれば、直行的・汎用的で使い勝手がよくなりそうだ」みたいなの漠然としたゴールイメージの設計はあって、それを実現するために各所を順に書き換えていくみたいなことも多いです。
たしかに、プログラミング言語は設計や抽象を試行・探索するための最良の言語でもあるべきだと思うのだけれど、現実の言語はそこまで良く出来てはいなくて、上記のようなことを考える際にはプログラミングに先行して設計を別途考えている気がします。
自分の考えではかなり前、VS2008のあたりでは、既に順序は逆転していて、それは7年とかの遠い昔という認識です。
当時はそれは一般的という程では無かったけれど、今はあれから7年も経っていて、その議論は既に片付いた、と思っています。
この七年間で、それを前提として、それからかなりいろいろ進歩している、という認識でいますが、ここ数年の進歩はキャッチアップしていないので私は知らない、、、
コード生成とリファクタリングブラウザ回りの一連の進歩の結果、プログラムとはコードを書く物では無くなった。
プログラミングとは、ロジカルにはIDEに複数の実装を生成させてみて、その中から良い物を選ぶ、というアクティビティに変わった。
この内、いまや前半の「IDEに複数の実装を生成させる」という部分は、プログラミングというアクティビティでは無くなった。
だから現在のプログラミングは、概念的には「複数の実装の中から良い実装を選ぶ物」つまり選ぶ事がプログラムとなっている。
良い実装を選ぶと、当然以後のプログラミングは容易になりバグも少なくなります。
実装の中には概念の理解の表現の様々な方法が含まれ、それらの理解の表現同士を比較、選択を積み重ねる事で、理解自身が進み、またその表現自体も深化する。
これが良い設計という物、という理解です。
良い設計を選ぶと、設計から流れるようにプログラミングが行える、というのは、自分の知る現代のプログラミングとは大分実態が異なると感じます。
深化した理解へと至る過程こそがプログラミングというアクティビティだと思っています。
特に、純粋にコードをどう組織化するかというレベルでだけでなく、どのような抽象化を行うかといった、より抽象度の高いレベルでもそれができるとしたら、だいぶ未来感があります。
引用元の“Software Abstractions”でも、こないだのAmazonの形式手法適用事例 https://plus.google.com/+MasahiroSakai/posts/gVCSHAvHDW9 でも、「コードは実行したりテスト出来るという利点がある一方で、設計を検討するには着目したい側面以外の詳細があまりにも多すぎて、本質が埋もれてしまう。それに対して、文章や図表による設計では、着目したい側面以外を捨象して本質に集中できるが、一方で意味論が明確に定義されておらず、動かしたり自動検証したりしながら試行錯誤したりができない」という問題に対して、コードよりは抽象度が高いけれど、ちゃんと意味論が明確に定義されていて、かつ動かしたり自動検証したりしながら試行錯誤できる設計記述言語としてAlloyやTLA+を導入しているのですが、もしIDEの支援によってコードレベルでそういった試行錯誤ができるとしたら、前提が変わってきますね。
C# は十分に抽象的な記述が出来る、という訳では無い。
だから形式言語の価値は理論上はある。
ただ、二つの言語(自然言語含む)の二重のメンテナンス、及び自然言語は統一的な変更に対するIDE補助が無い事から、少し実装の詳細が含まれてもC# 一本にするのが、3.0以降は勝ったと思っています。
特に自然言語は変更にあまりにも弱いので、使われなくなったという理解。
少なくともMS社内では自然言語のスペックは消滅しました。(1ページスペックというのが代りに生まれたが、これはまた別物)
IDEの支援、と一言で言ってしまうといろいろと詳細が省かれて問題があるような気もします。
例えば2005年の時点でもリファクタリングブラウザはあったし、インテリセンス等もあった。
でもこの時点ではコーディングは従来の延長で行われていて、多くの人は探索的には書いてなかった。
2005年から2008年までの三年間はたくさんの事が起こり、その集大成としてアクティビティの内容自体が変わっています。
例えばC# 2.0と C#3.0のちがいは凄く大きい。
個々の機能はなんて事無いのだけれど、全てがIDEの力を最大限発揮するように作られているので、探索空間が劇的に広がった。
そしてIDE側でも探索空間を広げる様々な改善が行われて、結果として小規模なクラス内などの探索だけじゃなく、中規模な構造も探索的に行われるようになった。
また構造の学習方法も、あらかじめ固定的な物を学んでおく形式からIDEが構造をリアルタイムで教えてくれるように変わり、大規模で継続的な変更に対して他のプログラマが対応出来るようになった。
そして中規模の構造がどんどん変わるようになると、大規模な構造の捉え方も以前とは別物になった、と思ってます。
この一定のしきい値を超えたかどうか、は割と重要で、それが2004年前後の型付きIDEの革命と2008年あたり以後のその上の第二の革命的な物を分ける大きな違いと思います。
C# 2.0世代と3.0世代の違いと言っても良い(この辺は全部くっついてるので分けられない)
2008年で結論は出たけれど、2010年にもう決定的になった、という認識です(だいたいVSのバージョンに対応)。
この探索的な活動は他の言語、特にC++の大規模開発やJavaに逆輸入されて、広く行われるようになった、と思ってます。少なくともG社のブラウザ系の人たちと話すと、彼らはかなり探索的にリファクタリングをしている。
IDEや言語の抽象性は不十分でも、人月を突っ込んで気合で真似してる、というのが自分の理解です。
少なくともJavaとAndroid Studioはかなり貧弱だけれど、その形態で自分は開発してて、回りも当然そうだ、と思ってました(これは本当か確認する必要はあるかも)
なんにせよ、2005年は10年前です。
今更2005年のIDEを基準にするのは無しなんじゃないか。
* 私としてはサーバ側とクライアント側でどう処理を振るのかとか、そこでプロトコルをどのへんに落とし込むか、みたいなところも探索的な設計(粘土こねこね)でやる感覚なんですが、最近のIDEってそこまでやってくれるんでしょうか。ならすごいな。
* 最近Chromiumいじっててあの規模をC++でやるのは人間の脳内キャッシュに収まる量を越えてるんじゃないか、理想的にはもうちょいましな言語をデザインしてその上に書くのがいいけど歴史的コードベースがあるから仕方なくあれでやってるんじゃないか、なんて思ってたんですが、実は中の人はIDEの支援でばりばり書いててもう脳内キャッシュに全部収める必要なんてなくなってるんですかね。
* IDEが生成してくれるもの、って、生成されるべきパターンがわかってるものなんじゃないかな、そのメタなところがわからない場合はどうなのかな、なんて思うんですがそのあたりは使って見ないとわからんですかね。ともかく旧来のエディタの感覚でやろうとするとIDEと衝突することが多いので、多分やり方をがらりと変えないとならないんだろう、と思いつつ、結局編集はEmacsでやってコンパイルとデバッグだけIDE使うような中途半端なことをしています。
なんとなくIDEの認識が10年以上前の物のような気が。
太古の昔、ATLとかでウィザードが死ぬほどコードを自動生成して、自動生成すげー、とか言ってた時代がありました。
でも、実際には全然つかいものになりませんでした。
これが何故ダメだったのか、というのはShiroさんの言ってる事に近い気がする。
結局コードの量が多いのは本質的な問題で、それが自動生成されても複雑さは解決されない。
そして自動生成は想定されてる物と違うコードは吐けない。
という事で自動生成はやめて、コード自体の量を少なくする方向に行きました。
これがC#2.0。
その後、型を認識してリファクタリングとかインテリセンスとかすげー、という発明があった。VS2005、十年前です。
2005年の革命とそれ以前の違いは、2005年の物は基本的には一字一句残らずユーザーの制御下にコードが書けた事です。
でもタイプ数は1/20くらいになった。
そしてこれは物凄く賢い入力補助でした。
入力補助なので、基本的には全て意図したコードしか出てこない。
勝手には一文字も書いてくれない。
で、この10年前の時点でもかなり革命的な事だったけれど、今となってはこんなのemacsに毛が生えた程度。
その後、言語とライブラリとプログラマがIDEに最適化される、という事が三年くらいかけて起こった。(C# 3.0)
2008年くらい。
そこからはみ出た物をその後数年かけて潰した(Rxとか)。ここは自分はバックパッカーになってリアルタイムで参加してないので多くは語れない。
その先の事はキャッチアップしてないので知りません。
で、話を戻してC# 3.0世代。
この頃から、プログラマは自分の書くコードを知らなくなった。
その代わりプログラマが「なるほど、これが俺の書きたかったコードなのか」というのをIDEから教えてもらうようになった。
といっても人工知能とかがある訳では無い。
ちゃんと説明するのは難しいけれど、従来のプログラミングでも書いていく過程で曖昧だったのがはっきりして、「これじゃダメじゃん!」とか気づく事はあったと思うけれど、あれが凄い広い範囲に拡大して、大部分を教えてもらう感じになった。
grepとかを見ながら考えるのが凄まじく発展した感じで、自分の考える力を一時的に数倍にしてくれる。
ただそんな事は、IDEの機能だけを評価しても、信じられない。
何故ならこれは、IDEだけで達成する事じゃないから。
言語とライブラリもそうなるように直した。
人間の側も足りない部分をヒント情報として提供してやるようになった、また必要無い事をあえて考えないでIDEに任せて、その分IDEが解決出来ない事だけに集中して考えるようになった。
この全てが無いと、思考を一時的に倍増してくれるようにはならない。
で、その結果。
IDEをさわってちょんちょん、と突くと、可能な解空間がぶわっと見えるようになって、その中からbad smellを取り除いたり良さそうな方向に位置を進めて、また解空間をぶわっとリロードする。
プログラミングは、そういう感じになった。
だから生成してくれてすごい、ってのは、大分実態とは違う気がする。
F# でも平気と思いますが自分はそこまで使えない。
Type Scriptは不勉強につき分からず。
どちらにせよC++はさすがに無理かと(^_^;)
C♯とVSをそれなりに触ってみるのは、凄いいろいろ発見はあると思いますよ。
IDEに全てを合わせるとどうなるか、というのは、自分はどうせやる気は無くても一度見ておいてもいいんじゃないか、と思います。
以前Windowのメモリダンプをする必要があってC#を使いかけたんですが面倒臭すぎて挫折しました。
https://github.com/eyasuyuki/DumpHeapMemory
当時の話をもっと詳細にする事は自分でも出来るけれど、今を知りたいならWin8世代の人に聞かないといかんですな。