T6-501多言語パラダイムによる実装手法に関するフォローアップ

TechEdの「T6-501 多言語パラダイムによる実装手法」に関して、フォローアップとしてお話した内容を記載します。説明した内容は、論点が3つあります。 プログラミング言語と計算モデル 複数の言語を組合わせた具体例 分析・設計のおける考慮点(マルチパラダイムを抽出するために) 最初の「プログラミング言語と計算モデル」では、コンピューターで動作させるモデルとしてチューリングマシンやラムダ計算モデル、並列に特化したDAGやCSPなどのモデルが存在しており、近年のプログラミング言語はマルチパラダイム化しているが、中心となる計算モデルというものが間違いなく存在するということです。従って、汎用言語(GPL)が他の計算モデルへ対応するためにマルチパラダイム化したとしても、現時点では最適化などを考えると最適解には決して成り得ないという話をしました。この理由として、複数の言語が活発に使われているし、新しい言語も開発されていることを取り上げました。現実的に複数の言語を組合わせる時の問題点として、「人材が居ない」とか「新しいことを覚えたくない」とかを良く耳にします。ですが、この論点においては生産性などとのトレードオフで判断すべきだという説明をしました。その理由として、不可能ではないけど頑張れば出来るから頑張って1000行のコードを書いたとして、別の言語を使うと500行で済むことが良くあるからという話をしました。これは、別の言語を知っているかどうかであり、異なるパラダイムでは異なる問題解決アプローチがあるからです。だから、様々な言語を知ることは自分にとって有益になります。 次に具体例として、動的言語と関数型言語を取り上げました。動的言語では、オブジェクトの結合度を弱めるためにObjectコンテナーが、スクリプトでオブジェクトを生成する3種類の戦略をお見せしました。これ以外にも、検証ルールや構成パターンなどをデモでお見せしました。これらの理由は、オブジェクト同士の結合度を弱めることで、変更が起きる可能性をスクリプトなどへ隠ぺいすることで、保守容易性や変更容易性を向上することができます。 続いて、非同期パターンを組合わせた場合にプログラムが複雑化していくという説明をしました。この問題を解決するために、F#の非同期ワークフローが有益であり、同時実行などを考えた場合はアクターモデル(メッセージ エージェント)を使うと簡単になるというデモをお見せしました。さらに、デモの中ではWPFで作成したUIへイベントを通知するモデルを用意することで、非同期+リアクティブ プログラミングという組み合わせの重要性を説明しました。.NET Frameworkの非同期処理で、Begin系メソッドで呼ばれるコールバックメソッドは、Beginメソッドを呼び出したスレッドとは異なるスレッドで呼ばれます。このためコールバックメソッド内で、イベントを発生させるとコールバックメソッドが動作しているスレッドになってしまいます。このままだと、UIスレッドとは異なるためWPFではDispactherを使わなければならなくなり、この形式は良くありません。何故なら、イベントの利用者がDispactherを意識する必要があるからです。この問題を解決するには、同期コンテキストを使ってイベントを呼び出し側スレッドに同期させるのが良いリアクティブ プログラミングとなります。 最後に説明した分析・設計における考え方では、以下のような考え方をベースに説明をしました。 メンタルモデル(James.O.Coplien) Domain Driven Design (Erick Evans) DCI(Data Context Interaction) この中でご説明したこととして、現在のOOA&Dではプログラミング言語が持つ制約としてのクラスを抽出することに重きを置いており、ユーザーの目的を支援する本来のオブジェクトになっていないということです。このギャップを埋めるために、Agileの様々な手法が使われています。その例として、XPにおけるユーザーの参加と早期のフィードバックを踏まえた動くソフトウェアを素早くリリースするというプラクティスを取り上げました。この考え方からCoplienのDCIアーキテクチャに繋がっており、彼の考え方によればクラスのしての設計時点の振る舞い(Methodfull Role)と、オブジェクトが動作する場(コンテキスト)において異なる振る舞い(Methodless Role)が出てくるということです。従ってDCIでは、ユーザーのゴールを「ドメインオブジェクトに対する操作」ではなく「目的を達成するためのタスクフロー」に置いています。 一方、DDDの世界においてはEric Evansなどのその後の研究や実践した結果から、書籍としてのDDDに定義されていないことなどを学習していき、DDDを再定義しようとする動きに繋がっています。これらの動きが、DDD eXChange 2010の資料などから読み取ることができます。DDDの再定義から提唱されているのが、以下のような考え方です。 Event Sourcing Process Integration Event Sourcingでは、CQRS(Command Query Responsibility Segregation-コマンドとクエリーの分離)という考え方でオブジェクトの振る舞いを分離していきます(この考え方が、T1-502の萩原さんのセッションでも説明がありました)。また、DDDのビルディングブロックとして、Entities、Value Objects、Services、Domain Events(非同期イベント)、Aggregates、Modulesなどが定義されると再定義しています。これは、EvansなどのDDDの考え方をクラウドを含めたシステムに対応できるように考え方を洗練させていったことにより出てきたものと考えられます。このビルディングブロックやCQRSを組み合わせると、ドメインモデルにはコマンド系のメソッドしか残らなくなります。こうなると、今までのドメインモデルとは異なったものに変化していきます。EvansのDDDの世界で重要なポイントと私が考えているのが、Bound ContextとContext Mapになります。モデル(オブジェクトと言い換えても良い)が意味を成す領域がBound Conetxtであり、これに関連するContextとの対応関係がContext Mapとなります。よって、このことはContextによってモデルの振る舞いが決定されることを意味します。このようなEvansなどの考えに気が付いた時に私が思い出したのが、Martin Fowlerの「Development of Further Patterns of Enterprise Application Architechure」になります。つまり何が言いたいかといえば、ドメインモデルを現在のシステム形態(Key-Valluesストレージなどのクラウド技術を含んだもの)へ対応させるにはどうしたら良いかという動きが、今まさに始まっているということです。 Evansのこのような考え方は実装により近いのではないかということを私は考えており、Coplienはもっと上流(別の言い方ではユーザーより)から考えているように私は感じています。これはどのような視点でシステムを見ているかによるものです。そして、もっと重要だと私が考えるのは、システムにおける共通性と可変性を識別し(ドメイン工学のFODAなど)、可変性をどのように実現していくかということです。それが、DCIアーキテクチャや再定義されつつあるDDDの前提になっていると私には思えます。 分析・設計論として、簡単な結論があるわけではありません。考えるべき事柄が多岐に渡っており、それらの要素に気が付くというのが本セッションの大きなテーマでもありました。このような雰囲気が参加者に伝えようと意図したのが、今回の私の発表になります。 PS.これらの考え方は、今回のセッション資料を作成するに当たって萩原さんと何度もディスカッションをして得られた気づきによるものです。これらのディスカッションは、TechEdの期間中も何度も行っており、その中でお話する内容が決まっていきました。これらの理由から、公開している資料には本エントリーで記載さしたようなキーワードが含まれいないのです。

