Archive for the ‘コンピューターとインターネット’ Category
フリーズしないアプリケーションの作り方
@IT 向けに書いた記事が公開されました。
これもまた、裏ではいろいろと思うところあり。
タイミングよかった
いやー、題材が題材だけに、C# 5.0 とか .NET Framework 4.5、VS11 の正式版が出る頃に出そうかなーなどと思って書き貯めてあった文章だったり。
諸事情あって、実は意図せず今月完成させて出すことになって、今日の公開だったわけですが、意図せずいいタイミングになったなぁ。
BUILD での発表内容がもうほんと非同期処理だらけで。「WinRT では50ミリ秒以上かかる処理は非同期APIにします」とか、C# 5.0 の async/await 構文の再説明も多々入っていたり。
ついかっとなってやった。後悔なんてあるわけない。
まあ、非同期処理は一応、年々ホットな話題になってきているので、他にも記事はあるにはあります。
ただ、自分的に納得のいくものがないというか、「非同期処理なんてどうせレベル高い人向けのものだから、わかりやすい説明とかしないでいい」と言わんばかりのものだらけなのが納得いかず。難しいものを難しいまま書いてる記事とか見るとイラっとして、ついかっとなって自分で書いた。後悔はしていない。
なんというか、図が全然ないとか、いまいちきれいな分類がなされてないとか、そもそもなぜ必要か理由が抜けてるとか。そういうのを抜かない丁寧さは大事だと思うのに、ほんと、非同期処理がらみの記事できっちりしてるものを見たことがなく…
特に、C# 5.0 で入る async/await 構文なんかは、「今までレベル高い人だけが触っていたものを、もう少しレベル低めの人でも触れるようにしよう」というものなので、丁寧な説明を要するわけで。
かぶった
「他にも記事はある」というか、書いてる最中、100%かぶった記事が公開されて焦ったり…。しかも、MSDN マガジン。
テーマはおろか、Task クラスから始めて、Parallel クラス、C# 5.0、Dataflow ライブラリを説明と、構成まで完璧にかぶりましたとも。びっくりするレベルで。
まあ、でも、上記の理由(丁寧さの問題)があるので気にせずそのまま書くことに。
難しいことを簡単に
簡単なことを簡単に説明しても役に立たないだろ。難しいこと難しいまま書いても読んでもらえないよ。
などと、常日頃から思っております。難しいことを簡単に説明できなきゃいけない。
でも、テーマが「難しいこと」な時点で編集部の方々に敬遠されがちなんですよねぇ… さんざん言われていますとも、
- 「えっ、LINQ までやるの?」
- 「非同期をテーマにすると、予想以上に引きが弱い」
等々。
ページビューによって広告収入が決まるんで、編集さんとしては正しいご意見。難しいこと難しいまま書く人が多いんだもん、そりゃ PV 取れない。
しかし、レベル高い記事ほど PV 取れないとなると、ウェブからレベル高い記事が消えるよなぁと、常々懸念しております。
なんとしても、レベル高めの記事で PV 取らなきゃいけない。それには、ただ難しいこと書いていてはダメで、難しいことを簡単にかかなきゃいけない。
まあ、前の「データ処理」(要は LINQ)とか今回の「非同期」とかで、そこそこちゃんとブックマークついているようなので、ひとまずは安心。
(自分の場合は、自分自身が twitter とか ufcpp.net とかから宣伝かけれるんでチートといえばチート、フェアな数字でもないんですが。あと、対外的に「難しいことを簡単に」であることに加えて、まあ商売ですんで、制作的には「見合ったコスト」で書けなきゃ意味なく。この点はまだまだ改善の余地あり。)
(あと、「非同期」という言葉がよくわからなさすぎて良くないという説も。今回の記事も、タイトルからは非同期の文字を外すことに。それは多分、効果あったと思います。「フリーズしない」の方がやっぱりパッと見でイメージ伝わる。)
今のページビューと、これからと
開発者の収益性という面でみると、一番コスト・メリットのバランスがいいのは「平均的なレベルの1歩だけ先を行く」なんですよね。はっきり言って、最新技術追いすぎてもコスト高。
それもあって、ニュース性の高いものならともかく、僕が書くような教科書的色合いの濃い記事は、最新なもの使うより、今、現場で一番使われているであろう枯れたものが使われがちなんですよねぇ。
- GUI のサンプルはやっぱり Windows フォームでしょうか?
- Task クラスは .NET 4 に限られるので、Thread クラスを使った例を。
- データベースは DataSet、取得側のダウンロード形式は CSV、サーバー間連携は FTP でファイル アップロード、etc.
ただ、でも、そういう記事は5年10年という期間で、人を育てるんですよね。
その5年・10年とみられるものに、今現在の最大多数であっても、減少トレンドがはっきり表れているものを書いていいのか。それでも、ページビューのために最大多数なレガシーを書くべきなのか。
とかあるので、自分の場合はサンプル コードとかには絶対最新のライブラリしか使わないわけですが。ただ、記事の収益性を軽んじては絶対いけないと思うので悩むんですよねぇ、最近。これも、「新しいことを、既存技術者にもわかりやすく」と「見合ったコストで」をちゃんと気にしていかないと。
プログラミング言語の簡単さ/むずかしさ
Scala をディスると PV が増えると聞いて。Scala、難しいよね(棒読み)。
そういう冗談さておき。プログラミング言語が簡単/難しいって何だろう。
How vs. What
C# もよく言われるんですよね、「C# は簡単だ」というのも、「C# は難しい」というのも両方。で、よくよく話を聞いてみると、だいたい以下のような感じ:
- C# は文法が多い。概念覚えるのが大変だから難しい。
- C# はやりたいことをやれるから簡単。
文法の簡単さ
「プログラミング言語マスター = 文法を覚える」だというなら LISP でも使ってなさいってば。あの言語、超簡単ですよ。() の中にトークン並べるっての以外に何も文法持ってないから。
こういう意見って、要するに、How(どう書くか)ベースの簡単さなんですよね。
やりたいことをやる簡単さ
プログラミングって手段であっても目的ではないわけで。What(何をしたいか)ありきだと思うわけです。
さて、そうなると、プログラミング言語の文法が少なければ簡単かというと、if とか for とかを書くのがあなたの目的ですか、と。
というか、この意味でいうと、「簡単さ」という言葉に占めるプログラミング言語文法の割合なんて大したことはなくて、ほとんど、ライブラリとかフレームワークの方に依存するのではないかと。
文法なんて、覚えることも少なければ、ここ数十年での進歩の度合いも大したことはないです。C# みたいに、たった10年でずいぶんと進歩した言語でみても、フレームワークやライブラリの方の追加・進歩と比べると大したことはない。
理不尽な難しさ
「難しさ」にも、必要に迫られてどうしようもない必要悪的なものと、意味もなく単に難しい理不尽なものとあるわけで。
と言っても、好き好んで理不尽な難しさを導入しようなんて人は、通常、いないわけで。ネタ言語ならともかく、少なくとも実用を目指すものならば。
理不尽な難しさって、だいたいは歴史的背景に起因するか、思慮が足りなかったかのどちらかで。
歴史的背景
まあ、できた当時の事情を考えればしょうがない。どうしようもないものの…
C++ の理不尽の大半は、歴史的にどうしようもないものが多く。
C#、たった10年しかたってないこの言語ですら、もはや黒歴史と言っていいものもあり。
特に、古い文書はいつまでも残る
今はさすがにもうって感じですが、C 言語って、長らく K&R の呪いみたいなものに悩まされ続けてたり。ANSI 標準化前の初版のスタイルで C 言語を覚える人が続出してしまったという。
そんなに頻繁に更新のなかった C ですらそんなので、まして、発表から10年、正式リリースから8年にしてバージョン 4.0 の C# なんてもう。ほんの少し昔に自分で書いた説明ですら「あっ、古い。このコードまねないで。」と思いつつも、直す時間取れない/メディアの都合でそう簡単に直せないものがどれだけあるかっていう。
思慮の足りなさ
だいたい、問題は後からでてくるもので。
これに対する解決策は、十分な試用期間を設けて、十分な人数で使ってみて問題を洗い出すこと。
となると、Java とか C# みたいに最初から企業の後ろ盾のあるものはともかくとして、個人ベースの開発から始まって、徐々にコミュニティが成熟してきたような言語は何かしらカオスを抱えてしまうもので。
個人的には、Scala にもやっぱりこの手の理不尽が少々あると思っています。
簡単さ/難しさ の要因
もちろん、ライブラリの充実、言語機能の充実。そして、前述の「理不尽」が少ないかなどもありますが、その他にも。
検索性
ライブラリやらフレームワークやらの挙動まで含めれば、プログラミング言語のすべてを覚えきれる人なんてほとんどいないわけで。ソフトウェアに求められる要望も多ければ、言語やライブラリが持つ機能も膨大な今、大事なのは機能の探しやすさではないかと。
目次検索
膨大な数の機能を、名前空間(パッケージ)とかクラスで分類・整理できた方が「簡単」だと思います。
「書くのが楽だから」とか「クラスって概念を教えなくてもいいから」って理由で、標準ライブラリをグローバル関数だらけにしてしまうと、検索性で非常に困ることになるかと。IntelliSense とかのコード補完機能で、補完候補が100個くらい出て来るともう、それは補完の価値半減。
検索エンジン
検索エンジンでの検索性でいうと、記号をやたらと使う言語は不利ですね。
その点、関数型言語というか、エンジニアじゃなくて数学者に媚びた感じの言語はつらいというか。
一貫性
他の文法との
文法が一貫してないことってそうないというか、一貫してないのは前述の「理不尽」にあたるはずですけども。
他のライブラリとの
まあ、新しいライブラリを使い始める際、使ったことのある既存のライブラリとの類推を求めるもので。
この辺り、標準ライブラリが強ければそれに合わせるサードパーティが多くなるとか、言語機能が充実していれば独自にデザインパターンの亜種実装しなくていいとかあり。
C# の楽さはこういうところにあると思う。snake_case, camelCase, PascalCase が混在すること少ないし、イベントハンドラーの登録口は普通eventになってるし。
他の言語との
例えば、.NET 言語なら、今となっては、「匿名メソッドとか作ったら Action か Func になる」というのを期待しちゃうんですよね。それが標準だから。でも、これが、F# だとそうならない。FSharpFunc とかいうクラスになる。
カリー化の都合とかだとは思うんですけど、こういう細かい独自路線が、「他の .NET 言語からの流入」を結構妨げてると思うんですよねぇ。
必要十分性
機能は多ければいいかというとそうでもなく。理想をいうと、目的に応じて、目的を達成するのに必要十分な量が一番簡単なわけですが。
この辺り、目的を絞れない汎用言語は不利。かといって、いちいち目的特化型の言語(DSL)を作ると、いちいち文法を覚える手間もかかるわけで。
結局、汎用言語+DSL の混在開発を目指してみるか、せいぜい目的ごとに名前空間をきっちり分類して検索性を上げるかくらいしか手の打ちようもなさそうな。
注意点
目先の簡単さ
世の中、「短期的に見ると簡単なんだけど、長期的には負債にしかならない」っていう罠だらけ。
そりゃ、setter/getter 書くよりも、フィールドを public にしちゃう方が楽よ。その場は。
そりゃ、デフォルト引数とかあると、オーバーロード書かなくて済むから楽よ。バージョニングの問題さえなければ。
そりゃ、イテレーターとか書くよりも、入力・加工・出力を全部1つのループの中で書く方が楽よ。後々、ループの規模がでかくならなければ。
パット見の簡単さ
概念も難しくない、書くのも簡単。でも、絶対はまるなんてものも。
例えば非同期処理、特に同時実行制御(ロックとか)なんかがその最たるもので。意外と、同期コードって単純に見えるんですよね。コード上は。
でも、同時実行制御の本当のヤバさはテストにあって。100万回に1回しかでないバグとかざらで、どうやってテストしろと。チェックインのたびに100万回テスト走らせるの?確率論的に「100万回に1回」なとき、1,000万回走らせても出ないときはでないよ?
慣れによる楽さ
自分は C で覚えたから C にある機能に近いことだけ覚えるのが楽。諸先輩がみんな C だから、新人も C 教えるのが楽。そういう楽さはあるのでなんとも。
そしてレガシー化。
標準と革新
なんか Silverlight に関していろいろ言われているようなので。
発端となる記事:
- マイクロソフトが戦略変更。HTML5が唯一のクロスプラットフォーム、SilverlightはWindows Phone 7のプラットフォームに
- Microsoft は Silverlight をあきらめ HTML 5 へと走る
(少なくとも、後者(英語の原文の時点で)はタイトルがよくない・・・)
これの意味するところは:
- 「標準ベース」で、ほんとに iPhone, Android 含め、単一のコードでクロスプラットフォームを目指すなら HTML5 を使ってほしい
- 当面、Silverlight は Windows Phone 7 に注力
- PC 版は「すでにある」ものなので、立ち位置としては、MS 製品内のクロスプラットフォーム
- 結局のところ、iPhone でいうところの Obj-C、Android でいうところの Java と同じ立ち位置が Silverlight
- HTML5 との間には、「標準」と「革新」のトレードオフがあって、棲み分けられている
という感じかと思います。
もう少し補足でいうと:
- 開発リソースを HTML5 の方にさくのは、Silverlight は現時点で結構安定したという証
- MS 技術内のクロスプラットフォーム(3 screens の中核)という位置づけは変わらない
- 今、スマートフォンがホットな話題なので、iPhone, Android, WP7 間のクロスが話題になりがちで、この文脈だと 「HTML5 こそが真の、唯一のクロスプラットフォーム」と言われるのもしょうがなく
- かといって、既存のデスクトップ アプリ資産と WP7 のクロスとなると、WPF/Silverlight の出番
Microsoft が HTML5 に本気なのも事実ですけども、Silverlight はなくならない。
「標準」と「革新」のトレードオフって書きましたが、つまるところ、誤解恐れず端的に言ってしまうなら、
標準っていうのは、「10年遅れくらいで、かつ、互換性に悩まされる(標準化漏れや対応遅れのバグフィックスまで含めれば10年どころではなく遅れる)のを覚悟の上でも、少しでも間口を広げたければどうぞ使ってください」というもの
だと思います。
UI(プレゼンテーション層)の標準化はほんとに大変なもので、そのくらいの遅れは覚悟しないと、標準とかは無理だと思います。UI に対する要求が高い場合、「iPhone は Objective-C で、Android は Java で、WP7 は Silverlight で、3重開発した方がマシかもしれない」ってレベル。
となると、ほんとのところ大切なのは、クライアント側の技術選定の前に、サーバー側を「サービス化」しておくことなんですよね。「UI まで含めて1つのシステム」みたいな作り方はダメで、任意のプログラムからサーバー上の機能を利用できる形で作って、UI はいつでも差し替えれるようにしておくべき。
数か月も経てば、過去の自分は赤の他人
コンソール アプリケーション作るのってむちゃくちゃ難しくない?
といっても、「僕の基準では」なんですけども。僕がアプリ作る上で絶対外せないと思ってる条件が、
作ってから3か月以上放置した後でも、ドキュメントもソースコードも全く読み返さずに自分で使えること
なんですよねぇ。そのせいで、コンソール アプリを書くなら・・・
- 使いやすくてかつ覚えやすいコマンドってどんなだろう
- オプションにするにしろ設定ファイルにするにしろ、それにエイリアスを付けるにしろ、
- 長いと打つのしんどいし、略称だと覚えにくいし、どう略したかで間違うし
- IntelliSense欲しい
- 文字列から色んな方への変換を適切にやらないと
- 標準でコンバーターとか検証属性欲しい
- 絵を使って2次元的に表示すれば一目でわかるようなものを、1次元的に入力してもらわないといけない
- 相当な工夫がないと、ドキュメントなしで使えるものにはならない 等々、相当ハードル高い。結局、スクリプトをダブルクリックしたら後は全自動みたいなタイプのもの以外は、コンソール アプリを書ける気がしないという。
WPF 慣れしてて、それで実際、素人さんにマニュアル一切なしでアプリを普通に使ってもらえてるという経験もあり、気が付けばコンソール アプリを書けない身に・・・
今日小耳にはさんだ話
- 「ベンダーロックは避けたいから Java で」というけども、「弊社は JVM の全機能を自前実装していて、全ての責任を負えます」というとものすごく受けがいい
- ベンダーロックって何なんだっけ?
- ↑ 結局、国産信仰かもね。国内大手にならロックされたい
- Microsoft にはロックされたくないっていうけど、Oracle データベースはいいの?
- 世界一の金持ち(だった)企業に金払いたくないという出る杭打つ思想?
言語設計
「言語設計者たちが考えること」などという本を買って呼んでいるわけですけども。Anders Hejlsberg のところを主に。この本を読みつつ、自分的に思うところなどをまとめてみる。
フレームワーク
ここ2・30年ほどを見て、言語は大して進化してない。進化してるのはフレームワーク。
属性、イテレーター ブロック、LINQ や dynamic を導入している C# を基準に見てすら、それ以上にフレームワーク側の進化の方がはるかに大きい。LINQ や dynamic も、言語上は薄い構文糖衣で、多くの部分をフレームワーク側に寄せている。
今は、言語、フレームワーク、開発ツールが切り離せない。
新言語
新しい機能が欲しいんなら既存の言語の拡張でいい。新しい言語を作りたいのはむしろ機能を削りたい時(危険だったり誤用を招く機能をなくしたい時)。
汎用言語の新機能は、汎用であるべき。LINQ はデータ アクセスという domain specific ではあるけど、拡張メソッド、匿名型など、汎用な細々とした機能の組み合わせで実現している。単純に言語内に SQL 埋め込むだけのような実装方法だったら決して採用されていない。
DSL
外部 DSL だと「特殊な文法の中で、式だけは C# のものを流用したい」って要件が多すぎてつらい。言語の9割方はありふれてて使いまわせる要件で、残りの1割程度に domain specific が詰まってる。
逆に、内部 DSLで 困るのは、制限を掛けたい時。機能が多すぎるのが煩雑さ・誤用を招くから機能制限したいけど、内部 DSL だと元の言語の機能フルに使えてしまう。
多分、必要なのは、既存言語を部分的に流用する機能。
ここ10年ほど注目浴び続けてる domain っていうと並列処理だけども、immutable がいいとか、状態を共有したくないとか色々ある。で、immutable って機能を足す方は簡単。問題は、mutable な既存機能をどう制限するか。(言語全体で制限するのはかえってまずい。GUI 部分みたいに本質的に mutable な部分はやっぱ mutable にやった方が。)
動的
動的言語の良さはメタプログラミング。でも、そのためだけに型の静的チェックをなくすのはあまりにもデメリットが大きすぎる。
注意: 動的実行・動的コード生成をしてても、型チェックだけは静的にできる。
さて、WordPress になったところで再度、PowerPoint 貼り付けテスト
今度はどうかな?
ちなみにこの資料、書くに至った経由は以下のような話と、それに付随する twitter でのやり取り。