Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

Gotchas in Eclipse JET (JET2)

No uniq()

There are no XPath functions to uniq the result of XPath (e.g. text element). If you want to uniq something, you have to implement control break with <c:iterate> like:

<c:setVariable select="''" var="control" />
<c:iterate select="XPath to list text elements" var="item" >
  <c:if test=“$item!=‘${$control}’”>
    DO SOMETHING WITH $item
    <c:setVariable select="${$item}" var="control" />
  </c:if>
</c:iterate> 

No String.join() equivalent

There are no XPath functions to join strings. You have to implement string join logic with <c:iterate> like:

<%-- join strings with "+" --%>
<c:setVariable select="''" var="control" />
<c:iterate select="XPath to list text elements" var="item" >
  <c:choose>
    <c:when test="$control=''">
      <c:setVariable select="string('X')" var="control" />
    </c:when>
    <c:otherwise>
      + 
    </c:otherwise>
  </c:choose>
  WRITE $item
</c:iterate> 

Can’t count numbers

There are no way to implement loop with index like for (int i=0; i<N; i++) in ordinal programming language. It would be better to implement loops in the generated Java source, rather than in JET templates.

Almost everything is XPath

<c:setVariable select="''" var="item" />

is OK. But

<c:setVariable select="'A'" var="item" />

will cause runtime error, because the content of value attribute is considered as XPath (there is no such a XML element in scope). You have to write like this:

<c:setVariable select="string('A')" var="item" />

康煕字典体から常用漢字へ変換するコマンドレット

変換対照の文字は、文化庁 常用漢字表*1康煕字典体が示されているものを対照とした。常用漢字表のPDFの内容をテキストファイルへダンプし、以下のスクリプト常用漢字とカッコ書きの康煕字典体とのペアを抽出した*2

> Get-Content .\常用漢字表.txt | Where-Object { $_ -match '(?<Oyaji>.?)   ((?<Itaiji>.?))   ' } | Foreach-Object { ("{0}{1}" -F $Matches.Oyaji, $Matches.Itaiji) }

上記の結果をもとに、trコマンド相当のコマンドレット*3を使って変換処理を実装した。

function tr {
  Param(
    [Parameter(ValueFromPipeline=$true,Mandatory=$true)]
    [string] $TargetString,
    [Parameter(Mandatory=$true)]
    [string] $FromString,
    [Parameter(Mandatory=$true)]
    [string] $ToString
  )
  begin {
    # [-split ""] splits a surrogate pair into two invalid characters,
    # so the code below is not suitable for this purpose
    # $FromStringArray = $FromString -split "";
    # $FromStringArray = $FromStringArray[1..($FromStringArray.length-2)];

    # Split string into character array
    $FromStringArray = @();
    $FromStringBytes = [Text.Encoding]::UTF32.GetBytes($FromString);
    for ($i=0; $i -lt $FromStringBytes.length; $i+=4) {
         $FromStringArray += [Text.Encoding]::UTF32.GetString($FromStringBytes, $i, 4);
    }

    $ToStringArray = @();
    $ToStringBytes = [Text.Encoding]::UTF32.GetBytes($ToString);
    for ($i=0; $i -lt $ToStringBytes.length; $i+=4) {
         $ToStringArray += [Text.Encoding]::UTF32.GetString($ToStringBytes, $i, 4);
    }
  }
  process {
    for ($i=0; $i -lt $FromStringArray.Length -and $i -lt $ToStringArray.Length; $i++) {
        $TargetString = $TargetString.Replace($FromStringArray[$i],$ToStringArray[$i]);
    }
    $TargetString
  }
}