0

IronRuby 1.0 におけるエンコーディングの取り扱いについて その2

前回のエントリについて、NAKAMURAさんかフィードバックをいただきました。「$KCODEとはコマンドライン オプションのことですか」という話で、その通りなんですが、この辺はどうなんでしょうかと個人的には考えていたります。コマンドライン オプション「-Kkcode」というものがあります。これを以下のように設定すると、スクリプトファイルのエンコーディングを変更することができます。 -Ks: $KCODE=’shift-jis’ -Ku: $KCODE=’utf-8′ 利用するスクリプトに応じて-Kオプションを使い分けるというのもあるでしょうし、オプションを設定しなくても動作するようにするという考え方もありますので、私がどちらの立場が好きかといえば、間違いなく後者なだけです。 前回は文字列のエンコーディングを変換するのにSystem::Text::Encoding.Convertメソッドを使ったわけですが、提供されているライブラリを調べるとIconvが使えました。NKFは移植が完了していませんが、Iconvを使えばエンコーディングの変換は問題なくできます。Iconvを使ったコードを以下に示します。 # オリジナルの読み込み(UTF-8) d0 = open(“utf8 bom.txt”).read # BOM(0xEF 0xBB 0xBF)を除いた文字列の作成 d1 = d0.slice 3..-1 # ICONVモジュール require ‘iconv’ # エンコーディングをUTF-8からシフトJISに変換 d2 = Iconv.conv(‘shift-jis’, ‘utf-8’, d1) puts d2 これでir上は、問題なく表示することができました。System::Console::WriteLineメソッドなどで出力するには、正しいエンコーディングを文字列に持たせてやる必要があります。というのは、上記の変換した結果のEncodingプロパティは、ASCII-8BITになっているからです。 IronRubyのIOクラスのソースコードを調べるとRuby 1.9のexternal_encodingとinternal_encodingを実装しようとしていることがわかりました。この実装は、まだ未完成でexternal_encodingがASCII-8BIT(バイナリ)固定になっています。これが、Fileオブジェクトを使って読み込んだ場合のEncodingプロパティがASCII-8BITになっている理由でした。 また「-1.9」オプションを使用すると、不完全ながらRuby 1.9互換モードになります。この1.9モードであれば、String#encodingプロパティへアクセスできるようになりますし、Encodingクラスも不完全ながら使用できるようになります。これらのことから推測できるように、前回のエントリで使っていたString#Encodingプロパティが1.9互換実装の機能を使うものだということです。 SilverlightでIconvを使用するには、「load_assembly ‘IronRuby.Libraries’, ‘IronRuby.StandardLibrary.Iconv’」を使ってモジュールを読み込みます。load_assemblyメソッドは、IronRuby固有のもです。このメソッドを使用する理由は、iconv.rbというライブラリをSilverlightの実行環境で使えるようになっていないからです。もしろんiconv.rbを使えるようにすれば「require ‘iconv’」で構いません。

