Nov 11, 2011

SVGで半透明図形の外側にドロップシャドーを付けるには?

暫くこのweblogを更新してないので、リハビリの為に何か書く。
これまで、代わりにTwitterとかをやってた訳ではなく、weblogとかを書きたく無くなった訳でもなく、ネタはあって細かいことは色々やってはいたのだが、何をやっても成果が出ないのである。考え事のネタだけが溜まっていく。物書き用のMacBookが不調で筆無精になってたり、部屋の地デジ化に時間を奪われたり、肺炎に罹ったりしたこともあったが、土日もクタクタで、そもそも頭を使うことに取り組む時間が激減してるので、トシなのだろう。

話を戻して、SVGでドロップシャドーを付けるには、SVG 1.1のドキュメント§15.1のサンプルコードのように、feGaussianBlurを使ってぼかしてずらしたものを先に描けば良いのだが、影を付ける対象が半透明だと、半透明の部分に自身の影が透けて暗くなってしまう。例えば、この方法で
dropshadow0.svg(注:この画像はJPEG、クリックするとSVGファイルが開きます)
この四角の上にある半透明の円に影を付けると、
dropshadow1.svg(注:リンク先はSVGのfilterに対応していないブラウザでは影が出ません)
このように、円の内側が暗くなってしまう。もし、円の外側にだけ影を付けたい場合、どうすれば良いだろうか。
手前に光源があれば、円の内側の半透明部分も影を作り出すんだから、円の内側に影が入り込むのは当たり前だろ、と言われればその通りである。この所、ブログの記事を書き始めてから問題設定に問題があることに気付いて、草稿をボツにすることが度々発生するのだが、今日はこのまま書き続ける。

上のSVGでは、SVG 1.1のドキュメントのサンプルコードに従って、

<filter id="dropShadow1" width="150%" height="150%">
<feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="5"/>
<feOffset in="blur" result="offsetBlur" dx="10" dy="10"/>
<feBlend in="SourceGraphic" in2="offsetBlur" mode="normal"/>
</filter>

このようなフィルターを定義しており、元の絵(SourceGraphic)と影との合成にfeBlendを使っているが、これをfeMergeに替えて
<filter id="dropShadow1" width="150%" height="150%">
<feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="5"/>
<feOffset in="blur" result="offsetBlur" dx="10" dy="10"/>
<feMerge>
<feMergeNode/> <!-- blurred and offset image -->
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>

にしても結果は同じである(feMergeはnormalモードでfeBlendするのと同じ)。

SVGでは、オブジェクトにα値がある限り、オブジェクトの重ね合わせにはα合成が発生するので、下の絵を消すかのようにα値ごと上書きすることはできない。<filter>〜<filter>の中では、feBlendやfeComposite等を使うことによりブレンドモードを変えることができ、特に<feComposite operator="arithmetic" k1="0" k2="0" k3="1" k4="0" />とすると重ねる絵で完全に上書きすることができるが、これらは矩形でしか行えないので、重ねる絵の何も無い部分(α=0のピクセル)も上書きして、下の絵を消してしまう。従って、

<filter id="shadow_normal" width="150%" height="150%">
<feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="5"/>
<feOffset in="blur" result="offsetBlur" dx="10" dy="10"/>
</filter>

これによってできる
dropshadow2.svg
こういう影の画像に元の絵を重ねるのではなくて、
dropshadow3.svg
こういう影の画像を作らないといけない。このdropshadow3.svgでは
<filter id="shadow_out" width="150%" height="150%">
<feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="5"/>
<feOffset in="blur" result="offsetBlur" dx="10" dy="10"/>
<feComposite in="SourceAlpha" in2="offsetBlur" operator="arithmetic"
k1="0" k2="-100" k3="1" k4="0" />
</filter>

のようにして、元の画像のα値を-100倍して重ねることにより、元の画像のα > 0.01の部分のαを0にしている。これで目的が達成できているように見えるが、元の画像を重ねると
dropshadow4.svg
このように、少し隙間ができてしまう。これは、元の画像の輪郭の、輪郭を外れた少し外側に、アンチエイリアシングによって生じる微小なαを持つピクセルがあるからだと考えられる。上の例では右下に影を付けているので、影を左上にずらせば隙間を隠せるのではないかとも思うが、
dropshadow5.svg
この円の右上のように、隙間は右下にできるとは限らない。

次に、フィルターではなくクリップやマスクを使って影をカットすることを考える。まず問題になるのは、<clipPath>によって作られるクリッピング領域はパスの内側を残すクリップだということである。SVGではクリップやマスクを反転させる術は無いように思える。パスの外側を塗り潰すことが難しいのと同様に、パスの外側を残すクリップを作るのも難しいのである。
しかし、clip-ruleにevenoddを指定することによって穴開き領域を作ることができることを利用して、十分に大きな領域の内側に消したい領域の穴を開けたクリップを作ることは可能である。
そう思って、

<clipPath id="does_not_work" clip-rule="evenodd">
<rect x="0" y="0" width="200" height="200"/> <!-- 十分大きな領域 -->
<circle cx="80" cy="80" r="50"/> <!-- 消したい部分 -->
</clipPath>

のようにしてクリッピング領域を作ってみたが、これはrect部分からcircle部分が抜き取られるのではなく、rect部分とcircle部分の和になってしまった。evenoddは1つのパスで完結しないと働かないようである。
そこで、上記のrectとcircleをpathに置き換えて連結してみた。
<clipPath id="shadow_clip" clip-rule="evenodd">
<path d="M0,0 H200 V200 H0 V0
M130,80
C130,107.6 107.6,130 80,130
C52.4,130 30,107.6 30,80
C30,52.4 52.4,30 80,30
C107.6,30 130,52.4 130,80
Z"
/>
</clipPath>

これによって影を切り取ると
dropshadow6.svg
このようになり、元の絵を重ねると、
dropshadow7.svg
となり、所望の外側だけのドロップシャドーが得られた。

とりあえず目的は達成できたが、問題点として、
(1) SVGファイル内に似たようなパスデータが何度も現れる
(2) 影をつける対象は必ず1つのパスで書けなければならない
がある。(1)は似たようなパスでクリップと影と本体を別々に書かないといけないことによる。影と本体は、次のdropshadow8.svgのようにxlinkとuseを使ってパスを共通化できるが、クリップとの共通化は難しい。(2)とも共通する課題だが、複数のパスデータをclip-rule="evenodd"が利くように繋げる手段や、複数の要素をclip-rule="evenodd"で並べる手段が見つからないのが原因である。
dropshadow8.svg(xlinkを使って少しまとめたもの)

やはり問題設定が適切でないということだろうか。

See more ...

Posted at 23:43 in PC一般 | WriteBacks (0)
WriteBacks

Sep 19, 2011

「DevLOVE関西2011CONNECT」傍聴録

9/17に、「DevLOVE関西2011CONNECT」とかいうアジャイル関連のイベントが府内であったので、行ってきた。

【聴いたセッション】

  1. オープニング
    遅れて入ったのであまり聴けず。
    Hanger Flightの話(初期の飛行士は、その体験を格納庫で話し合って共有することによって、飛行機の操縦という人類にとって新種の問題に取り組んだという話)とかしてた。
    1エンジニアの生涯工数は高々300人月くらいしかないから、1人で解決できることは知れてるとかなんとか。

  2. 「アジャイル開発事例と15分で作るRailsアプリ」(川端さん)
    XPの話、Javaで開発した事例紹介、Ruby on herokuの実演
    後述

  3. 「ゴール・リズム・愛って、プロジェクトの処方箋!?」
    プロジェクトファシリテーションとか
    後述

  4. 「障害管理からチケット駆動開発へ~BTSから始まる進化の歴史」
    Mantis最高、Mantis万能みたいな話
    後述

  5. PicoDialog
    「あなたはどんな時に能力を発揮していますか?」とか「どんな時に萎えますか?」とかのWebのアンケート5問を、1問ずつリアルタイムに集計しながら、各人の選択について参加者同士で話してみるというもの。
    4択だったのだが、いずれの質問においても、筆者に当てはまる選択肢が無く、すっきりしなかった。

【川端さんの話】
・XPの話
XPのテーマとして、Kent Beckの「白本」に始まり、それ以降のどの本でも言われていることは、コミュニケーション、フィードバック、シンプル、尊重、勇気の5つ。尊重と勇気がXPの特色だと思う。勇気とは、できる人がやったコードでも直す勇気のこと。
XPは、具体的なプラクティスが示されていることが良い。

XPが目指す成功とは、プロジェクトの成功というより、開発者満足+顧客満足だと思う。
開発者満足は従業員満足とはちょっと違う。従業員満足というと、給料が上がることとか休暇が取れることとかになるが、そういうことではなく、開発者が能力を発揮して成功できる、子供に憧れられる、尊敬される、自分が興味のある好きなことがができるようなこと。

「白本」のサブタイトルにもなってる"Embrace Change"(変化を抱擁する )という言葉が好き。レストランで魚料理を注文した客が、後になって肉料理に変更したいと言い出したら、もし料理ができ上がってても、もう作ってしまったので、と断るのでなく、もしもう作っている途中であってもそれを見せることなく、注文の変更を受け入れること、また注文の変更がしやすいように思わせること、が目指す理想だということ。

・Javaでの開発事例
COBOLだった金融システムをJavaに置き換えるためのフレームワークの開発を担当した時、発注者がアジャイルに理解があったので、やり方を全て自分達で決めてそれも都度変更していくアジャイル流で行った。

オブジェクト指向の知識も無かったが、リッツ・カールトンの「クレド」の話を知って、それを参考にしたり、進め方を自分達で決めてマインドマップにまとめるということをやって目的意識と自主性を高め、2週間のイテレーションを毎回確実にやり切り、20回のイテレーションだったが、最後まで週40時間のペースで終わらせることができた。

その過程で何を工夫したか、どんなトラブルがあってどう解決したかの話も色々あったが、筆者がポイントを掴めなかった為、カットする。

・Ruby on herokuのデモ
Rails, heroku等のインストールからscaffoldを使ったWebアプリの作成、herokuとgitを使ったインターネットへの公開まで、15分くらいで実演された。色々なConfigファイルの類を書き換えてたのが数ヶ所、アプリコードを書き換えてたのが1〜2行くらいで、ほとんどの時間はRubyのコンソールを操作してインストールしたりmakeしたりしていた感じだった。

打ち合わせの最中にも動くものが作れてしまう、動く仕様書なので意思伝達の齟齬も無い、とかいうアピールもされた。

(感想)
このイベントのWebページのこのセッションの表題の所に「バグがないプログラムのつくり方 JavaとEclipseで学ぶTDDテスト駆動開発」と書いてあって、実はこれに興味を持ったから参加したのだが、これは今回のセッションのテーマではなく、川端さんの著書のタイトルだったようだ。何と紛らわしい。かなり当てが外れたが、終始興味深い話で、Ruby on Railsの実演はなかなか鮮烈だったので、満足だった。

まあしかし、ある物を単に組み合わせるだけで作れる範囲なら短時間で作れるというのはよくある話であって、その範囲を少しはみ出ると途端に大変になるというのもよくある話である。特にお仕着せのオートマチックなフレームワークであるほどありがちである。まあ面白かったなということだろう。

筆者にはどうもRubyは遊びに見えてしまう。"Rails", "scaffold", "rake"といった名前の付け方からしてもそれは思う。新しいこと、面白いことを好むRubyな人達にとっては、実用的、実践的な名前の付け方は「つまらない」のだろう。

