ひしだまの変更履歴

ひしだまHPの更新履歴。
主にTRPGリプレイの元ネタ集、プログラミング技術メモと自作ソフト、好きなゲームや音楽です。

プログラムの品質と価値

2013-12-30 13:44:58 | プログラミング

今年読んだどこかのブログを見て思ったことを思い出したw
プログラムの品質と価値について、そのブログでは、「品質」の評価基準に「価値」を含めているようだった。

プログラムの「品質」と「価値」は別物だと思う。
プログラムの「品質」っていうのは、例えばWebアプリなら、24時間365日稼動し続けられるとか、大量のアクセスがあっても落ちないとか、インジェクションっぽい入力をされても大丈夫とか、そういう事だと思う。
一方、「価値」は、ユーザーにとって便利であるとか、(そのプログラムを動かすことによって現れる)サービスを提供する企業にとっては収益が高いとか、そういう事だと思う。

そして、品質と価値は全く無関係という訳でもなくて、品質が悪ければ価値は下がる。でも品質が良いからといって価値が高いとは限らない。
便利なサービスでも落ちまくってたら評判(価値)は下がるし、全くバグの無いクソゲーは品質は高いけど価値は低いよね(笑)

ちなみに、「UI(ユーザーインターフェース)がクソ」とかいうのは、プログラムの品質というよりはサービスの品質だと思う。
プログラムは、あくまでサービスの仕様(要件)を満たすように作るものだから、仕様を満たしていればプログラムの品質としては合格。
つまりサービスの品質が悪いというのは、プログラムの品質が悪い場合と、そもそも仕様が悪い場合があるってことかな。

ユーザーやサービス提供企業が欲しいのは「サービスの価値」の方だから、「価値」を重視するのは当然だろう。
でもプログラムを作る側(SIerとか)にとっては、「プログラムの品質」を担保するのが第一の仕事だと思う。(メンテナンスしやすいプログラムにする、というのもプログラムの品質のひとつだと思う。これは「サービスの価値」とは全く関係ないが)
「価値」の担保をSIerに求めているとすれば、それは筋が違うと感じる。
(SIer側の戦略として、自らの意義を高める為に「価値」の領域に手を出すのはありだとは思うけど、「品質」を高めるようにするのが本業だと思う(というかまずは最低ラインをですね・・・^^;))

このように、「品質」と「価値」は別々の意味で使うので、品質と価値をどちらかに含めて考えるのは良くないと思ったのでした。 


ちなみに、どういうものが価値になるかを考えるのは、当然サービス提供企業だよね。それを考える気が無いというなら、みんなが大好きなコンサルという手もあるけどw
自社が何を提供するのかを考えないなら、何の為の会社なんだか。金だけ出す?
さらにお金も出さないとしたら、何なんだろうね?^^;


Asakusa Toad Editor公開

2013-12-25 00:59:01 | PG(分散処理)

Asakusa Framework Advent Calendar 2013の25日目、最終日です。
無事完走することが出来ました^^ 参加してくださった方、見ていただいた方、どうもありがとうございます。

という訳で、最後にAsakusa Toad Editorを公開します。
これは、AsakusaFWのBatch DSLFlow DSLをGUIで描くツールです。
(最近書いていた各ページのBatch DSLやFlow DSLの図は、Toad Editorを使って描いていましたw)

ある程度の制限はありますが、
バッチやフローの図を描き、そこからBatch DSL・Flow DSLのJavaソースを生成することが出来ます。
ユーザー演算子については、Operator DSLの雛形(メソッド本体が空の状態)を生成することも出来ます。
既存のBatch DSL・Flow DSLをToad Editorのファイルに変換する機能もあります。 

正直まだ完成度は低いですが、本業の仕事やDQ10の合間に作ったにしてはそこそこの出来だと思いますw
(バグとか要望とかはGitHubのissueに書いていただいたら善処します^^;)
MS-VisioやExcelでフローを描く代わりくらいには使えるかも??
あるいは、Asakusa DSLのJavaソースがどういう風になるかの学習(実験)に使えるかもしれません。 

(あ、Toad Editorの説明ページを作るついでにDMDL EditorXの説明ページも作りました。やっぱり、色が付いている画像を見た方が一目瞭然なのでw)

そして、たまたまなのですが、今度開かれる『Asakusa Framework 勉強会 2014冬』に発表者として呼んでいただきましたので、丁度タイミングも良いのでDMDL EditorXとToad Editorの紹介(というかデモンストレーション)を行いたいと思います。
既にエディターは公開しているので、デモをするときには目新しい事は何も無いような気もしますが(汗)


ふー、これでアドベントカレンダーは全部終了。ようやくDQ10 ver2.0が解禁できるw


Asakusa Frameworkの演算子

2013-12-22 13:12:22 | PG(分散処理)

Asakusa Framework Advent Calendar 2013の22日目です。

