JRubyでJUDE CRUD-APIを試す
JUDE-CRUD-API
JUDE5でCRUD図がサポートされ、さらにAPIも公開されました。さっそく試してみましょう。題材は、おなじみファンクションポイント測定アプリです。さらに今回はJRubyも使い、JUDE-APIとJRubyの相性も体感します。
仕様
仕様は基本的に前回と同じで、計測結果も前回と同じになるはずです。
使い方はユースケースとER図を描いて、ユースケースとエンティティそれぞれの「タグ付き値」にDET/RETなどの見積りに必要な情報を入力します。(DET/RETの詳細は前回のエントリを参照してください)
前回との仕様の違いは次の通りです。
環境
JavaではなくJRubyを使いました。実は平鍋さんのエントリに刺激を受けたのです。
ファンクションポイント算出ライブラリ
これは前回作ったサンプルアプリをJARファイルにしたものです。今回のサンプル動作に必要となります。JRubyのlibフォルダに突っ込むか、クラスパスに通しておきます。
Ruby初体験
Hello World以外では、初めてRubyのコードを書きました。まだ「Rubyっぽさ」というかその良さが分かってないですね。(私の周りのRubyエキスパートの皆さん、優しいツッコミをお待ちしております)
サンプルソースコード
require 'java' module Jude include_package "com.change_vision.jude.api.inf.project" include_package "com.change_vision.jude.api.inf.model" end module Fp include_package "com.jude_api.fp" end # データファンクションのDETを求める # 単純にエンティティ中の属性を数えているだけ def getDataFunctionDET(model) model.primaryKeys.length + model.nonPrimaryKeys.length end # データファンクションのRETを求める # JUDEのタグ付き値に"RET"というキーで設定する # 未設定の場合は1 def getDataFunctionRET(model) model.taggedValues.each do |tv| if tv.key == "RET" then return tv.value.to_i end end return 1 end # データファンクションポイントを求める def getDataFunctionPoint(fileTypeId,det,ret) complexity = Fp::FunctionPointUtil.getDataFunctionComplexity(det, ret) dataFp = Fp::FunctionPointUtil.getDataFunctionPoint(fileTypeId,complexity) end # トランザクションファンクションのDETを求める # JUDEのタグ付き値に"DET"というキーで設定する # 未設定の場合は30 def getTransactionalFunctionDET(model) model.taggedValues.each do |tv| if tv.key == "DET" then return tv.value.to_i end end return 30 end # トランザクション種別(EI/EO/EQ)を求める # JUDEのタグ付き値に"type"というキーで設定する # 未設定の場合は0(EI) def getTranTypeId(model) types = ["EI","EO","EQ"] model.taggedValues.each do |tv| if tv.key == "type" then types.each_with_index {|type,i| return i if tv.value == type} end end return 0 end # トランザクションファンクションポイントを求める def getTransactionalFunctionPoint(tranTypeId,det,ftr) complexity = Fp::FunctionPointUtil.getTransactionalFunctionComplexity(det,ftr,tranTypeId) tranFp = Fp::FunctionPointUtil.getTransactionalFuncitonPoint(tranTypeId,complexity) end pa = Jude::ProjectAccessorFactory.projectAccessor pa.open "test2.jude" fpTotal = 0 pa.project.diagrams.each do |dg| if dg.java_kind_of? Jude::IMatrixDiagram then dg.showRowHeaders.each_with_index do |rh, i| # グルーピングおよび合計行は無視 next if !rh.parent || rh.isTotal puts rh.label dataFpSum = 0 ftr = 0 dg.showColumnHeaders.each_with_index do |ch, j| # グルーピングおよび合計行は無視 next if !ch.parent || ch.isTotal fp = 0 det = getDataFunctionDET(ch.model) cell = dg.getShowValueCell(i,j) if cell != nil then if (cell.isCreate || cell.isUpdate || cell.isDelete) then # C/U/DがあればILF ret = getDataFunctionRET(ch.model) fp = getDataFunctionPoint(0,det,ret) printf " %s %s DET=%d RET=%d FP=%d \n","ILF",ch.label,det,ret,fp ftr+=1 elsif cell.isRead # Rのみの場合はEIF ret = getDataFunctionRET(ch.model) fp = getDataFunctionPoint(1,det,ret) printf " %s %s DET=%d RET=%d FP=%d \n","EIF",ch.label,det,ret,fp ftr+=1 else # 一旦CRUDを作成しその後削除したCELL print " (使わない) ",ch.label,"\n" end else # 一度もCRUDを設定していないCELL print " (使わない) ",ch.label,"\n" end dataFpSum += fp end print "** Data FP合計 ",dataFpSum,"\n" tranDet = getTransactionalFunctionDET(rh.model) tranFp = getTransactionalFunctionPoint(getTranTypeId(rh.model),tranDet,ftr) print "** Transactional FP ",tranFp,"\n" fpTotal += dataFpSum fpTotal += tranFp end end end puts "\nFP合計:", fpTotal pa.close
JUDE-APIにフィードバック
一度もCRUD設定していないCELLと、一旦設定し削除したCELLの違い。
一度もCRUD設定していない場合、IMatrixDiagram#getShowValueCellメソッドはnullを返します。一方、一旦設定し削除したCELLの場合はIValueCellのインスタンスが返ります。JUDEの見た目上は区別が付かないのですがAPIでは区別されます。
グルーピングと合計行の判別
合計行はIHeaderCell#isToralメソッドが使えますが、グルーピング行の判別は、IHeaderCell#getParentがnullを返すかどうかでチェックする方法しかありません。