0

[TechDays 2010] Dynamic のデモについて

TechDays 2010が終わりましたので、参加者の方へのフォローアップ(デモを失敗した自分へのフォローアップも含みます)を兼ねて、何回か不足していると思われる内容を記述していきます。今回は、Dynamic(動的)に関して説明します。 最初にPythonのコードを使って、以下のような図形を描画しました。   このデモ(BadPaint.exe)は、C#でWPFを使って作成しています。上記のようなシェイプを描画したPythonコードを以下に示します。 from System.Windows.Controls import Canvas from System.Windows.Shapes import * from System.Windows.Media import * import math dim = min(Application.Painting.ActualWidth – 20, Application.Painting.ActualHeight – 20) / 2 for i, color in zip(xrange(0, 360, 10), dir(Brushes)): rect = Rectangle(Width=20, Height=20, Fill=getattr(Brushes, color)) Application.Painting.Children.Add(rect) Canvas.SetTop(rect, dim * math.sin(i * math.pi * 2 / 360) +…

0

[TechDays].NET Framework 4 時代の言語を担当します

Tech・Days 2010では、「.NET Framework 4時代の言語」というセッションを担当します。概要にも記載していますが、扱うテーマは以下の3つになります。 Dynamic (動的) Declarative (宣言型) Concurrent (同時実行) 最初のテーマであるDynamicについては、DLRが提供されることで何ができるかというのがメインテーマになります。ここでお見せする予定のデモとしては、C#<->IronPython、C#<->IronRubyなどの静的言語と動的言語間の相互利用になります。両方を組み合わせることで、どういうことが実現できるかについて説明ができればと考えています。 2番目のテーマとしては、宣言型プログラミングの定義に従って XAML と Visual F#を取り上げます。XAMLについては、.NET Framework 4で提供される System.Xamlを説明する予定です。 F#は、関数型言語としての基本的な部分をご説明することを考えています。 3番目のテーマに関しては、これが一番難しいと感じています。Concurrentという単語を「同時実行」と訳していますが、「並行」と訳す場合もあります。Parallelという単語では、並列と訳するわけです。一般的に並列プログラミングと呼んでも、並行プログラミングと呼ばれることは少ないわけです。並列か並行かというのは、言葉の定義が大切なのですが、並列プログラミングに関するトピックはMSDN ライブラリの中では、Advanced Topicになっているため、一般の人には理解しにくいのではないかと考えています。従って、どのように説明するかという点に関しては、未だに検討しています。 すべてのテーマに関して考えていますのは、 今迄がどうだったのか .NET Framework 4 でどうなるのか ということです。たとえば、Dynamicですが今迄は提供されていませんでしが、これからは提供されるわけです。そうすると、モックオブジェクトと本番オブジェクトを入れ替える場合に「Dynamic」を使うことで依存性を気にしないで入れ替えることが可能になります。もちろんプログラミング的には、インターフェース継承などを使って入れ替える方が、記述ミスの少ないプログラムを記述できますし、実行速度も速くなります。ですが、オブジェクトのインスタンスを作成するFactoryクラスなどを用意する必要があるわけです。これをDynamicにすることで、FactoryクラスがDynamicオブジェクトを返すことで、どのようなオブジェクトでも扱えるようになるわけです。もちろん、知らないメンバーを呼び出すことはコストがかかりますので、呼び出すメンバーの名前に関しては知っている必要がありますが、インターフェースを使うことなく実行時に解決できるのが、DLRのメリットになります。また、2度目以降の呼出しは、サイトバインダーによってキャッシュされていますから、速度の向上も望めるわけです。Dynamicを使用しなかった場合との違いは、「コンパイル時にメンバーを解決するか」「実行時に文字列でメンバーを解決するか」ということです。 この速度面の課題を許容するのなら、オブジェクトを作成するコンテナとしてDLRを活用する価値があるのではないかと、私は考えています。スクリプト系の言語が、色々なところで使われている状況を考えると、使っても問題ないと考えることができます。もちろん、絶対的に速度を重視する場合では、目的を達成するために別の手段をつかうべきだと思います。 PS.考えることが多くて、資料を読み込むのも大変な状況にいます。