AsakusaFWの演算子は23種類あります。中にはほとんど使わないものもあるので実質的にはもう少し減りますが。
AsakusaFWのアドベントカレンダーを始めた時は参加者があまり居ないだろうと思っていたので、およそ1日1演算子でブログを書いていけばちょうど良いと想定していたんですが、ありがたいことに予想に反して多くの人に参加していただき(笑)、気が付いたら演算子に全く触れることが出来ませんでした(爆)

という訳で、演算子擬人化をする人向けに演算子をまとめて紹介したいと思います。


まずはフロー制御系の中から、分岐演算子(@Branch)。愛称はブランちゃんで決定w
条件に応じてデータの出力先を振り分ける演算子です。郵便局で手紙を振り分ける作業に似ているような気がしますね。

次は合流演算子(confluent)
複数の同一データモデルのデータを1つにまとめます。SQLのUNIONみたいなものです。

フロー制御系の最後は複製演算子
出力されたデータを複数個所で使用するために複製する、というイメージですが。
これはAsakusaFWとして論理上定義されているけれども、DSLとしてコーディングに使うものは用意されていません。幻のキャラですね。NO IMAGEでいいでしょう。


続いて、データ操作系。
まずは更新演算子(@Update)
レコード内の項目を使って(演算して)別の項目の値を設定するときに使います。入力データモデルと出力データモデルは同一となります。

変換演算子(@Convert)は、別のデータモデルに変換したいときに使います。
データの移送をいちいち書かないといけないですが、逆に言えば演算を行うことも出来ます。

拡張演算子(extend)射影演算子(project)再構築演算子(restructure)も別のデータモデルに変換する演算子です。
入力と出力のデータモデル間で同名プロパティーであれば自動的に移送してくれます。
特殊なケースで楽をする為の演算子群ですね。Convertはデータ移送をいちいち書かないといけないので。
拡張はプロパティーが増える、射影はプロパティーが減る、再構築はプロパティーが増減するときに使用します。
いわば同一キャラで装備が異なる感じです。

データ操作系の最後は抽出演算子(@Extract)
1レコードの入力に対して複数種類データモデル・複数レコードを出力できます。
性能特性がMapの演算子の中では最強です。


結合系では、マスター確認演算子(@MasterCheck)マスター結合演算子(@MasterJoin)マスター分岐演算子(@MasterBranch)マスターつき更新演算子(@MasterJoinUpdate)はひとまとめでいいでしょう。
2つの入力(マスターデータとトランザクションデータ)をキーで結合するところは全て同じです。
出力内容がそれぞれ異なるので、どういう出力が欲しいのかに応じて使い分けます。
敵の特性に応じて武器を持ち替える感じですね。
MasterCheckはマスターが存在するかどうかを確認する小手調べ。
MasterBranchはマスターの内容に応じて振り分ける。
MasterJoinUpdateはマスターの内容を使ってトランザクションデータを書き換える。
MasterJoinはマスターとトランザクションデータを結合した新しいデータを生成する。 

分割演算子(@Split)は、MasterJoinの裏の姿です。
MasterJoinによって生成された結合モデルのデータを、元の(結合前の)2種類のデータモデルに分離します。

グループ結合演算子(@CoGroup)はAsakusaFWの全演算子の中で最強です。最終秘密兵器です。
これさえあれば何でも出来る反面、最適化されづらいというデメリットがあります。
ゴテゴテに武器を装備できるが小回りが利かない感じでしょうか。なるべく登場させないようにしましょう。


次は集計系。
集計といえばまずは単純集計演算子(@Summarize)です。
SQLのGROUP BYによるSUM・COUNT・MIN・MAXに当たる集計が出来ます。とってもオーソドックス(笑)

関数型プログラミングが得意な人にとっては、畳み込み演算子(@Fold)も馴染み易いでしょう。

グループ整列演算子(@GroupSort)は、複数のレコードにまたがった処理を行うことができます。その際に入力データをソートすることも出来るので、整列(sort)という名が付いているのでしょう。
ちなみに、演算子擬人化する人向けの裏設定ですが、GroupSortはCoGroupが変装した姿です。AsakusaFW内部では、GroupSortは“入力ポートが1つしかないCoGroup”です。


残りは特殊系。

フロー演算子(FlowPart)は演算子群をまとめて1つの演算子として扱えるようにするものです。要するにサブルーチンを作るイメージです。
代表役というかまとめ役というか。ワンピースのカポネの能力が近いかなぁ(爆)

チェックポイント演算子(checkpoint)は普通は使わないでしょう。
AsakusaFWはHadoopのMapReduceジョブを作る際に複数の演算子を1つのMapReduceジョブにまとめる最適化を行いますが、checkpointがあるとそこで必ずMapReduceジョブが終わりになります(ジョブが分割されます)。
役立たずのように見えますが、何か特別な使い道があるのかもしれません。

ロギング演算子(@Logging)はデバッグ用です。
そこを通過するデータをログファイルに出力します。書記みたいな感じ?
最近のAsakusaFWではトレース機能が実装されつつあるので、Loggingの出番は減っていくでしょう。