function ConvertFrom-Kokijitentai {
  Param(
    [Parameter(ValueFromPipeline=$true,Mandatory=$true)]
    [string] $TargetString
  )
  begin {
    $FromString = "亞惡壓圍醫爲壹逸隱榮營衞驛謁圓鹽緣艷應歐毆櫻奧橫溫穩假價禍畫會悔海繪壞懷慨槪擴殼覺學嶽樂喝渴褐罐卷陷勸寬漢關歡觀氣祈既歸器僞戲犧舊據擧虛峽挾狹鄕響曉勤謹區驅勳薰徑莖惠揭溪經螢輕繼鷄藝擊缺硏縣儉劍險圈檢獻權顯驗嚴廣效恆黃鑛號國黑穀碎濟齋殺雜參棧蠶慘贊殘絲祉視齒兒辭濕實寫社者煮釋壽收臭從澁獸縱祝肅處暑署緖諸敍將祥稱涉燒證奬條狀乘淨剩疊繩壤孃讓釀觸囑神眞寢愼盡圖粹醉穗隨髓樞數瀨聲齊靜竊攝節專淺戰踐錢潛纖禪祖雙壯爭莊搜插巢曾瘦裝僧層總騷增憎藏贈臟卽屬續墮對體帶滯臺瀧擇澤擔單膽嘆團斷彈遲癡蟲晝鑄著廳徵聽懲敕鎭塚遞鐵點轉傳都燈當黨盜稻鬭德獨讀突屆難貳惱腦霸拜廢賣梅麥發髮拔繁晚蠻卑祕碑濱賓頻敏甁侮福拂佛倂竝塀餠邊變勉步寶豐襃墨飜每萬滿免麵默彌譯藥與豫餘譽搖樣謠來賴亂覽欄龍隆虜兩獵綠淚壘類禮勵戾靈齡曆歷戀練鍊爐勞郞朗廊樓錄灣"
    $ToString =   "亜悪圧囲医為壱逸隠栄営衛駅謁円塩縁艶応欧殴桜奥横温穏仮価禍画会悔海絵壊懐慨概拡殻覚学岳楽喝渇褐缶巻陥勧寛漢関歓観気祈既帰器偽戯犠旧拠挙虚峡挟狭郷響暁勤謹区駆勲薫径茎恵掲渓経蛍軽継鶏芸撃欠研県倹剣険圏検献権顕験厳広効恒黄鉱号国黒穀砕済斎殺雑参桟蚕惨賛残糸祉視歯児辞湿実写社者煮釈寿収臭従渋獣縦祝粛処暑署緒諸叙将祥称渉焼証奨条状乗浄剰畳縄壌嬢譲醸触嘱神真寝慎尽図粋酔穂随髄枢数瀬声斉静窃摂節専浅戦践銭潜繊禅祖双壮争荘捜挿巣曽痩装僧層総騒増憎蔵贈臓即属続堕対体帯滞台滝択沢担単胆嘆団断弾遅痴虫昼鋳著庁徴聴懲勅鎮塚逓鉄点転伝都灯当党盗稲闘徳独読突届難弐悩脳覇拝廃売梅麦発髪抜繁晩蛮卑秘碑浜賓頻敏瓶侮福払仏併並塀餅辺変勉歩宝豊褒墨翻毎万満免麺黙弥訳薬与予余誉揺様謡来頼乱覧欄竜隆虜両猟緑涙塁類礼励戻霊齢暦歴恋練錬炉労郎朗廊楼録湾"
  }
  process {
    tr -TargetString $TargetString -FromString $FromString -ToString $ToString
  }
}
PS > ConvertFrom-Kokijitentai "慶應義塾大學"

慶応義塾大学

「定量的な数値」とは何か

  • (A) 第三者が何らかの方法で計測できる数値を指して「定量的な数値」と言う。
  • (B) 第三者が何らかの方法で計測できる数値の中でも、ものごとの量を表す数値を指して「定量的な数値」と言う。

たとえば、生産効率や不良率は(A)、生産量や作業時間は(B)にあたります。定「量」的な数値、というわけですね。 (言葉の意味として適切かどうかは別として)作業量やスケジュールを報告する際には(B)だけを指して「定量的」と言ったりする人がいるようです。

ソフトウェア考古学論考 (2)

どっちかもいうとこっちが本題。

さて、ソフトウェア考古学の目的としては、