0

DLR プロジェクトの状況 2010年1月時点

久し振りにDLRの状況を記述したいと思います。2010.1時点では、以下のようなものがリリースされています。 IronPython 2.6 (2009.12.11) IronPython 2.6 CTP .NET 4.0 Beta2 (2009.10.21) IronRuby 1.0 RC1 (2009.11.20) IronRuby 1.0 CTP for .NET 4.0 Beta2 (2009.10.21) DLR 0.92 (2009.10.22) Visual Studio 2010 ベータ2と合わせて試すのなら、IronRuby 1.0 CTP for .NET 4.0 Beta2 がお勧めです。その理由は、.NET Framework 4.0 ベータ2に同期した IronRuby と IronPython のバイナリが含まれているからです。 また、結構前からになります DLR を使った言語サンプルとして SymPL が以前に提供されていたToyLanguage に替わって提供されています。SymPLには、2種類の実装が提供されています。 charp:ExpandoObjectなどを使った言語実装です。 charp-cponly:DLR対応のホスティングサンプルです。 SymPLの実装方法自体は同じなのですが、ホスティング方法の違いで2種類が提供されています。DLR 対応として DLRホスティング可能なサンプルとしては、charp-cponlyをお勧めします。DLRホスティングの方法としては、以前に私が公開した…

0

DLR の COM バインダーに対する考察