【ゴール・リズム・愛って、プロジェクトの処方箋!?】
アジャイルを10年やって、やはりソフトウェアは人が作るものだということを意識している。
メンバーのパワーを何%出せてるか、を考える。やり方がまずくて30%しか出せてないとか、100%を出しているがやらされ感があってクタクタとかいうことがある。
しかし、例えば運動会では100%以上の力を出せてると思う。それの実現を目的とするのがプロジェクトファシリテーションである。

プロジェクトマネジメントは計画達成型のマネジメント、
プロジェクトファシリテーションは参加者の協調の場作り。

運動会で100%以上の力が出せるのは、目的が明確で、かつ、メンバー間で一致しているから。
ゴールが明確でなかったりメンバー間で共有できていなかったりすると、チームとして100%の力を発揮するのは不可能である。また、ゴールが漠然としていると、その漠然としたレベルではチームで共有できていても、具体的なゴールの認識にはずれがあるもので、それもパフォーマンスの低下に繋がる。課題とはゴールと現実とのギャップでしかなく、ゴールがずれていれば課題は解決しない。

アジャイルのイテレーションが有効な理由は、遠いゴールを目指すのでないこと。長期的なゴールがメンバー間で一致していても、短期的なゴールにはずれが生じるものである。
WBSがなぜ階層化して分割するかというと、目の前のゴールがはっきりしていると走りやすいからである。

ソフト開発はメンバー間でリズムが一致していると良いと思う。例えば、毎日決まった時間にミーティングするとか。しかし、経験上、そのミーティングを夕方以降にすると「今日も大変だったね」だけになりがちなので、朝にするのが良いと思う。朝やると目標の確認になる。
朝会では、何か笑顔になることをやってみるといい。ハイタッチとかのつまらないことでも、自然に笑顔になる効果がある。すぐ飽きるが、飽きたら次のネタを考えればいい。それでファシリテーションになる。

愛とは、結局、欲望だと思う。人それぞれ欲望は異なる。異なっても、それにより違うtryが行われるので良いのである。

ピーターパンは、"Let's fly"とは言わず、"You can fly"と言う。相手によってその結果はまちまちだが、それで最終的に"We can fly"になる。

(感想)
宗教的な香りが漂うアジャイルの中で、しかも人間相手で掴み所がなく、極めて答えが少ないテーマに関わらず、相当にわかりやすく実践的な話だと感じた。ファシリテーションやコーチングに答えは無い。あるのは目的だけだ。テーマが広すぎて迷子になるよりは、このように具体的なヒントがある話にする方が幾分かマシであろう。

ただ、目の前のゴールの認識にもメンバー間でずれがあるもの(それがチームのパフォーマンス低下の一因)という話は、比較的難しい問題が置き去りにされていると感じた。メンバー間の認識にはずれがあるものだということを理解して話を聞けば、自ずと道は開ける、だろうか。マネージャーの本分は道を見つけること、リーダーの本分は道を示すこと、そのどちらもメンバーの知識や理解力に偏りがあるほど、衝突するものである。運動会のように競争本能によって労せず目的を一致できるものではないし、メンバー全員がゴールを共有できるとは限らないものである。
個人的にはむしろ、メンバー全員がゴールを共有しない限りは団結できないと考える方が危ういのではないか、と思ったりもする。

【障害管理からチケット駆動開発へ】
本来のTiDDとは何なのか?
BugzillaでTiDD以前のことをやってた時は、軽量さと規律の両立の妙、をあまり理解してもらえなかった。

Excelによる障害管理には課題があった。バグ情報が散在して混乱しやすい、作業履歴がExcelやメールに散らばる、集計や報告書作りに手間がかかる、バグ修正と検証のワークフローが複雑で、たらい回しにされることもある、管理台帳でリリースとの関連を管理する必要があるなど、リリース管理が大変、リリース履歴からバグを探しにくい、等々。

MantisはPHPで作られているOSSのBTSで、バグ管理に特化している、Web I/Fを持つシステム。障害はチケットで一元管理し、チケットのステータス遷移でワークフロー制御でき、検索や集計が楽で、終了チケットをリリース履歴として残すことができる、等々。

Redmineと同じく、No ticket, no commitのプラクティスが実践できる。

平均完了日数がわかる。これでチケットの粒度がわかる。イテレーションのサイクルに関係してると思う。
あるプロジェクトで、MTBFを求めてみたら、 1ヶ月持たずにバグが出ることがわかった。

BTSを仕様変更や課題管理にも使いたい。バグ修正のワークフローはSW開発の基本フローである。BTSからITS(Issue Tracking)へ。
BTSのチケットはXPのタスクカード、アジャイルのストーリーカード。BTSはアジャイルと対応付けができ、アジャイルそのもの。
Mantisは柔軟なワークフロー管理ができ、並行開発やブランチもサポートできる。

TiDDは組織全体(全ての業務)へ展開可能。TiDDはBTSのベストプラクティスを引き継いでいる。TiDDはメンバーの自発性が出てくる。TiDDはXPと同じくプログラマ復権運動。

(感想)
TiDDがBTSから派生したものだというのはそうだが、それを言うならMantisとRedmineの比較がされるべきだった。Mantisだけを取って何々ができる、というのは本質的ではないし、厳しく言うと、Excelを比較対象としているが、BTSに必要な機能として、MantisでできてExcelでできないことは何一つ説明されなかった。基本的に、Mantisと同じ入力フォームやデータ管理はExcelで実現可能である。Excelで障害管理する上での課題として挙げられたことは全て、障害管理そのものが理解されずにExcelが使われた結果であり、障害管理のノウハウはMantisを使う上でも必要なのであり、Mantisを有効に使うスキルがあればExcelで管理しても挙げられたような課題は起こらないのである。

Webのシステムだから使いやすい、というのはナンセンスである。Webのシステム(ネットワークシステム)であることとWebブラウザをI/Fとして使うシステムであることは違うし、HTMLに制限されたUIを持つシステムが一般に不便であることは常識であり、むしろExcelからのインポート、Excelへのエクスポート機能が求められることが多いものである。WebブラウザをI/Fとして使う利点はplatform independentであることだけであり、Webのシステムの利点はinteroperability、つまり他のWebベースのシステムとの連携が容易(である可能性が高い)ということである。どちらにしても、MantisやRedmineの長所となるものではない。

筆者の経験上、実務的にBTSに最も求められる機能は、検索/集計と、バックトラッキング(トレーサビリティ)である。それはMantis/Redmineは構成管理ツールと連携して実現しているが、その他の障害管理システムでも何らかの形で実現しているものである。ソースコードのリリースとバグ票番号の対応が取れない構成管理システムはあり得ない。問題はできるかどうかではなく、やり易いかどうかである。MantisやRedmineでも、チケットとコミットとの関連付けを、人の手でチケット番号やタグの入力によって行うのであれば、Excelでも同じことをすればコミットからのバックトラッキングができるのである。

TiDDはあらゆる業務に使えるというのは根本的におかしい。No ticket, no commit(or no work)というのはトレーサビリティの話であり、本来は要件番号や要求仕様書との関連や業務指示書のIDを明確にすることによってMantisやRedmineを使わなくてもトレース可能な情報を残すべき話である。「チケット」だからどうという話ではないのであり、「チケット」でも単位作業の粒度が問題になる話であり、「チケット」ベースだから確実という話でもないのである。何もかも「チケット」ベースにすることが可能であることと、何もかも「チケット」ベースにする方がやり易いことは全く異なる。手段が目的になってしまっている話であり、道具に使われてしまっている話である。そのような発想では、チケットの海に沈むことになり、Excelでやってた頃と同じ状況に逆戻りしてしまうであろう。

MTBFを求めてみたという話があったが、ソフトウェアのバグが確率的にしか起こらないのであれば意味があるかも知れないが、再現手順が明確になったバグはMTBFと関係なく起こせるのであり、1つのバグのTBFは1回しかないので、本当の意味のMTBFではない。
例えばもし、修正すべき不具合は平均的に1ヶ月に1件起こるというデータが出るのであれば、毎月1件分の修正コストを見込んでおけばいいなどの使い方ができるので意味があると思うが、平均を求めたら1ヶ月に1件だった、というのと、平均的に1ヶ月に1件起こるのとは違うのである。
ソフトウェアは、初めの頃に不具が合多く発見され、次第に安定して発見される不具合が少なくなるものである。従って、平均を取る期間を長くすればするほど平均値が減るものであり、そういう平均値は意味が無いのである。推定量の一致性がないというやつだ。また、ばらつきの有無も問題である。平均が1件/月でも、3件の月が1回で0件の月が2回であれば、平均値に意味が無いのである。
そこまで考慮して、実測したら意味のあるMTBFを取れたという話なら有益だったが、今回の話はそういうものではなかった。やはりソフトウェアの不具合にMTBFを持ち出すのはナンセンスであろう。これも本質を捉えずに拡大解釈したことにより無意味に混乱した話だと思った。

See more ...

Posted at 13:30 in 雑記 | WriteBacks (0)
WriteBacks

Jul 30, 2011

クロソイド曲線

x'=\cos\left(\frac{\pi t^2}{2}\right)
y'=\sin\left(\frac{\pi t^2}{2}\right)
というシンプルな数式で表されるそうなので、Maximaでその数式でグラフを描いてみようとしたが、残念ながら媒介変数を含む微分方程式をそのまま描画することはできないようだった。
微分方程式をグラフ化する関数としてplotdf()があるが、parametric plotができないようだ。
integrate()で定積分したものをplot2d()でparametric plotすればいいかと思ったが、残念ながら上記の関数のintegrate()は計算されなかった(erf混じりの非数値解になる)。

上記のx',y'を定積分したものはフレネル積分と呼ばれるそうで、Maximaにfresnel_c(), fresnel_s()があったので、今回はそれを使うことで良しとした。

●Maximaへの入力

plot2d([parametric, fresnel_c(t), fresnel_s(t), [t,-6,6]],[x,-1,1],[y,-1,1],[style,lines],[nticks,1000]);