の他にも、poorly-documentedなレガシーシステムソースコードから、その仕様(あるいは意図)を読み解き復元し、システム再構築のインプットにするというケースが考えられます。

システムの技術的負債の解消や開発者の技術継承などを目的としてシステムを再構築する考え方としては、Fowler(2014)による犠牲的アーキテクチャ*1、および高橋 (2017)による式年遷宮アーキテクチャ*2が提案されています。 システム再構築にあたっては、セカンドシステム症候群を避けるためにも、まずは欲張らない(つまり、現行システムと同程度の)機能をカバーするよう開発を行うわけですが、その際これまで現行システムが本番環境で踏みつけてきた様々なコーナーケースの地雷を避けるには、現行システムの処理がなぜ現在のようになっているのかの理解が欠かせません。

ここで「システム再構築のインプットとなる設計思想の復元」を目的としたソフトウェア考古学的活動が必要になると思うのですが、そのような論文は見当たりません。とすると、

  1. アジャイルソフトウェア開発における知識の保存は成功を収めた。犠牲的アーキテクチャに基づくシステム再構築に耐え得るだけの知識を保存することができた(≒問題にならなかった)
  2. 犠牲的アーキテクチャに基づくシステム再構築は、ソフトウェア考古学的活動を伴っていない。十分な業務知識に基づくトップダウンの再設計だけで、刷新前のシステムと同程度の機能を実装できている(≒やっぱり問題にならなかった)
  3. ソフトウェア考古学的活動による設計思想の復元に成功した例はない。システム再構築は単純なストレートコンバージョンで行われている(≒成功していないので何も書けない)

のどれかなのかなぁと思うのですが、どうなんでしょうね?(3に一票入れたいのですが、悲観的に過ぎるかな?)

*1:Martin Fowler, "Sacrificial Architecture", 2014. URL: http://bliki-ja.github.io/SacrificialArchitecture/

*2:高橋征義, "青空文庫式年遷宮アーキテクチャ: 青空文庫200周年に向けて", 青空文庫20周年記念シンポジウム「青空文庫の今とこれから」, 2017. URL: https://www.slideshare.net/takahashim/aozora20th-2017

ソフトウェア考古学論考 (1)

ソフトウェア考古学(Software Archaeology)という考え方は、OOPSLA 2001で提唱されたのが始まりのようです *1Wikipediaにある通り *2 、poorly-documentedなレガシーシステムソースコードやドキュメントをどう読み解くか?というところから始まったようなのですが、現時点では、Google Scholarで調べる限り、ソフトウェア考古学の研究分野は大きく以下の2つに分かれているように見えます。

  • レガシーシステムの保守開発の効率化。poorly-documentedなレガシーシステムソースコードから、その仕様(あるいは意図)を読み解き、保守開発を確実に実施する(またはリスクを低減する)。たとえばBryon (2009)*3など。
  • システムの仕様理解の補助。昔から開発の続いているソフトウェアのソースコードの変遷やバグの出かたを変更履歴から読み解くことで、現時点のソフトウェア(これ自体はいわゆるレガシーでない場合もある)の仕様理解を助けたり、品質向上の助けにしたりする。たとえば Carrington et al. (2003)*4など。

分析に用いる手法や、その目的から見ると、後者はどちらかといえば「ソフトウェア考古学」というより「ソフトウェア発生学 (Software Embryology)」と呼ぶべきかもしれません。

前者の例を挙げると、たとえばCOBOLソースコード中に

IF 件数 = 9999 THEN

みたいな文があったら、

  • なにかのレコード件数が本当にぴったり9999件だったときの処理なのか?
  • 異常を表す値としてHIGH-VALUEである「9999」を使うのはCOBOLでは常套手段だから、異常系処理なのか?
  • あるいはレコード件数が9999件より多かったときの処理(レコード取得時に上限を9999件として取得しているために、イコールで比較するだけで済んでいる)なのか?
  • あるいは変数名に騙されているだけで、「件数」という変数は実は配列のインデックスなのでは?レコード取得時には件数を制限しておらず、ループ回数に上限を設けて処理を打ち切っているのでは?