DLRを使ったExcelプログラミングというエントリーで、興味深いご指摘をいただきました。それは、COMオブジェクトのリリースを誰が面倒を見てくれるのかというものです。この問題を考える上で意識しないといけないのが、オブジェクトのライフサイクルの管理という側面です。具体的には、以下のようなものです。 マネージ オブジェクトは、GCによって回収される。 COM オブジェクトは、COMサーバーが参照カウンタが0になった時点で消滅させる。 オブジェクトの生存の可否そのものが、異なる観点で管理されているのです。つまり、 マネージ オブジェクトは、マネージヒープ上で参照されないものがGCによって回収される。つまり、ルート オブジェクトから辿っていけないオブジェクトが、回収の対象になる。 COMは参照カウンタで管理していおり、マネージコードからはRCWが内部で参照カウンタに対する操作を行う。従って、RCWが回収されない限り参照カウンタがデクリメントされない。 ということです。COM参照をカウンタを適切なタイミングでデクリメントするには、Marshal.ReleaseComObjectメソッドを呼ぶ必要があります。(注)GCはCLRホスト内に存在しますので、アプリケーションがアンロードされれば解放されます。アンロード前にCOMサーバーを解放するために、Marchal.ReleaseComObjectを呼ぶかGC.Collectを呼び出す必要があるだけです。この考えをベースに.NET Framework 4.0で導入されるDLRについて考えていきます。C#言語では、dynamicというキーワードによってレイトバインディングが実現されます。dynamicというキーワードを付与した変数は、コンパイルされたILを見るとSystem.Object型がSystem.Runtime.CompilerServices.DynamicAttributeによって振る舞いを変えるようになっています。この振る舞いを変えるという言葉の意味は、以下のようなことを意味しています。 通常のメソッド呼び出し:IL上は、直接メソッドを呼び出す(MethodInfoを示すマネージポインタである)。 dynamic属性を持つオブジェクトのメソッド呼び出し:名前によってMethodInfoを取得してから、Invokeで呼び出す(この意味で、リフレクションを使ってMethodInfoを取得してからInvokeするのと同じです。厳密には、DLRのバインダーによってこれらの処理が行われます)。 つまりdynamicというキーワードは、リフレクションを使ってメソッドを呼び出す代わりにDLRが実行時にメソッド名の文字列からメソッドを呼び出してくれることになります。この時のパラメータの型に応じた呼び出しを最適化するために、CallSiteキャッシングという仕組みをDLRは用意しているのです。CallSiteキャッシングによって、同じパラメータを使ったメソッド呼び出しが高速化されるというメリットがあります。つまり実行時に文字列でメンバーを解決するが、繰り返し呼び出す場合の高速化メカニズムが用意されているのがDLRというレイトバインディングになります。今までのメソッド呼び出し比較した場合に、コンパイラが解決するか、実行時に解決するかという違いから速度的にdynamicの方が不利になるケースもあることでしょう。ですが、それは初回のメソッド呼び出し時のオーバーヘッドの違いで、2回目以降は同じとは言いませんが遜色ない程度に早くなると言えるでしょう。 これらの動的なメンバー呼び出しをCOMオブジェクトに適用するのが、DLRのCOMバインダーの役割になります。COMバインダーの設計思想は、VB6.0と同じようにCOMのAutomationインタフェースを使えるようにすることにあります。このため名前を使ってIDispatch::GetIDsOfNameメソッドでDispIDを取得してから、IDispatch::Invokeを呼び出すメカニズムを提供します。このことは、CLRにのCOMインタロップの仕組みとは異なっています。COMインタロップでは、インタロップ・アセンブリ(TLBから生成-tlbimp.exe-)を生成してアーリーバインディングを実現します。もちろん、自分でコードを記述するかVBコンパイラを使うことで、レイトバインディングを実現することもできました。これらのレイトバインディングが、コードを記述することなくCOMのAutomationインターフェース経由でCOMを扱えるようになるのが、DLRのCOMバインダーです。 ここまででdynamicキーワードでCOMを扱う時の特徴が理解できたのではないでしょうか。具体的には、以下のようなことです。 COMオブジェクトのインスタンスは、RCWでラップされている。参照カウンタは、RCWが管理している。 メンバー呼び出しは、COMバインダーがGetIDsOfName、Invokeを使って呼び出している。 そうするとCOMオブジェクトのインスタンスを早期に回収するには、プログラマがコードを記述する必要があるということです。この意味において、今までと何も変わらないということができます。異なるのは、メンバーを呼び出す内部の仕組みだけです。 但し、.NET Framework 4.0ベータ1では実装されていませんが、DLR-0.91のソースコードに含まれるMicrosoft.Scripting.ComRuntimeHelpers.IUnknownReleaseDelegate(Microsoft.Dynamicの中にあります)のコメントなど参照してみてください。この実装などが、DLRの最終形に入ってくればDLRのCOMバインダーでCOMオブジェクトのリリースまで管理してくれる可能性があります。まだ開発途中ですので、DLRの開発方向を調べたい場合はcodeplexのDLRを参照するようにしてください。 PS.DLRのCOMバインダーは、System.Dynamic.dllアセンブリに実装されています。

5