空演算子(empty)停止演算子(stop)は双子みたいな感じですね。
emptyは0件入力データを生成します。入力データが不要なポートに使用します。
stopは出力データが不要な場合の出力先として使用します。何でも食べちゃう腹ペコキャラ?


真面目な話に戻りますが、実際にFlow DSLを書こう(設計しよう)としたら、どの演算子を使えばよいか?というのは悩ましいところでしょう。

基本的には、各演算子の入力・出力に着目します。
抽出(Extract)とグループ結合(CoGroup)は最後の手段として、最初は選択肢から外します。その上で、

  • 入力ポート数が1つでいいのか、2つを結合するのか。
  • 1レコードずつ処理すればいいのか、前後のレコードも見たいのか。
  • 出力は入力1レコードにつき1レコードでいいのか、複数レコード出力したいのか。

といった観点で見ていけば、使える演算子は限られてくると思います。


Operator DSLで使うResultクラス

2013-12-19 00:00:00 | PG(分散処理)

Asakusa Framework Advent Calendar 2013の19日目です。
昨日のOption系クラスの話に続いて、Operator DSLで使うResultクラスについてです。

一部のユーザー演算子では、データの出力先を示すクラスとしてResultが使われます。
Resultを使ってデータを出力する場合は、Resultのaddメソッドを使う形となります。
addというメソッド名が示す通り、データを追加していくイメージなので、何レコードでも出力できます。
java.util.Listもaddメソッドで複数のオブジェクトを追加できるので、それと同じ感じですね。

と、自分は「addメソッドという名前なんだから、Resultで複数のレコードを出力できる」と思って疑わなかったんですが^^;、teppei_tosaさんの『GroupSortのハマりやすいところ』を見ると、そう思うのは自分がJavaに毒されている為だったのかもしれません。

AsakusaFWに限った話ではありませんが、ある技術に慣れていない人がどう考えるかについては、慣れている人からはなかなか想像できません。
pekokunさんの様に、AsakusaFWに慣れていない人が色々使ってみて「ここが分からん」と言ってくれると、ウェブページに書くネタが増えて嬉しいです(爆)
どんどん使って下さい(笑) 


Operator DSLで使うOption系クラス

2013-12-18 00:46:52 | PG(分散処理)

Asakusa Framework Advent Calendar 2013の18日目です。
そろそろOperator DSLの話に入っていきたいと思います(笑)

AsakusaFWでは、Flow DSLで演算子(メソッド)の実行順序を指定する感じでプログラミングします。
演算子には20個ちょっと種類があるのですが、どういう種類の演算子があるのか?というのは後日に譲るとして、、、これらの演算子は、実装方法に応じて「ユーザー演算子」と「コア演算子」の2つに分かれます。
ユーザー(プログラマー)が演算子(メソッド)の中身を実装しないといけないのがユーザー演算子、実装する必要が無いものがコア演算子です。

ユーザー演算子は、Operatorクラスを作り、その中にメソッドを定義します。メソッドにはどの種類の演算子かを示すアノテーションを付けます。
メソッド内は通常のJavaプログラミングと同じです。基本的には、引数のモデルクラスのオブジェクトを元に加工・演算を行い、モデルクラスのオブジェクトを出力します。
これが「Operator DSL」と呼ばれるものです。
Flow DSLやBatch DSLとは異なり、Operator DSLで定義した演算子(メソッド)は、アプリケーションの実行時に実際に呼ばれます。 

モデルクラスはDMDLで記述したデータモデル毎に生成されるクラスです。
例えば以下のような感じです(あくまでイメージであり、実際はもっと色々なメソッドやクラスがあります)。

public class Example {
  private IntOption value = new IntOption();
  private StringOption hoge = new StringOption();

  public int getValue() { return value.get(); }
  public void setValue(int value) { this.value.~; }
  public IntOption getValueOption() { return value; }

  public Text getHoge() { return hoge.get(); }
  public void setHoge(Text hoge) { this.hoge.~; }
  public String getHogeAsString() { return hoge.getAsString(); }
  public void setHogeAsString(String hoge) { this.hoge.~; }
  public StringOption getHogeOption() { return hoge; }
}

プロパティー毎にintやStringを扱うセッター・ゲッターメソッドがありますが、内部ではIntOptionやStringOptionという、AsakusaFW独自のクラスが使われています。
これらのOption系クラスは、値を保持する他にnullかどうかの情報を持っていたり、HadoopのWritableとの変換機能を担っていたりします。
(null関連の判定メソッドにはScalaのOptionクラスに似たものが感じられます(笑))
したがって、Option系クラスの特徴を知っていないと実行効率の悪いプログラミングをしてしまう可能性があります。

という訳で、各Optionクラスの使い方を自分のウェブページにまとめてみたので、ご覧下さい。(このブログでは書ききれないので^^;)