●出力(ブラウザがSVGを表示できない場合→ PNG
Clothoid curve

車のハンドルを一定の速度で回していくとできる曲線だそうだ。

See more ...

Posted at 23:55 in 数学 | WriteBacks (0)
WriteBacks

Jul 18, 2011

JavaアプレットでSVGを再生する(2)

以前にBatikを使ってJavaでSVGを描画したり書き換えたりしてみたが、特にWebブラウザ上で動かすJavaアプレットを作成する目的ではあまり満足のいく結果が得られなかったので、もう1つ気になっていた、軽量が売りのSVG Salamanderも使ってみることにした。

SVG書き換え再生テストの起動ページ

ソースコード
svgSalamanderTest1.java アプレット本体
SVGIconOnJPanel.java アイコン描画用にダブルバッファリングを有効にしたJPanel
BouncingIcon.java
SVGファイル
txtanitest1s.svg 文字列書き換えテスト用SVG
p_icon.svg アイコンのSVG

前回と同様に、SVGの文字列を動的に書き換えて再生する。このSVGの表示には、JPanelを継承していてJAppletに組み込みやすいSVGDisplayPanelクラスを使っている。
それとは別に、SVGIconクラスはjava.awt.Graphicsに描画できるので、Swingのコンポーネント上も含めて、アイコンを動かしながら表示してみた。
ちなみに、Popボタンを短時間に連打するとアイコンが初期サイズまで戻らなくなるのは、仕様である。

以下、今回何か作ってみてわかった、SVG Salamanderを使う上での注意事項をまとめる。

まず、再生可能なSVGはかなり限られると思っておいた方が良い。SafariやBatikのSquiggleでは思い通りに再生できるのにSVG Salamanderでは思い通りに再生されないということは頻繁に起こった。それがSVG的に正しくない(SafariやBatikは気を利かせて補間している)からなのかSVG Salamanderの対応が不十分なのかはあまり追究していないが、何せ、SVG Salamanderを使うなら、svgSalamander.jarを実行すると起動するSVGプレーヤーで再生確認しながら、SVGファイルを編集することになる。

SVG Salamanderの描画がSafariやBatikと違ってしまう要因の1つは、ECMAScriptが使えないことである。<script>タグが含まれるSVGファイルはSVG Salamanderでは正しく再生されないのである。動的なSVGコンテンツにはよくECMAScriptが使われるので、どこかから拾ったSVGはこれが原因で再生されないことが少なくない。

他に、SVG SalamanderのSVGの扱いに関して筆者が気づいたこととして、パスデータ(<path>タグのd属性などで与えられるもの)に、"C"/"c"(curveto)や"Q"/"q"(quadratic Bézier curveto)が先行せずに"S"/"s"(smooth curveto)や"T"/"t"(smooth quadratic Bézier curveto)があると、まず期待した動作にならない。SafariやBatikでは1つ目のcontrol pointを始点(またはその閉パスの最後のcontrol point?)とすることで突拍子も無い表示になることを避けているようだが、SVG Salamanderは2つ目のcontrol point或いは終点の、始点からの反対方向の鏡像点を1つ目のcontrol pointとしている節がある。

次に、Javaライブラリに関して気付いたことをまとめる。

SVGのテキスト要素の文字列の先頭や終端に余分な空白があると、描画時とText#getBoundingBox()実行時とで空白の扱いが異なってしまうようで、内部の計算位置と表示位置にずれが発生してしまう。これはSVGファイルの<text>〜</text>で括られたテキストの先頭や末尾の改行や空白についても同じことが起こるので、Javaコード内だけでなくSVGファイル内でも空白文字を消しておく必要がある。

SVGにフォントサイズのアニメーションがあると、SVGUniverse#updateTime()では表示に反映されないようだ。内部的に値は更新されるようで、Text#rebuild()すれば文字サイズに反映されるが、透明度のアニメーションと組み合わせると、ちらつく上、Text#rebuild()時に変化中の透明度が無視されて不自然な表示になった。

SVGElementクラスにhasAttribute(), setAttribute()があるのにgetAttribute()が無いのが謎である。現在の値からいくらか変化させるということができないことを意味する。
また、現実的な問題として、printfデバッグのために、その時点での属性の値を取得したいということはよくあったが、その手段が無かったのが結構辛かった。

それから、色々なクラスのset系のメソッドの引数にある、attribTypeの意味がわからない。JavadocのAPI referenceには与え得る値も何も書かれていない。今回は"Using SVG Salamander"のページのサンプルコードに書かれているAnimationElement.AT_XMLを一律に指定しているが、これで正しいのかどうかはわからない。

BatikのJSVGCanvasはSVGの表示位置が自動的に中央寄せになるが、SVG SalamanderのSVGDisplayPanelでは左寄せになってしまう。しかも、中央寄せにするメソッドが無い。SVGファイルの<svg>タグのviewBox属性を書き換えれば位置調整ができるが、メモリにロードしたviewBox属性を更新する手段がない。SVGDiagram#getRoot()で取れるSVGRootのprivate属性にはあることがわかったが、getAttribute()メソッドが無いので、値を取得することすらできない。
今回は、SVGDiagramのgetViewRect()とgetDeviceViewport()で得られた座標を元にSVGのviewBox属性を直接書き換えるという強引な方法で、何とか中央寄せができた。(svgSalamanderTest1.javaのcenterViewBox()参照)

最後に、Webサーバーに配置する時の注意点として、svgSalamander.jarはSVGプレーヤーが内蔵されていたり署名されていたりするので、そのSVGプレーヤーも署名する必要も無ければ、ライブラリとしての実行用にはsvgSalamander-tiny.jarを使うと良い。

See more ...

Posted at 22:32 in Java | WriteBacks (0)
WriteBacks

Jul 03, 2011

3位

B級で3位だった。
ShoujouTate

調整が不十分で、ついでに朝から頭痛で、予選落ちしてもおかしくなかったにしては、上出来だった。
準決勝の相手(優勝者)が別格に強かったので、十分調整して万全の体調であっても、良くて3位だっただろう。

結構嬉しかったので、自分へのお祝いに、携帯電話をmovaからFOMAに変更した。
携帯電話なんかよう使わんけど。

See more ...

Posted at 23:09 in 将棋 | WriteBacks (0)
WriteBacks

Jun 18, 2011

n個のサイコロの目がk種類になる確率

次のような感じの確率を求めようとしたら、泥沼にはまった。

Q: サイコロをn回振った時、出る目がk種類になる確率は?

A:
k=1の確率は、n回全て同じ目で、その目は6通りあるから、6/(6n)である。
k=2の確率は、場合の数が(n回全てaかbの場合 − n回全てaまたはn回全てbの場合)×((a,b)の組み合わせ)だから、(2n-2)(6C2)/(6n)である。
k=3の確率は、場合の数が(n回全てaかbかcの場合 − n回全てaかbの場合 − n回全てbかcの場合 − n回全てcかaの場合 + n回全てaまたはn回全てbまたはn回全てcの場合)×((a,b,c)の組み合わせ)だから、(3n-3*2n+3)(6C3)/(6n)である。
つまり、k種類の値を固定した時の場合の数が包除原理に従っているので、答は
\frac{1}{6^n}\pmatrix{6 \cr k}\sum_{i=1}^k(-1)^{k-i}\pmatrix{k \cr i}i^n
である。(括弧内に2つの数字が縦に並んでるのは二項係数、(6 k)は6Ckと同じ)

サイコロの目の数6をmに一般化して整理すると、等しい確率でm通りの値を取るn個の変数の値がk種類となる確率P(m,n,k)は
\pmatrix{m \cr k}\sum_{i=1}^k(-1)^{k-i}\pmatrix{k \cr i}\left(\frac{i}{m}\right)^n
となる。

See more ...

Posted at 21:54 in 数学 | WriteBacks (1)
WriteBacks

AFAIC that's the best ansewr so far![link]

Posted by Daisy at 07/20/2011 08:01:06 PM

May 29, 2011

JavaアプレットでSVGを再生する

ベクターグラフィクスのフォーマットに、SVGというのがある。GIMPやDiaなど、画像をベクターグラフィクス形式で保存することをサポートしている場合、そのフォーマットはSVGであることが多い。SVGがオープンな規格であることがその理由であることは想像に難くない。特に理由が無ければSVG形式を採用することになるのであろう。
SVGは、フォーマットがXML形式であり、それでいて、Adobe Flashと同様、アニメーションや、マウス操作等の入力に対する動作を記述することもできる。何て理想的でパーフェクトなのであろうか。
アニメーションするベクターグラフィックだとFlash形式が使われることの方が圧倒的に多いが、特に静止画像だとSVGはWikipediaでもよく使われており、マルチページで文書用途のPDFやPostScriptを除くと、既にデファクト・スタンダードになっていると思う。

筆者としては、SVGはテキストエディターで編集できるというのが特にポイントが高い。EmacsやPerlやPythonで扱い易いかどうかというのは根本的な問題であり、それを満たすものがあるならそれを満たさないものは無いのである。よって、筆者としてはFlashは無いのである。

しかしながら、SVGは環境によっては正しく再生されないことがしばしばある。筆者の自宅にあるWindows XPでは.svgファイルをダブルクリックしても開かないし、Internet Explorerでは、表示されてもアニメーションは動かない。Mac OS X 10.5のSafariではアニメーションも大体動くようだが、実に惜しいことに、α付きのフィルターが働かないようである。そんなのは些細なことだという話もあるが、たまたまそれを試したくてSafariでプレビューしながらSVGをEmacsで書いて思い通りに表示されず、何が間違ってるのだろうと悩んだ果てにSafariがそれに対応していないと知った時の心の傷は、深かったのである。

そんな訳でSVGの別の再生方法を探していると、Batik SVG ToolkitというJavaのパッケージを見つけた。まあまあ再生の成功率が高いようである。このサイトにあるMoving GearsというSVGのアニメーションが正しく表示されるのは、筆者が試したフリーのプレーヤーの中では、このBatikに含まれるSquiggleというプレーヤーだけであった(同サイトで指定されているOpera 9やAdobe SVG Viewer(サポート終了)は試していない)。
しかし、わざわざSVGを再生するのにJavaを起動することは無かろう、とパスしようとしたが、JSVGCanvasのデモのページを見て、気が変わった。何と、SVGファイルが、HTMLのフォームへの入力に従って書き換えられながら再生されているのである。

Webブラウザで表示されている画像ファイルそのものがユーザーの入力に従って変化するというのは、意外と難しい。HTMLのsubmitボタンやJavascriptによりユーザーの入力がサーバーに送信され、サーバー側プログラムが動的に画像ファイルを生成すれば、似たようなことができるだろうが、クライアントサイドで画像ファイルを書き換えながら再生できるのは、プラグインのプレーヤーならである。また、再生時の画像ファイルの加工方法として、例えばFlash VideoのメタデータをActionScript(Flash Videoファイル内の)やJavascriptで書き換えながら再生するというような、付属的なメタデータを動的に変更することはよくなされているようだが、上の例では、SVGファイルの相当コアな部分にあるベクトル図形が、Javaのコードで、しかも単なるXML APIで書き換えられているのである。

これは、筆者のようなJavaをかじった者に、触ってみろと言っているに違いない。

SVG書き換え再生テストの起動ページ
ソースコード
SVGファイル

Restartボタンを押すと、SVGファイルのid="TheString"の要素のテキストが書き換えられる。

それだけのことであり、SVGファイルを読み込んで再生する部分はJSVGCanvasのデモのページAppletDemo.javaから丸ごと拝借したのだが、実際に作ってみると、色々あった。

まず、アニメーションの再生終了後にSVGファイルをリロードせずにもう一度最初から再生する方法がわからなかった。
それくらいのI/FはJSVGCanvasクラスにあっても良さそうに思ったのだが、それらしいのは見当たらず、実際にいろんなメソッドを呼んでみたが、再開はしなかった。
結局、batik-users MLのアーカイブで見つけた、SVGAnimationEngine#setCurrentTime()を使う方法でできたが、そのメールでもこれが本当に正しいかどうかわからないと書いてあるし、Batikのjavadocを読んでも妥当性がさっぱりわからない。

次に、Safariでは発生しなかったが、IEでは、ネットワーク越しのSVGファイルのロード開始後になかなかアニメーションの再生が始まらないという問題が起こった。
当初はHTTP上のXML parserが何らかの理由で完了しないからかと思ったが、ファイル全体をStringとして保存してからparseするようにしても、さらにSVGファイルをJARに含めてそれを読み出すようにしても、直らなかった。
SVGファイルが参照するファイルの読み込みに時間がかかるのかと思って、svg11.dtd等の参照ファイルを全てローカルに置いても変化が無かった。
たまたま、JavaコンソールでGCさせるとアニメーションが開始することに気付いたので、色々なイベントリスナーでSystem.gc()を呼ぶようにしてみたが、効果が無かった。しかし、苦し紛れに、スレッドを作ってSystem.gc()を繰り返してみたら、すぐに再生が始まるようになった。
従って、やはり何らかのタイミングでSystem.gc()すれば良いのだと思うのだが、改めてSVGLoadのlisterやSVGLoadEventDispatcherListenerなど色々なイベントリスナーで、invokeLaterやsleepもしながらSystem.gc()してみたが、適当な場所は見つからず、結局別スレッドでGCする以外では解決しなかった。

後に、batik-users MLのアーカイブに詳しい原因が書いてあるのを見つけたが、Batikを改造しなくて済む回避策は書かれていなかった。Subversionには何らかの修正が入れられたようだが、それはBatik 1.7のリリース後のことのようである。

さらに、アニメーションが始まるまで要素を表示しない方法ではまった。
今回のSVGのテキストの下の角丸矩形は、テキストによって長さを変える必要があるので、その長さをECMAScriptで設定するようにした。そのため、それが呼ばれるまでは矩形の長さが不正であり、アニメーション開始前から表示するとちらつきが発生してしまう。
当初は、SVGの各要素をvisibility="hidden"にしておいて、onload時に矩形の長さを設定し、アニメーションのonbegin時にscriptでsetAttribute("visibility", "visible");するようにしていたのだが、Safari 5.0では<animation>タグのonbeginが効かないことが判明した。MacではSVGファイルをダブルクリックするだけでSafariが開いてアニメーションがほぼ完璧に再生できるので、SafariでレビューしながらEmacsでSVGを編集していた。

今回、その便利さを諦める気になれなかったので、Safariに合わせて、onbeginを使わないことにした。
それではと、onload時にvisibleにすると、それが矩形のサイズ変更後であっても、ちらつきが発生してしまったり、アニメーションの開始まで間があると画面が固まって見えてしまったりした。
アニメーションの開始直前にvisibleにすることができないのであれば、アニメーションの途中でvisibleにするしか無い。<animation>タグでvisibleとかinvisibleとかの定性値を変化させることもできるようだが、今回はopacityを0から1に変化させることで徐々に見えるようにした。

その前に、scaleが1だと小さく表示されるような座標で作って、アニメーション中にscaleを増やすことにより、アニメーションが始まるまでは不正な表示になっても目立たないようにしていたのだが、アニメーションの最後にopacityを変化させてフェードアウトするようにすると、Batikでもう一度最初から再生するとopacityが1に戻らず、opacityを変化させるまで表示されないということが起こってしまった。
SVGファイルの作り方の定跡は調べていないが、小さく表示してごまかすのは災いの元だと教えられた。

さらに、Batikで単にSVGAnimationEngine#setCurrentTime()でリピートするとonload時のスクリプトが実行されない問題があった。
SVGファイルのECMAScriptの関数を明示的に呼び出す方法がわからなかったので、ScriptingEnvironment#dispatchSVGLoadEvent()でSVGLoadイベントを発生させてonloadのスクリプトが実行されるようにして解決した。
SVGファイルの作り方の常道は知らないが、アニメーションの時刻を戻す可能性があるなら、時刻変更の度にonloadの処理を実行しなくて済むよう、初期化処理はonloadでせず全てonbeginでやる方がいいのかも知れない。

See more ...

Posted at 22:27 in Java | WriteBacks (1)
WriteBacks

Posts like this brighten up my day. Thanks for taknig the time.[link]

Posted by Holland at 07/20/2011 02:15:07 PM

Apr 29, 2011

アジャイルセミナー傍聴録

いつも返却ポストとして利用している図書館で、参加費無料のアジャイルソフトウェア開発のセミナーをやるというので、今借りてる本の返却期限はまだであるが、自転車を30分漕いで行ってきた。

【内容】

  1. Kent Beck氏からのビデオレター上映
    被災した日本の皆様にお悔やみ申し上げますって感じの20秒くらいのもの。
    再生後、日本語訳が説明され、それを踏まえてということで、もう一度再生された。
  2. テクノロジックアートの長瀬氏による講話
    後述
  3. ThoughtWorks社のDavid Joyceという人のオーストラリアからのテレ講演
    System thinkingとかLean開発とか
  4. パネル討論会
    後述

【長瀬氏のお話】
これまでは、アジャイル開発をやってきた人はオブジェクト指向のプロフェッショナルだったりして、アジャイル開発でうまく行ったという話も、アジャイル開発でなくてもうまくできるような人がやってた。それに対して、最近はウォーターフォールをやってた所がやり始めている。

アジャイル開発を始めるには、まずそこのカルチャーを見極めないといけない。きちんとドキュメントを作ってきた所なのか、インターネット系でオープンソースをばりばり使ってるのか、新しい技術が好きで次々に取り込んでるのか、若い人中心でゲーム感覚で作っているのか。

日本ではアジャイル特有の言葉はあまり使わない方がいい。既存の概念に囚われない目的でそうするものだが、既存の概念を捨て去るのは合わない。
全員がプログラムも設計もできる、というようにするのは難しい。それらは分業することになるが、そうするとオペレーション(イテレーションの周期)が2週間では厳しい。4週間とかになるだろう。

アジャイルにはオブジェクト指向設計が大事。最適な設計はオブジェクト指向設計から。やったことがない所ならオブジェクト指向の教育をみっちりと。

アジャイル導入には、まず手順書を作ること。テストを作ってから中身を作って、とか、それぞれの人の役割をはっきりするとか。それにはじっくり1ヶ月はかかる。

テスト駆動開発はユーザーの要求を漏れなく反映できるかにかかっている。欧米ではそのためのしっかりしたツールがあるが、欧米ではユーザー(顧客)が技術に明るいことが多く、ツールの作りもそれが前提になっている。それに対し、日本のユーザーは漠然とした要求しか出さないケースが多いので注意が必要。
ツールを使ったら使ったで、その内毎日のCI(Continuous Integration)つまり結合と自動テストが夜中に終わらないということも起こることがある。考えるべきことは多い。
拠点が分散しているとツールを使わざるを得ない。しかし、日本ではこれまでアジャイルは1つの拠点で小規模にされることが多かったので、アジャイル特有のツールが広まっていない。

【パネル討論会】
テーマ:アジャイルは失敗するって本当ですか?
パネラー:長瀬さん(T)、細谷さん(H)、永田さん(N)
司会:前川さん(M)

M: 本当です。
アジャイルは今第2次ブーム。
アジャイル宣言から10年、最初は技術者が主体だったが、ちょっと下火になった時期があって、今は経営陣が興味を持つようになってまたブームになってきた。
それ故、十分な知識が持たれないことが増えてきた。

(以下、Qは会場からの質問、Aは会場からの回答、Cは会場からのコメント)
M:パネラーの皆さんにとって、Agileとは、一言で言うと?
H:開発をマネジメントする為の有効なフレームワークの1つ。
N:"interplay"
(JAZZの用語、誰かがピアノを弾いてる所に、阿吽の呼吸で合わせていくようなこと。
営業でも開発でも、メンバーの誰かが課題やアイデアを持ったら、他のメンバーがそれに合わせて動く、のような意味合い。)
T:日本のソフトウェア開発を崩壊させるかも知れないもの。
それについていけないと、日本のソフトウェア開発が無くなってしまうもの。
M: 皆さんにとって、何をもってAgileが成功したと言えるか?
H: お客様が満足するか、プロジェクトが計画通りに進むこと。
N: Deliveryを満たすこと。
T: 日本では、イテレーションが回るようになったこと、開発が楽しそうであることを言うのではないか。
お客様が要求をはっきり言わず、具体的な要求は変化するので、機能追加型で開発できないといけない。その為には、リファクタリングもできないといけない。そこまでできて、イテレーションが完結すると言える。
Q: アジャイルを始める動機は何が多いか?Waterfallに失敗したから?
T: Waterfallが失敗したから、と言って相談に来る人はいない。このままではダメになるのではないか、Waterfallだけではだめなのではないか、という感じの漠然とした危機感を持っている人が多い。
Q: 欧米では、組み込み系と業務用システムで、どちらの方がAgileが成功しているか?
(中略)
H: ドメインによって違いはあると思う。
ハードウェアまで作り込むとか難しい物理的な制御をするなら、最初にある程度きちんと作らないと、全然動かない。
業務用システムを作るなら、最初は簡単に作って見てもらうことも可能。
T: 欧米では、開発が相当早い。
CIが活用されていて、毎回3,000のビルドが行われたりしている。
ツールチェーンが確立していて、ストーリーカードから実装、CIまでが繋がっている。
ビジネスアナリストからエンジニアまで、速く作れる体制が整っている。
ビジネス分析者がエンジニアと同じ稼ぎ。
ソフトウェア工学的には、日本はかなり遅れていると思わざるを得ない。
Q: 管理するツールという面で、Redmineはどうなのか?
A(阪井さん): 何の為に使うかによる。ツールはプロセス改善のために導入されるべきもの、何の為にツールを使うかを明確にすることが大事。
H: Redmineでは、メンバーにある程度マネージメントの権限を委譲できるのが良い。
ガントチャートを更新するというのは結構大変な作業。
但し、より上位のスケジュールとの差異をどう管理するかが問題。
M: Redmineの失敗事例として、ただチケットを発行して現場任せにして、遅れがあれば催促する、ということをやって、現場の担当者がチケット恐怖症になり、自分からはチケットを発行しないようになったということがある。
T: ツールを使うのが目的になるのではなく、マニュアル(手作業)でやってみて問題があったらツールを使う、というのが正しい。
欧米ではツールとマニュアルと両方やっている。ツール使いながらストーリーカードが壁に貼ってある。
M: PDCAを回す(計画を直しながら進める)のとタイムボックスを守るのとの違いは?
N: Agileはプロセスなのか、プロセス改善なのかという話があった。
Engineeringから見ると、Agileはなかなか大変だと思う。
H: 不安感が生産性に影響すると思っている。漏れ聞こえる噂に左右される。
タイムボックス化の効果は、2週間は邪魔が入らず集中できること。
M: 結局、マネージャーが、このメンバーで何が作れるか、どう成長するかをはっきりと予想できるかどうかにかかっているような気がする。
H: そこまでわかってたらWaterfallでできるのではないか?
C: 2002年くらいの論文では、Waterfallは見直されていて、2回回せばいいという論文も出ている。
?: Waterfallの知識が無いとAgileはできないと思う。Waterfallは、プロジェクト検証の過程が無いのが問題なだけではないか。
H: WaterfallでもAgileでも、実行可能だと大多数の人が思っている計画しかうまくいかないというのが真実ではないかと思っている。スキルが上がると、Waterfall力がついてくる。
Q: Agileって儲かるのか?
T: 儲からないと思う。
ユーザーから見て、Waterfallは途中が見えないから博打、Agileは見えるから安心ではある。開発とユーザーとの信頼関係は上がる。しかし、Agileは失敗したらユーザーの責任になることがあまり理解されていない。
M: これからAgileを始めたい人に一言
H: 失敗する所はちゃんとわかってやらないから失敗する、という話もあるが、興味あるならやってみれば良いと思う。
N: 海外の人は、AgileはEngineeringだという意識が強い。だから進んでいる。
Lean開発の目的がqualityになってるのがやっぱり凄いと思った。
T: 大手は大体そのどこかではやっていて、失敗した経験も持っているので、今後は失敗は減っていくだろう。
最初から失敗したくなかったら、コンサルタントを雇うとか、金が無かったら、こういうセミナーで擬似的にやってみるとか。
(その他の会場から出た質問で答えが出なかったもの)
Q: 外注さんが含まれる場合、どうお願いすればいいのか?
Q: 詳細設計ってどうやるのか?

See more ...

Posted at 23:07 in PC一般 | WriteBacks (0)
WriteBacks

Apr 25, 2011

StrategyパターンとVisitorパターンの使い分けに関する考察(4)

これまで[1][2]にStrategyパターンとVisitorパターンそれぞれで作った引力モデルのシミュレーションに対して、以下のような要素を追加してみる。

  1. 物体の種類として、Square
    Squareの特徴:
    • 縦か横にしか動かない(縦方向か横方向かどちらか速度の大きい方に動く)
    • 但し速度は2次元(一方が空回り)で、全方向の引力の作用を受ける
    • 標準の引力は通常の距離の2乗に反比例する引力
    • 標準色は緑
  2. 引力計算の種類に、引力の方向が相手の方向より少しずれるCurlGravityを追加する
  3. 色設定の種類に、Blinkを追加する
それぞれ、PhysicalObject, GravityStrategy/Visitor, ColorStrategy/Visitorのクラス階層へ何かを追加するという例である。

Strategyパターンによるものに対する変更は、次のようになる。
class diagram
元のクラス図に対して、黄色で示されたBlink, Square, CurlGravityの3つのクラスを追加している。

これに基づいて変更したソースコードとJavaアプレットを、次のリンク先のページに置く。
・StrategySample3のアプレットとソースコードのページ
ソースコードの差分は、詳しいdiffの出力を末尾に載せているが、 Square.java, CurlGravity.java, Blink.java の3ファイルが新規に作られた他は、変更されたファイルは SampleApp.java の1つのみであり、その変更も、新たに追加したSquare, CurlGravity, Blinkの3つが選択できるようにGUIのボタンを追加したりボタンの動作を変更したりするものだけであり、それらを使わないアプリケーションには必要の無い変更である。
つまり、本体側のサブクラスの追加もStrategyの追加も、既存のクラスに全く手を入れることなく行うことができる(†追記部分に補足あり)ということであり、いずれの場合も、オブジェクト指向設計の基本であるであるOpen-Closed Principleを満たしていることが明らかである。

一方、Visitorパターンによるものに対する変更はかなり多い。
class diagram
元のクラス図に対して、黄色で示されたBlink, Square, CurlGravityの3つのクラスを追加した他に、Visitorの階層のGravityVisitor, DefaultColorizerを除く全ての既存のクラスに変更が入っている。

これは、Visitorインターフェースにvisit(Square)を追加した為、Visitorインターフェースを実装する全てのクラスにvisit(Square)を追加する必要があるからである。もちろんVisitor階層で実装を継承できる場合は追加不要だが、Visitorパターンがその効果を発揮する用途ではVisitor同士は役割が類似しないことが多い(後述)というよりむしろ全く異なることが多い為、Visitorインターフェースが変更されても変更せずに済むのは、親クラスを僅かに拡張をするようなクラスに限られる。
また、Visitorインターフェースにvisit(Square)を追加しなくても良いのは、SquareがVisitorを一切acceptしない(accept()が何もしないか例外を投げる)場合のみである。(accept()でのvisit(this)はコンパイルエラーになる)

これに基づいて変更したソースコードとJavaアプレットを、次のリンク先のページに置く。
・VisitorSample3のアプレットとソースコードのページ
ソースコードの差分は、同様にdiffの出力を末尾に載せているが、 Square.java, CurlGravity.java, Blink.java の3ファイルが新規に作られた他に、 SampleApp.java, ColorVisitor.java, DefaultGravityApplier.java, Gradation.java, NegativeColorizer.java, NormalGravityApplier.java, RepulsionApplier.java, Visitor.java の8つのファイルが変更されている。
SampleApp.javaの変更は、Strategyパターンの場合と同様、使用者側が新たなクラスを使う為の変更であるが、その他は既に実装されているメソッドをcopy&pasteしたような怠惰な追加である。末尾のdiffの出力は先頭が+の行が追加された行であり、変更箇所の前後3行が参考の為に表示されているが、SampleApp.javaを除く前述の7ファイルの追加内容は、それらのすぐ上に同一または類似の処理があることが見て取れると思う。いかにも冗長である。

ただ、これら7ファイルは全て、PhysicalObjectの階層にSquareクラスが追加されたことに対応してvisit(Square)が追加されたものであり、CurlGravityやBlinkの追加に伴って発生した変更ではない。よって、VisitorパターンはVisitorの追加に対しては変更箇所が閉じている(Open-Closed Principleを満たしている)ことがわかる。
繰り返しになるが、visit(Square)を追加しなくて良いのはSquareがVisitorをacceptしない場合のみであり、それはVisitorパターンの適用外ともいうべきもので、そういう場合には変更に閉じていると言えるものではない。

以上より、StrategyパターンとVisitorバターンの違いとしては、次のようなことが見られる。

  • Visitorパターンの場合、本体側のクラス階層にサブクラスが追加されると、Visitor階層全体に変更が及ぶ。
    Visitorパターンの宿命のようである。
  • Visitorパターンでは、いずれのVisitorクラスも、本体側の全ての具象クラスについて別々のメソッドを持つ。
    具象クラス毎に処理が異なることが少ない場合は、適しているとは言い難い。一方、Strategyパターンでは、具象クラス毎に処理が異なるStrategyのみ、具象クラス毎にStrategyのクラスを別にすることが可能である。
  • Visitorパターンでは、本体側のクラスが主体となってその処理を実行することができない。
    accept()が呼ばれるまではVisitorが実装する処理を実行できない。その為、例えばメソッドの途中でVisitor側にある処理を呼ぶことは困難である。(抽象Visitorクラスがイベント発行要求を受け付けて、Visitorインスタンスを管理するクラスに通知して、acceptを呼ぶような、トリプルディスパッチが必要かも知れない)
  • Strategyパターンが本体側のクラスのインスタンス毎にStrategyを持つのに対して、Visitorパターンは特定のインスタンスとの関連が無い。
    切替可能な処理を繰り返し実行するのであれば、Visitorパターンの場合はVisitorのインスタンスを別に管理する必要が生じる。
    切替可能な処理を1回だけ、複数のオブジェクトに対して実行するのであれば、Strategyパターンの方が処理が煩雑になる。全オブジェクトに(抽象化された)同じ処理を1回だけ適用したい場合には、Visitorパターンが有利である。
  • Strategyパターンの場合は、Strategyの使われ方が決まっているので、追加できるStrategyの自由度は限定的だが、Visitorパターンの場合は任意と言うに近い自由度で処理が追加できる。

そもそも、Visitorパターンが有効な場合は相当限られると思う。
適用されるクラス群は抽象化されているのだからそれなりに共通の特徴を持つだろう が、
・Visitorから見るとクラス毎に処理が違うくらいにはサブクラスは異なる特徴を持ち、
・Visitorが行う抽象的な処理の種類はStrategyとして共通の特徴を持たないくらいには異なる、
ような場合ということになる。筆者がこれまでに見たことがある例は

  • オブジェクトダンプのようなデバッグ表示(toString+printのようなもの)
  • ファイル保存などのための、オブジェクトのフォーマッティング
くらいであるが、他にはなかなか思い付かない。ファイルハンドルのように、ストレージはファイルシステムかHDDかデータベースかネットワーク越しの何かかわからないようなものに対する処理を追加できるようにしておくような場合だろうか。

See more ...

Posted at 23:56 in PC一般 | WriteBacks (0)
WriteBacks

Apr 17, 2011

StrategyパターンとVisitorパターンの使い分けに関する考察(3)

前のエントリーでStrategyパターンで作った引力モデルのシミュレーションとほぼ同じものを、今度はVisitorパターンで作ってみる。


class diagram

Strategyパターンの場合との全体的な構造上の違いとして、本体のクラスに切替可能な処理(またはアルゴリズム)への関連が無く、処理を実装するクラスから本体のクラス階層への関連がある。具体的には、PhysicalObjectクラスにVisitorのメンバが無く、Visitorの具象クラスから本体の具象クラスへの依存がある。

切替可能な処理の構造の違いとしては、Strategyパターンでは本体の具象クラス毎の既定の処理をStrategyでなく本体側に入れることが可能であったのに対して、VisitorパターンではそれらをVisitor側に定義する必要がある。もし本体側に実装しても、それを呼び出す仕組みが必要になるので、Visitor側にクラスを定義するのは避けられない。
また、Strategyパターンでは処理が無い場合は無処理のStrategyを定義する必要があった(特にStrategyが値を返す場合)が、Visitorパターンでは無処理ならVisitorを定義する必要が無い。
具体的には、各PhysicalObjectの標準の処理の実装のために、DefaultGravity, DefaultColorizerというクラスを定義しており、無重力の場合は引力計算の処理の必要が無いので、NoGravityApplierはのようなクラスを定義していない。

なお、ColorVisitorのサブクラスにて各PhysicalObjectの標準色を使う場合があるため、
標準色の設定処理はColorVisitorクラスに実装するようにし、DefaultColorizerは、ColorVisitorをそのまま引き継ぐ、インスタンス生成可能にするためだけの空のクラスとしている。ColorVisitorを抽象クラスでなく具象クラスにすればDefaultColorizerクラスが不要になるように思えるが、そうすると、ColorVisitorが標準色の設定の役割を兼ね、ColorVisitorのサブクラスが標準色の設定の役割を持つColorVisitorとして振る舞えることになってしまい、いわゆるリスコフの置換原則に反してしまうので、好ましくない。

以上の方針で実装したのが、下のリンク先のページのJavaアプレットである。(ソースコードへのリンクもあり)
・VisitorSample2のアプレットとソースコードのページ

StrategyパターンのサンプルではボタンによるStrategyの切替がそれ以後に追加される物体のみに有効になるのに対し、Visitorパターンのサンプルでは、フィールド上にある全ての物体に対して切り替わる。
WiredStarについては、同じVisitorでもvisit先の具象クラスによって処理を変更する例として、全てのGravityVisitorのvisit()を空にし、常に無重力の状態にしている。

オブジェクト毎に別々のVisitorを適用するようにしていないのは、そうするためにはアプリケーション側でオブジェクトとVisitorとの対応を管理しないといけなくなり、Visitorパターンのメリットが大きく損なわれるからである。

次のエントリーで、StrategyパターンとVisitorパターンの例に対して、本体と切替可能処理のそれぞれのクラス階層にクラスを追加してみる。(続く)

See more ...

Posted at 20:01 in PC一般 | WriteBacks (0)
WriteBacks

Apr 10, 2011

StrategyパターンとVisitorパターンの使い分けに関する考察(2)

StrategyパターンとVisitorパターンの応用例として、簡単な引力モデルのシミュレーションを作ってみる。引力の計算方法は外部クラスに存在させ、既存クラスを変更せずに追加/変更可能にする。
なるべく簡単にするため、次のような制限をつける。
・全物体の質量は同じ
・空間は2次元
・引力は2物体間の距離だけで決まる

まず、Strategyパターンを応用する例を考える。
引力の計算方法についてStrategyパターンを適用し、クラス構成は、次のようにする。

class diagram

PhysicalObjectクラスの階層(緑部分)が物体の位置や速度を持ち、GravityStrategyクラス/インターフェースの階層(水色)が引力の計算処理を持つ。抽象レベルでPhysicalObjectがGravityStrategyに関連づけるため、PhysicalObjectの基底クラスがGravitystrategyへの参照を持つ。
NormalGravityは距離の2乗に反比例する引力、Repulsionは距離の2乗に反比例する斥力、NoGravityは引力なしである。

GravityStrategyが定義するメソッドは、計算結果を返すようにする方が自然だが、今回の例では、そのまま計算結果をPhysicalObjectに反映するようにしている。これは、Visitorとの類似性を追究する目的のため、そのようにした。その為、 PhysicalObjectの値を更新する為のaccessor(VelocityControllerインターフェース)が必要になっている。

Strategyパターンとして、そういう実現方法は許されるのかという問題があるが、一般に計算結果が1つの値とは限らないし、Strategyに委譲する処理が複雑になるほど、戻り側で必要な値が増える可能性があるし、出力する値の個数が決まっていると拡張する範囲が限られてしまう。
また、入力としてオブジェクト丸ごとでなく、最低限のパラメーターだけを渡す方がいいという考え方もあるが、やはりそのパラメーターの数が決まっていると拡張性が制限されてしまう可能性がある。
それに、入力のデータ型を新たに定義せずに委譲元のクラスそのものとするのであれば、出力のデータ型についてだけ、戻り値を格納できる新たなデータ型を定義するのはすっきりしないし、一般にStrategyの計算結果は中間データなので、委譲元のクラスには格納できない。
よって、Strategyへの入力を委譲元のオブジェクトそのものとし、併せてそれへのaccessorを渡すことにより、計算結果の反映までをStrategyに委譲する方法は、1つの妥当な方法だと考えられる。
Strategyパターンの本質は、クラスの一部の処理を差し替え可能な形で別のクラス(Strategy)に委譲することにより、既存クラスを変更せずに処理を追加できるようにすることにあるので、Strategyクラスに対して既存クラスを隠蔽することは優先されないと、筆者は考える。

Strategyを呼び出すのはPhysicalObjectクラスのupdateVelocityメソッドで、このメソッドは存在する自分自身以外の全ての物体についてStrategyを呼び出すことにより、他の物体からの引力作用を自身の速度に反映させる。
物体の形状は、PhysicalObjectが、形状そのものではなく、形状の描画方法として定義する。抽象的なPhysicalObjectは形状を持たないので、具体的な描画方法はPhysicalObjectの各サブクラスが持つ。

ついでに、描画時の色をStrategyパターンで切り替えられるようにもしてみる。
物体の色は、物理的特徴の1つとしてPhysicalObjectに持ち、ColorStrategyによって標準色から変更されるとする。ColorStrategyがnullなら、標準色とする。

Strategyパターンの実装として、Strategyを無設定にすることが許されるかという問題があるが、よくわからないので、そういう問題があることをメモしておく目的で、ここでは無設定を許すとする。
おそらく、デフォルトの処理を本体に持つかStrategyに持つかという問題に関係していると思う。デフォルトの処理が原始的で変更される可能性が無く、本体にあって自然なら、Strategyとしてnullが許されるのではないだろうか。
また、Strategyが計算結果を返すなら、Strategyがnullな状態を許すと、それに対応する計算結果と同じ型の値が必要になるので、違和感があるような気がする。
GravityStrategyの方は、無重力とは引力作用が無いということではなく、ゼロの引力が働いているものとして扱うため、明示的にクラス化している。

以上の方針によって実装したのが、次のリンク先のページのJavaアプレットである。(ソースコードへのリンクもあり)
・StrategySample2のアプレットとソースコードのページ
フィールド上をクリックすると、何らかの物体が置かれる。
"Disc", "Wired Star", "Star"のいずれかのボタンを押すと、クリックして置かれる物体が切り替わる。
"Switch gravity strategy"を押すと、次に置かれる物体の引力のルールが切り替わる。
フィールドは、表示されている領域の3x3倍の大きさがあり、それより外に出た物体は削除される。
標準(デフォルト)の引力と色は次の通り。

無指定時の引力無指定時の色
Disc引力水色
Wired Star無重力マゼンタ
Star斥力黄色

あとはソースコード参照。

次のエントリーでは、大体同じものをVisitorパターンで作ってみる。
(続く)

See more ...

Posted at 20:48 in PC一般 | WriteBacks (0)
WriteBacks

Mar 29, 2011

StrategyパターンとVisitorパターンの使い分けに関する考察(1)

今更ながら、かの著名なGoFのデザインパターンを復習している。

10年前に居た会社にGoF本の日本語版があり、たまに何とかパターンという言葉を使う人が居たので、その本を一通り流し読みしたことがあるが、その時はそれの重要性に気付かず、23種類のパターンのそれぞれについてなんとなくわかった気になったら、1行に要約して控えておいただけだった。
結局、その部署で耳にしたパターン名は「オブザーバーパターン」だけだったので、それ以外のパターンは全て忘れてしまった。

Observerパターンは要するに状態変化時のコールバック関数を登録する設計のことであり、特にGUIのイベントハンドラーを定義する仕組みでは頻出なので、忘れようが無いし、「コールバックモデル」とか「イベントハンドラー」とか、Javaなら「リスナー」とか言えば通じるので、もはや「オブザーバーパターン」という言葉を耳にすることも無い。もしソフトウェア開発の場で耳にしたら、何をカッコつけとんねん、と言いたくなるだろうし、「何かあったら電話して」と言われた時に「オブザーバーパターンですね」と答えるような用途は考えられないことは無いが、よほどのマニアでない限り、その洒落が通じることは無いであろう。

その後、デザインパターンへの興味を失ってしまったのだが、オブジェクト指向とは何かということに興味を持ち、時々図書館でそれ系の本を借りて読むようになると、GoFのデザインパターンがよく引用されているので、また目にするようになった。
というか、GoFのデザインパターン以外に、これぞオブジェクト指向設計と思うような例はほとんど目にしない。オブジェクト指向設計になっていても、実際に動作するアプリケーションになっていると、そのアプリが提供する機能に目を奪われてしまうからだろうか。

そこで、もう一度GoFのデザインパターンを復習した。

半年かかった。

23種類ってのは、1つ1つ取り組むと、思ったより多かった。
当初は1つ1つのパターンについてオリジナルなサンプルコードを作ることを目標としていたが、結構大変であることに気付いたので、方針変更して、興味を持ったテーマについてだけ書くことにした。


今回は、StrategyパターンとVisitorパターンの使い分けについて考える。全然違うもののようだが、特定の処理を交換可能にするという用途に限ると、似たような効果が得られるようである。

Strategyパターンとは、特定の処理を外部のクラスに置くことにより、既存のクラスを変更せずにアルゴリズムを交換可能にするパターンである。次のUML図は、StableClass以下を変更せずに、合計の計算方法を変更することを可能にする、Strategyパターンの適用例である。

これをJavaで実装したサンプルコードを、下の方に添付している。
StableClassを、計算対象のデータを保持する、変更不可なクラスとする。
StableClassが抽象的なSumStrategyへの参照を持っており、合計の計算はそれを介して行われる。具体的なSumStrategyは実行時に決まるので、StableClassを変更することなく、合計の計算方法を追加することができる。合計の計算方法として、通常の足し算でなく、掛け算を選択することができるように変更するには、新たなSumStrategyであるMultiplicationクラスを追加するだけで良い。

Visitorパターンとは、任意の処理を持つオブジェクトを受け付ける口を設けることにより、既存のクラスを変更せずに、様々な処理を後から追加できるようにするパターンである。
次のUML図は、上と同じことをVisitorパターンでやってみた例である。

Visitorパターンでは、visitorが操作対象となるクラス(以下visitee)をvisitすることをそのクラスがacceptするという表現が用いられる。
操作対象のクラスは、visitorのvisitメソッドを呼ぶだけの、acceptメソッドを用意する。抽象的なVisitorが提供するI/Fが呼ばれると、visitorはvisiteeの具体的なクラスを知らないまま、自身を引数にしてaccept()を呼び、visiteeのaccept()は、visitorの具体的なクラスを知らずに自身を引数にしてvisit()を呼ぶ。(accept()の呼び出し時にStableClassの具体的なクラスの特定が行われ、visit()の呼び出し時にVisitorの具体的なクラスの特定が行われる)
このdouble dispatchと呼ばれる2段階の呼び出しを経由することにより、StableClassとVisitorの結合は呼び出し時まで抽象化される。つまり、visitorとvisiteeのクラスの組み合わせによって決まる、実際に実行される処理は、実行時まで未確定にすることができるので、StableClassを変更せずに、新たなVisitorを追加できるのである。
従って、これによっても、新たな合計の計算方法を追加するには、図中のMultipleのようなクラスを追加するだけで良い。

一般的にはVisitorはVisiteeの全ての具象クラスをvisitできる必要は無いとされるため、上図のように、抽象Visiteeクラスにaccept()が無く、VisiteeからVisitorへの関連は、accept()を持つ具象Visiteeクラスから抽象Visitorへの関連とされる(accept()を持たない具象クラスからの関連は無い)ようである(GoF本は手元に無いので未確認)。しかし、今回のように、デフォルトの処理がVisitorとして存在する場合は、全てのVisiteeはvisitableであるとしても問題無さそうなので、StableClassにaccept()を設けてみる。そうすると、StableClassからVisitorへの関連は抽象クラス同士になり、Strategyパターンに近い構図になる。

これをJavaで書いたコードを、下の方に貼っている。

本題の考察に入る前に、もう少し大きなサンプルを作ってみる。
(次のエントリーに続く)

See more ...

Posted at 23:30 in PC一般 | WriteBacks (3)
WriteBacks

Finally! This is just what I was looknig for.[link]

Posted by Jahlin at 07/21/2011 02:30:04 AM

かなり古い記事ですが読んでいて気になったので。 visitorパターンの SumVisitorインターフェースが抽象化されていないです。 StableClassCが登場した場合に、インターフェースとすべての具現クラス(Concrete)に変更が発生します。 各visitor内で、instanceofを使って具象クラスの増減を吸収するのが骨子かと思います。 StrategyとVisitorの違いですが、呼び出す側から見て、 ・新しい処理の追加に強いのがVisitor  従ってvisitorは訪問先の構造を知らなくてはならない。状態も持つことが多いはず。  (例:エクスローラのデータサイズ合計の表示、グラフ表示のプラグインなど) ・構造が殆ど同じで、一部処理を切り替えるのがStrategy  状態を持たない場合もあるでしょう。  (例:データベースとの接続で、MS Access/Oracle/My SQLなど) ではないでしょうか?

Posted by at 02/19/2013 05:31:28 AM

鋭いコメントありがとうございます。 SumVisitorが、全てのStableClassの具象クラスについて、それを引数として受けるためのメソッドを定義するべきかどうかというのは、確かに悩みました。実は私も、最初はSumVisitorのvisitの引数の型を抽象StableClassにしていました。その方が楽だからです。 おっしゃる通り、そのようにして、具象クラスのvisitメソッドにてinstanceofを使ってどのStableClassの具象クラスかで場合分けをするようにすれば、StableClassCが現れてもSumVisitor以下全てに改造が発生することになりません。 しかし、いわゆるGoF本では、Visitorインターフェースは全ての具象Visiteeクラスについてvisitメソッドを定義しています(参考リンク1)ので、ここではそれに従いました。 実はVisitorパターンの目的の1つは、そのような場合分けによるvisitメソッドの複雑化を回避することにあります(参考リンク2)。オブジェクト指向設計は元々、できるだけ条件分岐はクラス分け(データの特徴付け)やメソッドのオーバーロード(協調相手の特徴付け)によって解決しようとする考え方ですので、それを追求した結果、VisitorパターンではVisitorインターフェースでVisiteeの具象クラスを解決するようになっているのだと思います。 実用的かどうかは別にして、VisitorインターフェースにおけるVisitor側の具象クラスの解決は、Visitorパターンの定義の一部だと考えて良いと思います。また、VisitorパターンではVisiteeが主でVisitorが従で、Visitee側は不変(なので"Stable"というクラス名にしました)だという前提があり、もしVisiteeに追加変更があれば全てのVisitorに変更が及ぶというのはVisitorパターンの宿命と考えて良いと思います。 なお、acceptメソッドをVisitableインターフェースと定義し、visitメソッドにて、VisiteeがVisitableかどうかをinstanceofで調べるのは、Visitorパターンの発展形として知られているようです。この用途でinstanceofを使用するのはVisitorパターンの範囲内だと思いますし、そういう選択肢があることはVisitorパターンを適用する上で必須の知識だと思いますが、VisitableでないStableClassはVisitorパターンに当てはまらないので、本記事では省きました。 後半のStrategyとVisitorの違いについては、全くおっしゃる通りだと思います。[link]

Posted by ynomura at 02/25/2013 08:28:42 PM

Jan 24, 2011

ソフトウェア開発のスペシャリストはコーディングを諦めるべきか

言い尽くされたテーマであるが、暇潰しに私も書く。

ソフトウェア開発のマネージャー(管理職、管理者、リーダー)はコーディングを諦めるべきか

日本のプログラマーは、地位が低く、SEやマネージャーへの転身を迫られることが多い。
成長の道筋としてそういう路線が規定されていると言っても過言ではなかろう。
なぜ会社が優秀なプログラマーをもSEやマネージャーにさせたがるかというと、プログラミングがわかってる人にやってもらいたい、結局、プログラミングがわかってる人でないと務まらないと思うからではなかろうか。
現場を離れてSEやマネージャーをやると、すぐに中身についていけなくなる人も居るし、実は現場に居ないと何もわからない、現場を離れると何もできないという人も居る。わかってない人にはSEやマネージャーが務まらない、と思って現場の人を引き抜くが、やっぱりすぐに務まらなくなる。それで、人の入れ替わりが激しくなり、プログラマーとしてもSEやマネージャーとしても、プロフェッショナルがなかなか育たないのである。
もちろん、それぞれの道でスキルを高められる人も居る。そのような成功者がどのようにしてきたかは学ばないといけない。
しかし、プログラマーや設計者として向いてるのに、会社の不理解でその道を外されてしまい、スキルが上がらなくなってしまう人は、日本では相当多いように感じる。
管理者は現場に深入りしないのが正しい、とか、理想的な管理者は現場に深入りしないものだ、とかいう論理がまことしやかに語られるのが象徴的である。普通の感覚なら言い訳にしか聞こえないのではなかろうか。

現場にかまけている暇があるのか、という問題ではあろうが、敢えて現場を知らない方がいいというのはあり得ない。まさが現場の仕事もしてるようだと威厳が保たれないからとかいうことは無いだろう。

知ったかぶりで通用してしまう、知ったかぶりをして何もしない人間が生き延びれてしまうのは何かがおかしいのである。そういう人間を信頼してしまうのは、知ったかぶりであることを理解できないからである。知ったかぶりは騙しているのである。本人が成果を出してるかどうか、その本人は役に立ってるかどうかを見極める術を持っていないのである。

設計ができる人が居ない、SEができる人が居ない、マネージャーをできる人が居ない。
できない人は居るのではないか。なぜその者たちが勉強しない?
なぜプログラマーをそれに当てようとするのか。
なぜ努力しない。なぜプログラマーに戻ってやり直そうとしない。なぜ高い賃金を払う人間にコーディングをさせない。1つにはコーディングの価値を不当に下げているからではないか?その人間にさせようとしている仕事は、本当にコーディングより価値があるのか?給料の高い人間が能力に劣ることが明確になりやすいから、ごまかしにくい状況になりやすいから考えないだけではないか?

ベテランがそれに見合う能力が無い、または現場から遠ざけてそれをぼかしているのは、ベテランが高い専門性を手にできるような仕事のさせ方をしてこなかったからではないだろうか。
高いスキルを保有しているベテラン(設計専門、SE、管理者含む)は、コーディングをやり続けていたのではないか。
ソフトウェア開発というのは、設計専門、SE専門、管理者専門で高いスキルを維持するのは困難だということではなかろうか。

これは永遠のテーマに近い感じで捉えられているのではなかろうか。

なぜそんなテーマが存在するのかと考えると、ソフトウェア開発という仕事が常に変化しているからであろう。開発技術が進歩し続けていることもあるし、ハードウェアが進歩して要求も増大していることもあるし、要求の性質が変化していることもある(デザインとか感性とか)し、時々なんとか認識技術とか人工知能的なソフトウェア技術自体が進歩するし、開発環境や動作環境も変わる(メモリ管理を意識しなくてもいいとか)。1回現場で仕事を覚えても、その知識は数年経ったら役に立たなくなってしまうのである。不変なのは人間という生物の特性くらいであろう。

ソフトウェア開発のマネジメントを、ソフトウェア技術の知識とは切り離して、開発者という人種のマネジメントという仕事だと割り切ってしまう方法は当然ある。そういうマネージャーは決して少なくないように見える。それが良いとは思わないのに、そうすることを強要されてる人、そうしかできない人も居る。実際、マネージャーの大半は技術についていっていない。それでいいのか?に対しては、人によって回答が異なる。
みんながみんなそれでいいのか? →Noだろう
少しは居ていいのか? →Yesだろう
知財形成に
研究所の管理職や法律事務所の所長に近いはずだと思う
何が違うかというと、人数と、そこまでは知能を必要としないことか
デザイン事務所の所長に近いかも知れない
研究所のリーダーなら、中身に付いていってることが多いだろう。研究職にマネジメントという仕事があるのかどうか想像がつかないということもある。部長クラスとして、やはり相当理解力が無いと務まらないだろう。

リーダーシップとは先見性、明確なメッセージを発信すること
それはわかるが、それが信用できない時はどうするのか
話せばわかるというのは全てに当てはまらない
実体の無いものだったり、間違ってたりしたら、わかりようがないのである
そもそもリーダーシップとマネージメントは違うのである

ソフトウェア開発という仕事は、デジタル土方とかIT土方とかと呼ばれるくらい、肉体労働に近い側面もあるが、間違いなく頭脳労働である。肉体労働になるのは頭を使っていないから起こるのである。コマネチ大学数学科のコマ大生と同じことである。但し、頭を使ってないのが労働者本人とは限らない。労働者が賢い方法を知っていても、マネージャーがそれに相容れない指示を出せば同じことである。5日かけて共通モジュールを作ってからそれぞれの機能を実装した方が生産効率が良くても、2日でこの機能、次の2日でこの機能…と指示されたらそれを選択できない。設計書を書いてからコーディングした方が良いのに、設計書を書く暇のないリリーススケジュールを引かれたらどうしようもないのである。

日本はガラパゴス化しているという。だって仕方ないだろう。さもなくば会社はマネーゲームの駒となり、従業員に対して冷徹になるだろう。それは日本を売り渡せというのと同義である。博打に勝った者が儲け、要領の良い者が儲け、成功は一時的で、失敗したら即解散ということである。日本人はそれを好まないのである。継続可能な方法を編み出しているのである。日本には守るべき日本文化があるのである。日本の産業がガラパゴス化しているなどと言うのは、左翼の発言である。外国が全て正しい、外国の方が進んでいる、日本は何もかも遅れているという錯覚をしている売国奴の発想である。

ソフトウェア技術はガラパゴス化しているのは否めない。著名なオープンソースに日本人の名前がほとんど出てこない。クレジットに日本人名がなかなか出てこないのを不思議に思ったことはないだろうか。技術力からすると異様である。日本人には飛び抜けた人が少ないということでもあろうし、外国人と共にやるようなパワフルな人が少ないということでもあろうし、狂ったようにのめりこむのを許容しない環境があるからかも知れない。

コーディングよりも生産的な仕事がある、またはコーディングは生産性が低い、というだけの理由でコーディングから卒業しても、コーディングするよりも生産的な仕事をしてる人が少ないのが実態ではなかろうか。楽するためにそういうのを都合のいい理屈として使われることもあるし、命令されて卒業して戸惑う人もいる。
しかし、実際に設計専門者に転身すると、最後まで使われるものが1つも無い設計書ばかり作っていたり、SEやプロジェクトマネージャに転身すると、やることは丸投げだったりする。
コーディングするよりも生産的な仕事のやり方が確立されていないのである。一応確立されていても当人が理解していないのかも知れないし、会社が理解していないのかも知れないし、伝授する人がいないのかも知れない。
漠然と、コーディングは卒業すべし、とだけ言われており、具体的にコーディングより何をすべきというのが明確でないから、または指示が曖昧だったり、夢のようなシステムを作れという無茶な事を要求されるからそうなるのである。
コーディングしてる方が生産性が高かった、ということに気付いたなら、すぐに戻るべきだろう。

大体、一概にコーディングは生産性が低いと決めつけるのはナンセンスである。素人でもコーディングができるからといって、誰がやっても素人と同じ生産性ということにはならない。職人がやれば、極端な話、たとえ設計書無しでコーディングしてもきちんとした設計になるのである。それは、設計のプロフェッショナルという方々に1000万円で作ってもらった設計よりも実用的であることもある。直接コーディングしなければ設計が無いとも限らないし、設計してコーディングすれば設計があるとも限らないのである。結局、有効な設計であるかどうかを判断できる能力が無ければ、何をやっても無駄なのである。また、設計の有効性を理解できる体制だとしても、現役コーディング担当者の実地の知識が無いと設計できないのでは、設計だけをやる意味は無いのである。

設計はセンスである。どのような条件で、どのような環境において有効な設計であるかは変化する。NULLチェックが省略されても良いようなサイズにクリティカルなプロジェクトもあれば、作ったものは全てブラックボックスとして画一的に動作する必要があるプロジェクトもある。資源を優先するか速度を優先するかということもある。能力さえあれば全体が1人の人間に把握可能な規模なものもあれば、超人をもってしても把握できる訳がない規模のものもある。全体を把握するという作業が、要件を把握するので手一杯で1ユーザーになるのと等価になってしまうものもある。中身を理解可能か、I/Fしか情報を得られないかということもある。オブジェクト指向が通用するミドルウェアになっているかどうか、タイミングにクリティカルかどうか、プロトコルがどれくらい複雑かということもある。
設計というのは極論すればオブジェクトをどのように配置しオブジェクト間にどのような関連を持たせるか決める事である。そのオブジェクトの規模によって考える相互作用の規模や抽象化のレイヤーが変わってしまうのはやむを得ない。一概にソフトウェアの設計と言っても、相当なバリエーションがあることを理解されるべきもの、願わくば設計という技術の体系化、種類の整理がなされるべきものなのである。

See more ...

Posted at 01:41 in 社会 | WriteBacks (0)
WriteBacks

Jan 18, 2011

(Emacs) Hi-lock modeを使う

前のエントリーからの続きである。

Hi-lock modeは、Font Lock modeのバッファ毎の追加ルールを手軽にインタラクティブに設定できるI/Fである。
Font Lock modeを有効にしていると、C-sで検索すると、マッチする部分がハイライト表示される。それが便利なので、ハイライト表示するためだけにいちいちC-sで検索することがあるのは筆者だけではないであろう。検索を抜けるとハイライトが解除されてしまい、またハイライトするために検索してしまう。そんな時はHi-lock modeである。

M-x highlight-regexp(既にHi-lock modeならC-x w h)を実行して、ハイライトするパターンを入力すると、マッチする箇所がハイライトされる。何かマッチすると、自動的にHi-lock modeが有効になる。もしFace Lock modeがOFFだと、自動的にFace Lock modeもONになる。

・実行前(Hi-lock modeでない)

・"x"をhighlight-regexpした状態(Hi-lock mode、mode-lineに"Hi"が追加されているのに注目)

検索パターンを単にxとするのでなく\<x\>とすると、単語の一部でなく単独で現れるxを対象にできる。
・"\<x\>"をhighlight-regexpした状態

続けてC-x w hして別のパターンをハイライトすることもできる。
・さらに"\<y\>"をhighlight-regexpした状態

C-x w l(highlight-lines-matching-regexp)を使うと、パターンを含む行全体をハイライトできる。
・さらに"draw"をhighlight-lines-matching-regexpした状態

1つのパターンのハイライトを解除するには、C-x w r(unhighlight-regexp)を実行する。全て解除するなら、M-x hi-lock-modeとしてHi-lock modeをOFFにすれば良い。

C-x w b(hi-lock-write-interactive-patterns)とすると、そのモードに定義されたコメント形式で、現在のハイライト設定が挿入される。
・上の状態から続けてhi-lock-write-interactive-patternsを実行した状態

c-modeなら、/*〜*/で括られたものが挿入される。これを残しておくと、次にこのファイルでHi-lock modeがONになった時に同じハイライトがなされる。

ハイライトを解除した後で、コメントに書かれたHi-lock設定を読み込むには、C-x w i(hi-lock-find-patterns)とする。

コメント形式のHi-lock設定はFont Lock modeのルールと同じなので、これを書き換えると、結構複雑な設定も書ける。
・"draw"のルールを書き換え中("draw_に続く単語を赤太字、"draw_"より後ろの"r"をピンクでハイライトするつもり)

・C-x w i(hi-lock-find-patterns)を実行した状態

See more ...

Posted at 22:27 in PC一般 | WriteBacks (0)
WriteBacks

(Emacs) Font Lockのルールを追加する

前のエントリーからの続きである。

Font Lock modeの追加ルールを設定するには、font-lock-add-keywordsという関数を使う。ルールは、正規表現のパターンとそれにマッチする部分に適用するface、の組み合わせとして定義する。モード毎の設定が基本だが、現在のバッファのみの設定もできる。

font-lock-add-keywords関数の書式は、

(font-lock-add-keywords モード名 ルールのリスト)
である。モード名をnilにすると、現在のバッファに対する設定になる。
ルールの書式はいくつかの種類がある。
  • a. MATCHER
  • b. (MATCHER . SUBEXP)
  • c. (MATCHER . FACENAME)
  • d. (MATCHER . HIGHLIGHTER)
  • e. (MATCHER HIGHLIGHTER1 HIGHLIGHTER2 ...)
  • f. (eval . FORM)
(参考:font-lock-add-keywordsのhelpと、Emacs LispのinfoのFont Lock ModeのSearch-based Fontificationの項)
a.とb.はfaceを指定しない場合(font-lock-keyword-faceが使われる)、c.はfaceのみを指定する場合(MATCHERにマッチする部分全体に適用される)、f.は正規表現の代わりにfaceの変更対象を検索する関数を別途定義する場合に使用するもので、a.〜c.はd.で代用でき、d.はe.で代用でき、f.は特殊なので、1つ覚えるならe.の形式が良いと思う。

HIGHLIGHTERの書式は、主に(SUBEXP FACENAME [OVERRIDE])である。SUBEXPは正規表現に()を使う場合の何番目の()の部分かの意味で、全体なら0とする。OVERRIDEは別のルールが適用済でも適用するかどうかである。

例えば、次のようにすると、java-modeの時に、TABの部分がunderline、2バイトスペースや行末の空白部分がtrailing-whitespaceというface(これらはfaces.elに定義されている)になる。

(font-lock-add-keywords 'java-mode '(
  ("\t" . 'underline)
  (" " . 'trailing-whitespace)
  ("[ \t]+$" . 'trailing-whitespace)
))
実行前

実行後

次のようにすると、java-modeに限らず、全モードで有効になる。

(defadvice font-lock-mode (before my-font-lock-mode ())
  (font-lock-add-keywords
   nil   ;現在のバッファのみ
    '(("\t" 0 'underline append)
      (" " . 'trailing-whitespace)
      ("[ \t]+$" . 'trailing-whitespace)
     )))
(ad-enable-advice 'font-lock-mode 'before 'my-font-lock-mode)
(ad-activate 'font-lock-mode)
なお、上の3行目の部分をnilでなくmajor-modeと書いている例をよく見かけるが、そのようにすると、バッファが開く度にfont-lock-add-keywordsが実行され、font-lock-keywords-alistが肥大化してしまうので、nilの方がいいと思う。


HIGHLIGHTERの書式には、他に、MATCHERがマッチした後の行末までの部分を対象に、別のパターンの検索を行う、anchoredな形式がある。
ANCHORED-MATCHERを使う場合は、HIGHLIGHTERの書式が(ANCHORED-MATCHER PRE-FORM POST-FORM SUBEXP-HIGHLIGHTERS...)となる。PRE-FORMは、このANCHORED-MATCHERの検索が始まる前に実行され、POST-FORMは、行末までこのANCHORED-MATCHERが探された後に実行される。これを使うと、以下のようなことができる。

■コメント部分の特定キーワードの表示を変える
筆者は試行錯誤中のコードをコメントアウトして残す癖があり、作成中のコードには使用中のコードの3〜4倍のコードがコメントに存在することが普通にあるが、デフォルトのルールでは大体それらがコメント色1色になってしまうので、たまに痛い時がある。

(font-lock-add-keywords nil '(
 (";"
  ("face\\|frame"
   nil  ;PRE-FORM
   (goto-char (match-end 0))  ;POST-FORM: pointを";"の直後に戻す
   (0 font-lock-type-face t))
  ("default"
   nil  ;PRE-FORM
   nil  ;POST-FORM
   (0 font-lock-builtin-face t))
  )))
実行前

実行後(コメント中の"face", "frame", "default"に色が付いている)

■CやJavaの"if"の後の"="を警告表示にする

(add-hook 'c-mode-common-hook
  '(lambda ()
    (font-lock-add-keywords major-mode '(
      ("\\<if\\>"
       ("[^<>=]\\(=\\)[^=]" nil nil (1 font-lock-warning-face))
       )))
))
実行前

実行後

過去にそんなミス滅多に無いだろ、みたいなことを書いたが、筆者はExcel VBAを書いた直後だとやってしまうことに気付いた。

■"\x1b\x24\x42"〜"\x1b\x28\x42"とその間の16進数に着色する

(font-lock-add-keywords nil '(
 ("\\\\x\\(1b\\)\\\\x\\(24\\)\\\\x\\(42\\).*?\\\\x\\(1b\\)\\\\x\\(28\\)\\\\x\\(42\\)"
  (1 font-lock-function-name-face t) ;"1b"の部分
  (2 font-lock-function-name-face t) ;"24"の部分
  (3 font-lock-function-name-face t) ;"42"の部分
  (4 font-lock-constant-face t)  ;"1b"の部分
  (5 font-lock-constant-face t)  ;"28"の部分
  (6 font-lock-constant-face t)  ;"42"の部分
  ("[0-9a-f]"  ;ANCHORED
   (progn  ;PRE-FORM
    (goto-char (match-end 3)) ;3つ目の後に移動
    (match-beginning 4))  ;4つ目の先頭までに限る
   nil  ;POST-FORM
   (0 font-lock-type-face t))
)))
実行前

実行後

See more ...

Posted at 22:26 in PC一般 | WriteBacks (0)
WriteBacks

(Emacs) Faceを使って部分的に見た目を変える

Emacsのfaceとは、フォント名や太字/斜体/下線といったフォント属性や文字色といったフォント設定をまとめたものであり、バッファ内のテキストの一部分に適用する事ができる。Emacsでソースコードを開くと、予約語やコメント部分や文字列部分に色が付くが、これは、そういう色で文字を表示するというfaceがそれぞれ定義されており、それらの部分にそれぞれのfaceが適用されている状態である。

Emacsでフォントの設定をしていると、時々faceという単語が出てくる。意味がわからないままでもフォントの設定はできたが、特にX resourcesでフォントセットの定義をすると、何に使われるのかわからなくても、default, bold, italic, bold-italicの4つ分を定義させられる。これらのフォントも、テキストにそういうfaceが適用されると使用されるが、そういうfaceが適用されないと、使われる事がない。
筆者はC, Java, Perl, Pythonなどのプログラム言語のソースコードをEmacsで開くことがあるが、キーワードや特定パターンに色が付くのはよく見るが、太字や斜体になるのは滅多に見ない。目にするのは、helpやinfoを開いた時くらいである。最も多く編集するのはテキストファイルであるが、text-modeでは色も付かない。

せっかく設定したものがほとんど使われず、しかもどうやれば使えるのかがわからないのは、気になる。そこで、faceの使い方を少し調べることにした。

Emacsで開いているテキストの一部分のfaceを変える方法としては、主に
・facemenu-*関数を使う
・Font Lock modeを使う
・Hi-lock modeを使う
・Highlight Changes modeを使う
がある。他にも、Emacs23ならtext-scale-*関数があったり、色々あるようであるが、Emacs22のinfoですぐ見つかるのはこれくらいである。(10年くらい前にEmacsを使っていた時はhilit19.elというのにお世話になったが、今ではobsoleteのようである)

■facemenu.elを使う
範囲選択してfacemenu-set-*関数を実行すれば、その範囲にfaceを適用できる。

これは、Carbon Emacs 22.3で3文字ずつM-o o(facemenu-set-face)してみた例である。適用したfaceは順に、highlight, lazy-highlight, link, match, query-replace, custom-button, custom-button-pressed, custom-face-tagである。加えて、"abc"はM-o bでboldに、"def"はM-o iでitalicにしてある。


これは、後述のfacify-iroha-regionマクロで、1文字ずつ異なるfaceを適用してみたものである。

キャラクターベースのリモート端末でも、これくらいカラフルになる。

(EmacsはDebianのemacs21-nox、ターミナルソフトはPuTTY、設定はほぼvt100のdefault)

しかし、Font Lock modeがONになっていると使えない。昨今のPCの性能では、もはやFont Lock modeをOFFにして使用することは少ないと思うので、あまり使えなさそうである。
また、これによって設定されたfaceはバッファローカルであり、編集したテキストと共に保存される訳ではないので、あまりこれによるテキスト装飾を手作業でがんばる意味は無い。失われることを前提に一時的に装飾するのに使うものである。
ただ、上のようにマクロで好き勝手に装飾したい時は、使えそうである。

■font-lock-mode.elを使う
何らかのソースコードを開いて自動的に色が付くなら、まず間違いなく、Font Lock modeが有効になっている。予め設定されたルールに従って自動的にfaceが適用されるモードである。
大体、c-modeとかperl-modeとかの言語毎のモードに入ると、自動的にその言語特有のルールが追加される。
有効でない場合は、.emacs等に

(global-font-lock-mode t)
と書けば有効になる。

追加ルールの設定については、長くなったので、次のエントリーに書く。

■Hi-hock modeを使う
長くなったので、次の次のエントリーに書く。

■Highlight Changes modeを使う
変更部分に自動的にfaceが適用されるモードである。ファイルを開いてからM-x highlight-changes-modeとするか、.emacs等に

(global-highlight-changes 1)
と書くと有効になる。

次の画像は、テキストファイルの編集にHighlight Changes modeを使った画面の例である。

黒以外の部分が、M-x highlight-changes-modeを実行してから変更した部分である。色違いは、highlight-changes-rotate-facesで世代を切り替えたものである。
highlight-changes-previous-changeやhighlight-changes-next-change等の関数を使うと、前の変更部分や次の変更部分にジャンプできるようである。
facemenu.elを使った場合と同様、これによる色はファイルに保存される訳ではない。

保存されていない変更があるかどうかはmode lineの**でわかるし、変更履歴として保存される訳でもないので、使い所が難しい気がする。Font Lock modeを使っていると、編集中の部分に本来の着色がされなくなり、スペルミスの点検ができなくなったりするので、却って不便である。Font Lock modeの効果が少ないText modeで長文の一部を修正する時は便利かも知れない。

See more ...

Posted at 20:32 in PC一般 | WriteBacks (0)
WriteBacks