Rack ベースの Web アプリを IIS で動かしてみました

前回にご紹介した Railsカンファレンスの IronRuby on Railsセッションで、Rails以外のWebフレームワークとしてrackが紹介されていました。rackは、Ruby向けの Webインターフェースを提供するフレームワークで、Ruby on Rails 2.3.x系も内部でrackと統合されています。このrackをIronRubyを使って、IISで動かしてみました。その動かし方を以下に記載します。 1.必要なもの IronRuby 0.5.0 rack 1.0.0 IronRuby.Rack Ruby 1.8系 2.rackのインストール 「igem install rack」コマンドでインストールします。私の場合は、PATHとGEM_PATH環境変数を設定後に実行しました。実行すると以下のようなメッセージが出力されます。C:>igem install rack Successfully installed rack-1.0.0 1 gem installed Installing ri documentation for rack-1.0.0… Installing RDoc documentation for rack-1.0.0… mscorlib:0:in `GetBytes’: 値が有効な範囲にありません。 (System::Text::EncoderFallbackException) from :0:in `write’ from :0:in `puts’ from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/ user_interaction.rb:227:in`alert_error’ from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/ user_interaction.rb:103:in`alert_error’…

0

IronRuby で Ruby on Rails を動かしてみました

昨年のRailsカンファレンスに続いて今年のRailsカンファレンスでは、「IronRuby on Rails」というセッションが行われました。このセッションでは、公開されたIronRuby 0.5.0とRuby on Rails 2.3.2を使って実際にRailsをIronRubyで動かしています。少し(大分かも)前から、IronRubyでRailsを動かすためのドキュメントが公開されています。このカンファレンスで何を紹介したかというサマリーが、Jimmyさんのブログで紹介されています。Railsを動かすドキュメントを使って、実際にRailsを動かしてみましたので、その手順を以下に記載していきます。 1.環境構築 IronRuby 0.5.0 Ruby 1.8系 (私は、OneClick Installer 1.8.6-27を使用しました) IronRuby 0.5.0をダウンロードしてC:\IronRuby-0.5.0フォルダへ展開し、OneClick Installerで使ってC:\RubyへRubyをインストールしました。 2.Rails 2.3.2 の導入 RubyGems のアップデート Ruby on Rails 2.3.2をRubyGemsを使ってインストール#コマンドプロンプトで作業 gem update –system gem install rails –v2.3.2 –include-dependencies  (注)RubyGemsを利用するために、Ruby 1.8系が必要になります。 3.環境変数の設定 PATH環境変数へ IronRubyのBinフォルダへのパスを追加します。 GEM_PATH環境変数へRubyGemsのパスを設定します。SET PATH=%PATH%;C:\IronRuby-0.5.0\bin SET GEM_PATH=C:\ruby\lib\ruby\gems\1.8   4.IronRubyの構成ファイルである「ir.exe.config」のLibralyPathsの値にRuby1.8のライブラリパスを設定します。<set language=”Ruby” value=”..\lib\IronRuby; c:\ruby\lib\ruby\site_ruby\1.8\; c:\ruby\lib\ruby\1.8\” option=”LibraryPaths” /> (注)valueの値は読みやすいように改行していますが、実際に設定する場合は改行を含めないで下さい。またir.exe.configは、IronRuby 0.5.0を展開した中のBinサブフォルダに存在します。 4.SQL…

4

DLR を使った Excel プログラミング

Visual Studio 2010ベータ1のウォークスルーの中に Office プログラマビリティ があります。このウォークスルーの中で、1か所だけ 動的呼び出しになると記述されたところがあります。この個所を、このウォークスルーではNo PIA(埋め込みPIA)というシナリオを確認するために、最終的には、キャストします。なぜキャストするかといえば、埋め込みPIAでは必要な型情報のみを取り込むからだと説明されています。この内容は、さておきNo PIAにしないコードの抜粋を以下に引用します。 public class Account { public int ID { get; set; } public double Balance { get; set; } } using Excel = Microsoft.Office.Interop.Excel; class Program { static void Main(string[] args) { var checkAccounts = new List<Account> { new Account { ID = 345, Balance = 541.27…

8