といった具合で、対処となる行やその周辺を元に処理の意図を読み解き、最終的には

*検索結果を表示できない場合(レコード取得時にDBエラー発生、
*または検索結果が画面表示件数の上限を超えていた場合)
 IF 件数 = 9999 THEN

のように仕様を復元することを指します。

もちろん、アプリケーションの業務的仕様を把握している人がいるなら、わざわざこんな面倒くさいことをせずとも「知ってる人に聞く」だけで解決できるわけですが、そうもいかないケースもあるわけで、たとえば以下のようなケースが思いつきます。

  • 仕様決定の経緯を把握してる人が定年で辞めちゃった
  • 仕様決定の経緯を把握してる人が他社へ転職しちゃった
  • 仕様決定の経緯を把握してる人がいるにはいるけど、元請じゃなくて開発会社の人(詳細仕様を質問するためだけに契約を結ぶのか?という話になる)
  • 仕様決定の経緯を把握してる人が所属してる会社と仲が悪くなっちゃって、ちょっと聞きに行ける雰囲気じゃない
  • 仕様決定の経緯を把握してる人が社内にいるけど、別のプロジェクトにアサインされてて、おいそれと聞きに行けない*5
  • 仕様決定の経緯を把握してる人が社内にいるし、話も聞いてきたけど、聞いた話の内容を理解できるレベルのメンバーがチーム内に残ってない

そもそもソフトウェア考古学が必要になる前には、開発は上手く回っていたわけで*6、その影にはこういう「知ってる人」や「仕様決定の背景を理解できる人」の存在があったわけですね。

翻って現代のアジャイルソフトウェア開発においては、知識を個人でなく組織に溜め込むことで、必要なドキュメントを減らそう、それで代替できるドキュメントは作らないようにしよう、という考え方があるわけです(SCRUMの研修で聞いただけの話ですが……)。 ただ、ソフトウェア考古学が生まれた経緯を見るに「知識を組織に溜め込むことで、保守に必要な知識が失われないようにする」のは、果たして可能なのだろうか?ドキュメントを作らないことで、逆にソフトウェア考古学の出番が増えやしないか?という点は疑問に思っています。開発チームは存続していても、メンバーの退職・異動・昇進などのイベントを経ることで、どうしても開発開始当初に考えられていた設計上の思想はチーム内でも薄まっていきます。大量のバックグラウンドや経緯や意図を伝えるには、それに見あった量のドキュメントが必要なのでは

アジャイルソフトウェア開発宣言がまとめられたのは2001年、今年で18年です。アジャイルソフトウェア開発の黎明期に作られたソフトウェアの開発思想や背景は、今でもチーム内に知識として保存されているのでしょうか?また、ソフトウェア考古学なしでもそのソフトウェアの保守開発に立ち向かえるのでしょうか?

*1:Ward Cunningham, Andrew Hunt, Brian Marick, Dave Thomas, "Software Archeology: Understanding Large Systems", OOPSLA 2001 Workshop, URL: https://web.archive.org/web/20100612232147/http://www.visibleworkings.com/archeology/position-papers.html

*2:https://en.wikipedia.org/wiki/Software_archaeology#cite_note-RGBH-1

*3:Bryon Moyer, "Software Archeology: Modernizing Old Systems," Embedded Technology Journal, March 4, 2009. URL: https://www.omg.org/adm/docs/Software_Archeology_4-Mar-2009.pdf

*4:Carrington, David, and S-K. Kim. "Teaching software design with open source software." 33rd Annual Frontiers in Education, 2003. FIE 2003.. Vol. 3. IEEE, 2003. URL: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.103.2003&rep=rep1&type=pdf

*5:こういう時に限ってアサイン先のプロジェクトが炎上してたりするんですよね……

*6:儀式的に回っていただけかもしれませんが。 cf. カーゴ・カルトソフトウェア工学