Funny Walking

人の個性への好奇心

SPVMを使って、オブジェクト指向的な実装を検証する

この記事は、Perl Advent Calendar 2020 1日目の記事です。

もう師走ですね。世界はコロナの影響で生活様式がびっくりするほど変わってしまいました。時間の流れを、いっそう早く感じます。みなさまはいかがでしょうか?

コロナの影響かどうか不明ですが、自分は転職先で適応障害という病気になりました。だいぶ回復してきましたが、まだ投薬はつづけております。

人生とはわからないものです。療養中に人生をふりかえっていたら面白い発見がありました。今回は、そんな話を書きます。具体的には、SPVMという新しい言語を使って、オブジェクト指向的な実装をためしたら面白かっったという内容です。さあ、1日目のアドベントカレンダー、はりきってまいりましょう!

SPVMとは?

本編に入る前に解説しておきましょう。SPVMとは、Static Perl Virtual Machine の略です。静的型付けプログラミング言語として実装されています

SPVMが作られた目的

Perl数値計算と配列処理を高速に行うことです

Perlの高速処理が求められる分野は、具体的にはバイオインフォマティクスの分野です。大量の文字列情報であるDNAの塩基配列を計算するために、文字列処理の得意なPerlがよく使われます。ただ、大量の情報を高速に処理するためには、CやC++などの言語のほうが向いています。そこで、Perlを使い馴れた人が覚えやすく、かつ、CとC++へのバインディングを容易に実装できるSPVMが作られました。

言語設計者による解説

SPVMの目的

SPVMでPerlのforループを100倍高速化する

SPVMの実装サンプル

GitHubの情報 を参考に、ベンチマークをしてみました。

コードの内容はGitHubのものと殆ど同じなので、リンクの掲載にとどめます。

SPVM/benchmark at master · yuki-kimoto/SPVM · GitHub

実行にあたり、変数名とループカウントだけ調整しました。結果が以下の通りです:

~/github/perl_test 🍌 perl benchmark-synopsys.pl 
Benchmark: timing 1000000 iterations of perl5_sum, spvm_sum, spvm_sum_native, spvm_sum_precompile...
 perl5_sum: 33 wallclock secs (33.24 usr +  0.02 sys = 33.26 CPU) @ 30066.15/s (n=1000000)
  spvm_sum: 10 wallclock secs (10.11 usr +  0.01 sys = 10.12 CPU) @ 98814.23/s (n=1000000)
spvm_sum_native:  1 wallclock secs ( 0.55 usr +  0.00 sys =  0.55 CPU) @ 1818181.82/s (n=1000000)
spvm_sum_precompile:  1 wallclock secs ( 0.55 usr +  0.00 sys =  0.55 CPU) @ 1818181.82/s (n=1000000)
                         Rate perl5_sum spvm_sum spvm_sum_native spvm_sum_precompile
perl5_sum             30066/s        --     -70%            -98%                -98%
spvm_sum              98814/s      229%       --            -95%                -95%
spvm_sum_native     1818182/s     5947%    1740%              --                  0%
spvm_sum_precompile 1818182/s     5947%    1740%              0%                  --

spvm_sum_nativeはCを呼び出したもの、spvm_sum_precompileはCに変換して実行したものです。Perlと比較して、かなり高速に動作します。

SPVMでオブジェクト指向的な実装を試す

さて、本題です

SPVMでオブジェクト指向的な実装がどこまで再現できるか、検証してみます。

検証の動機は、多角的な視点を開発者へ提供するためです。SPVMは、記事の執筆時点でver. 0.0927であり、本記事でも同じバージョンを使っています。ベータ版ということで、さまざまなユースケースを開発者へ提供することが必要だと自分は考えているのです。

オブジェクト指向設計の教材

だいたい、5章くらいまでのコードを参考にします。

では、さっそく行ってみましょうー

オブジェクトへのアクセサメソッドを設定

直接フィールド変数へアクセスさせないよう、アクセサを設定します。

SPVM

  sub rim : int ($self : self) { return $self->{rim}; }
  sub tire : float ($self : self) { return $self->{tire}; }

$self->rimで、アクセサを呼び出します。$self->{rim}と書くと、フィールド変数への直接アクセスになります。

引数の呼び出し順を抽象化

ハッシュを使って抽象化できます。

SPVM

  sub new : PracticalCode::Wheel ($args : SPVM::Hash) {
    my $self = new PracticalCode::Wheel;
    $self->{rim} = $args->get_int("rim");
    $self->{tire} = $args->get_float("tire");
    return $self;
  }

Test::Moreで検証

my $args = SPVM::Hash->new;
$args->set_int(rim => 26);
$args->set_float(tire => 1.5);

subtest "new" => sub {
  my $wheel = new PracticalCode::Wheel($args);
  isa_ok($wheel, 'PracticalCode::Wheel');
  done_testing;
};

use SPVM 'SPVM::Hash';と書いて、PerlからSPVMのモジュールを呼び出すことができます。

自分で作ったSPVMモジュールを、ハッシュ経由で渡す

$self->{wheel} = (PracticalCode::Wheel)$args->get("wheel");と書いてSPVM側で取り出します。

Perlで引数を設定するには、以下のように書きます。

my $args_gear = SPVM::Hash->new;
$args_gear->set(wheel => new PracticalCode::Wheel($args_wheel));

文字列を、ハッシュ経由で渡す

$self->{tape_color} = (string)$args->get("tape_color");と書いてSPVM側で取り出します。

Perlで引数を設定するには、以下のように書きます。

my $strs = SPVM::StringList->new_len(0);
my $args = SPVM::Hash->new;
$strs->push('green'); $args->set(tape_color => $strs->shift);

マニュアルを見ると、$args->set(tape_color => 'green');と書いても渡せるはずですが、自分の環境ではエラーになりました。開発者へ連絡しました。

metacpan.org

外部プログラムの呼び出しを抽象化

PracticalCode::Vendor::Wheelを外部プログラムだと仮定します。ラッパーモジュールをつくり、外部プログラムの呼び出しはラッパーを使うようにします。

SPVM

package PracticalCode::WheelWrapper {
  use SPVM::Hash;
  use PracticalCode::Vendor::Wheel;

  sub wheel : PracticalCode::Vendor::Wheel ($args : SPVM::Hash) {
    return PracticalCode::Vendor::Wheel->new(
      $args->get_int("rim"),
      $args->get_float("tire"),
    );
  }

}

引数の最後がカンマ,で終わっても、エラーにならないのがうれしいですよね。

Test::Moreで検証

my $args = SPVM::Hash->new;
$args->set_int(rim => 20);
$args->set_float(tire => 1.8);

subtest "new" => sub {
  isa_ok(PracticalCode::WheelWrapper->wheel($args), 'PracticalCode::Vendor::Wheel');
  done_testing;
};

ポリモーフィズムは、できない

ポリモーフィズムという概念は、存在しないそうです。開発者の方に聞きました。

動かないけれど、それっぽいコード

ファクトリ

package PracticalCode::Trip {
  use SPVM::Hash;

  has bicycles : int;
  has customers : int;
  has vehicle : int;

  sub new : PracticalCode::Trip ($args : SPVM::Hash) {
    my $self = new PracticalCode::Trip;
    $self->{bicycles} = $args->get_int("bicycles");
    $self->{customers} = $args->get_float("customers");
    $self->{vehicle} = $args->get_float("vehicle");
    return $self;
  }

# ...

  sub prepare : int ($self : self, $prepares : int) {
    for (my $i = 0; $i < 10; $++) {
        prepares->[i].prepare_trip($self);
      }
    }
  }

}

呼び出し対象その1(ドライバー)

package PracticalCode::Driver {

  sub prepare_trip : void ($trip : int[]) {
    gas_up($trip->vehicle);
    fill_water_tank($trip->vehicle);
  }

  sub gas_up : int ($vehicle) {
    #...
  }

  sub fill_water_tank : int ($vehicle) {
    #...
  }

}

呼び出し対象その2(旅行コーディネーター)

package PracticalCode::TripCoordinator {

  sub prepare_trip : int[] ($trip : int[]) {
    return buy_food($trip->customers);
  }

  sub buy_food : int ($customers) {
    #...
  }

}

呼び出し対象その3(メカニック)

package PracticalCode::Mechanic {

  sub prepare_trip : int[] ($trip : int[]) {
    my $res = int[];
    for (my $i = 0; $i < 10; $i++) {
      $res[$i] = prepare_bicycle($trip->bicycles->[$i]);
    }
    return $res;
  }

  sub prepare_bicycle : int ($bicycle) {
    #...
  }

}

ダックタイピング、インターフェース、テンプレートメソッド、抽象クラスの概念はSPVMに存在しません。

まとめ

自分の書き方には改善の余地がたくさんあり、勉強になりました。そして、新しい言語の開発に携わる面白さを体感しています。純粋にプログラミングをたのしむことは、新鮮な体験ですね。

今回の検証コードは、GitHubに上げています。全文が見たい方は、こちらからどうぞ。 github.com

明日はkfly8さんの、perl-users.jpについてのお話です!

【スプリントプランニングのインプットには、最新のプロダクトインクリメントが含まれるんだと分かって嬉しい】「スクラムガイドを読み解いてみよう」第7回 に参加してきました #ふりかえり実践会

今回は、スクラムイベントのスプリントプランニングに関しての話です。

retrospective.connpass.com

スクラムガイドのp.9 ですね。

プランニングの材料について

スプリントプランニングのインプットは、プロダクトバックログ、最新のプロダクトインクリメント、開発チ ームが予想するキャパシティと過去の実績である。プロダクトバックログから選択するアイテム数に ついては、開発チームが責任を持つ。スプリントで何を達成するかを評価できるのは、開発チーム だけである。



インプットとして最新のプロダクトインクリメントとあります。どういう意味でしょうか?

これは、たとえば、スプリントレビューで発見した新しい業務パターンへの対応をストーリーに含めるとか、要件定義中の新機能に追加要望を入れることなどが該当するようです。

スプリントゴールへの言及

スプリントゴールはスプリントの目的の集合であり、プロダクトバックログの実装によって実現するも のである。これは開発チームがインクリメントを構築する理由を知る指針となる。スプリントゴールは スプリントプランニングで作成する。スプリントゴールを設定することで、開発チームがスプリント終 了までに実装する機能を柔軟にできる。選択したプロダクトバックログアイテムは、一貫性のある機 能として届けられる。それがスプリントゴールになることもある。スプリントゴールがあれば、開発チ ームは一致団結して作業ができる。



スプリントゴールって解釈が広い概念だと思います。インクリメントとして届けられる時もあると思いますし、「新機能の実装にどれくらい現状のコードを改修しなければならないか」といったボリューム調査になる時もあるでしょう。

スプリントゴールを設定することで、ストーリーのフィーチャが現状の実装と合ってなかったら調整することも出来るのかなと思いました。

たとえば、業務フローを3パターン新しく追加したい場合、うまくいかない可能性を考慮して、最小限の実装でスプリントレビューできる業務フローを作成するとしても良いですね。最低1パターンできればOKですね。実装がめちゃくちゃ大変そうだと分かったときは、TDD前のスパイクへ方針転換することもできますね。

スプリントゴールは、抽象的な表現になってもいいと思います。柔軟にするということは、解釈の幅を広げるということですし。1%でも改善が出来ればそれで良いと思います。

スクラムに馴れてないチームがプランニングをするときの注意点

できるだけ小さいゴールを設定して、達成感を得られるようにすることが大切だという話が出てました。ただ、最小限のゴールさえ達成できなかったら無力感がすごいらしいです。。自分も経験ありますが、初めてスクラム開発を行う場合、ベロシティの計測も出来ていない状態なので、ストレッチゴールを設定しがちです。ベロシティが安定するまでは、自分たちができると思っていることよりも、1つ少ないことをやるようにすると良いと思いました。

セルフコンパッションと、千日回峰行を見ての感想

千日回峰行の動画をYouTubeで観て、感動した。


千日回峰行

一日に山道を30km歩き、寺の務めも果たす。だから睡眠は一日3時間。

1年に100日修行して、それを10年だったかな?それくらいやる。

マジか、すげぇな。信じられない。

自分は、セルフコンパッションで、自分がつらい気持ちになったときに優しい気持ちを自分に掛けることで、人生の辛さを解消しようと思っているけれど。

生活を修行の一つと捉えて、徹底して自分に厳しくする。ルールを課して、身体と心を整える。そんな状況に感動した。

最近、つらい事が続いて鬱々とした気持ちになっている。そんな中、勇気を頂いた。他人と自分を比べる必要はないが、心から湧き上がる感動の心を確かに感じることができた。

これが人生に必要なものだ。本当に人生に必要な感情だ。自分の常識の範疇を超えたものに出逢って、畏敬の念を抱かずにいられない。これが人間だ。ほんの少しだけでも、あやかりたい。自分も、ひたむきにひたすらに、目の前の事に没頭することで救いを得られるかもしれない。

ぼんやりと、しかし確実に、心の底に炎が湧き起こるのを感じ取ることができた。

吉祥寺.pm24【オンライン】参加ふりかえり #kichijojipm

いつもの通り、ふりかえりと感想を書いていこうと思います。

公式リンク

イベント全体

kichijojipm.connpass.com

発表内容のスライド

kichijojipm.connpass.com

発表内容ふりかえり

さて、みなさんの発表を振り返ります。

エンタープライズなうちでも簡単に触れるコンテナ環境をクラウド上にサクッと作るための技術

speakerdeck.com

自社内の、アーキテクトやエンジニア、セールスの方向けに、k8sの基礎、内部実装をトレーニングしたお話です。

用語が沢山出てきて勉強になったのは勿論ですが、トレーニングする人のコンテキストに合わせてトレーニングすることを意識されているのが印象的でした。説明って大事だなぁ、と思いました。

ハードウェアエンジニアにk8sを理解してもらうのって、なんとなくハードル高そうだなと思いました(自分もよく分かってないですけど。。)

ドメインモデラーにとって受託開発であることは制約なのか?

自社の開発リソースが足りなくて、受諾会社さんにお願いするケースは結構あります。自分の携わってる社内の新プロジェクトが正にそれで、会社の選定に結構苦労してるところです。

受諾開発だから、顧客のいったことだけを守るというマインドでは、確かに詰まらないですよね。発注する側としても、「こんな事言ったら面倒くさがられるのかな。。。」と、遠慮しがちになって、お互いにプラスにならない気がします。

であれば、受諾会社さんが持つ特定のビジネス領域の知見をモデリングいただいて、こちらの言ってる事とすり合わせしたほうが、より価値の高いソフトウェアが出来そうですよね。

受諾開発というドメインを突き詰めると、SaaS/パッケージ製品に似た性質を持つようになるという表現が印象に残りました。

本番障害に至る病

とても勉強になりました。特に、効率化のプレッシャーと最小限の効率で仕事を済ませたい欲求が、安全性の境界を押し下げてシステムが許容できない臨界点まで到達することを表現したラスムッセンモデルという言葉を初めて知れてよかった。

取返しのつかない失敗をする前に、故意に事故を起こす。カオスアーキテクチャという考え方も知れてよかった。

『More Effective Agile』 でも言及されていたような気がするが、アジャイル開発という文脈だと、「早い段階で検査と適応を実施せよ」という考え方に分類されるのかも知れない。

www.infoq.com

小さな家族を見守る

突然入院されることになり、家族である爬虫類の温度管理をやったお話です。Bot開発にSlack公式のフレームワークであるBoltを使われていました。

github.com

Botを作ると、色々なことがシンプルに出来るようになるのが嬉しいですよね。

Perlの依存ライブラリアップデートの話

依存ライブラリの更新ツールがPerlに非対応だったので、実装を調査してPerlで更新ツールを作成し、GitHub Actionsと組み合わせて自動でPRを出すところまで作ったお話。

Perl愛に溢れているなぁ。さすがはてなさんだなぁ。と、関心しました!

開発者が楽をするためのツールを、中身を調査して自分で作ってしまうという考え方が、好きです。

良かったこと

登壇できたことです。はじめてきちぴーで登壇できたのが嬉しい(オンラインだから皆の反応が見えないので、すこし寂しかったですが。。)

なので、下記のようなリアクションやフィードバックがとても嬉しいです。

自分を客観視できますし、今後の仕事に活かせる発見を頂けて、ありがとうございました!

課題に感じたこと

登壇で課題に感じたのは、参加者の顔も見えないし声も聞こえないしで、反応が無いのが辛かったことです。喋る内容についても、ごちゃごちゃと脱線せずに、一番言いたいことを熱量を持って伝えられればと思いました。

次こうしたい

5分のLTとはいえ、もっと具体的な事例を盛り込むべきだったなと。レトロスペクティブはチーム全体でやってましたが、内容を吟味するというよりも、周りの雰囲気を伺いながらやってた所があって、もっと濃密な時間を過ごしたいなぁ、と思いました。

ただ、人間同士の付き合いが仕事のすべてである以上、距離感を測りながら会話するのも仕事の一環なのでしょう。弊社でもリモートが増えて、週一でしかメンバーと合えないです。その範囲内で、効果的にコミュニケーション出来たなと思います。

おわりに

次は何を喋ろうかな。。と思いますが、認定スクラムマスターの取得を目標にしているので、やっぱりスクラム開発やアジャイルの文脈で話そうかと思います。Web APIについて勉強を始めたので、そのことも話したいのですが。

とりあえず、終わっておめでとうございます。参加できて嬉しかったです。ありがとうございました!

【スプリントゴールって、定義が難しいよねという話】「スクラムガイドを読み解いてみよう」第6回 に参加してきました #ふりかえり実践会

今回は、スクラムイベントに関しての話です。

retrospective.connpass.com

スクラムガイドのp.8 ですね。

スプリントの期間が1か月に制限されるのは、それ以上長すぎると予測可能性が低くなるからなんだそうです。

参加者にアンケートを取ったら、1週間が一番多かったです。自分も1週間でした。

アジャイルな見積もりと計画づくり』では、ストーリーポイントによる見積もりは規模の見積もりだと書かれています。なので、「一週間で終わらせるぞ!」と思って頑張って見積もるというより、「チームのベロシティ(生産性)がこれくらいだから、一週間ではこれくらい終わるよね」みたいな、「ベロシティを測ること」が目的なのかなーと、今のところ思ってます。

そもそも、最初はベロシティがない状態でスタートするわけだから、当然なのかもしれません。

スプリントゴールって、具体的に何ですか?

ガイドには、「スプリントプランニングで作成する。プロダクトバックログの実装によって実現する」と書いてあります。

定義が曖昧だなーという印象を受けました。不親切というか。

スクラムは、「検査と適応」を実現するためのフレームワークだと理解してます。そうすると、ベロシティを測ることは「検査」に当たりますよね。

では、「適応」はどのタイミングでするのか?デイリースクラムですかね?

スプリントゴールに、「ベロシティを測ること」を含めるのは、アリかナシか、気になりました。

スプリントプランニングは、メンバー全員の暗黙の了解を、明示的なものにしてあげること(言語化?)が目的のように思いました。これが、適応ということでしょうか?

まとまりの無い文章になりましたが、一番気になったことは、スプリントゴールにベロシティを測ること、つまり、チーム全体のメタ認知を獲得することを設定して良いか?ということです。

レビューできるインクリメントを作成することだけが、スプリントゴールではないと思いました。スプリントゴールは、曖昧というより、柔軟な解釈を許しているという表現が適切ですね。

【スクラムマスターはサーバントリーダーである】「スクラムガイドを読み解いてみよう」第5回 に参加してきました #ふりかえり実践会

8/29(土)に開催された下記イベントに参加してきました。感想をまとめてみます。

retrospective.connpass.com

スクラムガイド(2017年10月 Japanese版をダウンロードして確認してみました) www.scrumguides.org

スクラムガイドを読んだことがなかったので、いいキッカケになったというか、ちょうど自分に合っていた勉強会だったなという印象です。ありがとうございます。

会社でスクラムを取り入れて1か月くらいなので、他の人の知見が聴けるのは嬉しいですね。

スクラムマスターについて、スクラムガイドに「サーバントリーダーである」という項目があり、これは以前のスクラムガイドが更新されたときに追加された項目だそうです。

サーバントリーダーというのは、メンバーを引っ張る存在というよりも、メンバーがリーダーの役割を担えるようにコーチする役割がメインなのだと解釈しました。



チームジャーニーには、「リーダーではなく、リード」という一節がありました。何となくですが、「リード」という言葉からは、人に役割を強く結びつけないという印象を受けます。



サーバントリーダーが、リーダーではなくコーチなのだとしたら、スクラムマスターは、伝道師、または、スクラムコーチと呼べるのかもしれません。


良い学びでした。ありがとうございました。


スクラムマスターチェックリストというのもあるそうです。こちらも、面白い資料ですね。

https://scrummasterchecklist.org/pdf/Scrum-Master-Checklist-jp.pdf

経験から学ぶための、ウイークリーレトロスペクティブ 2020-08-w3

一週間のふりかえり

集中度グラフ(集中度:1-10)

スプリントの進捗が良くない。テンションが上がらない。

土日の値が高いのは、登壇用のスライドを作ってリハーサルしてたからか。

f:id:omokawa765:20200824222207p:plain
20-08-03w performance

満足度グラフ(満足度:1-10)

MBOの進行のため、調整中

1週間の主要なトピック

  • 非エンジニアの方にエンジニアリング研修を実施
  • スクラム開発5週目
  • 会社の新規プロジェクトに大きな動きがあった。新しいツールを調査

得た学び

  • 仕事が進捗しないと、精神的につらい。
  • 結果とカイゼンを混同しない

得た学び(スクラム編)

  • ふりかえりは、ガッツリやったほうがいい。たとえ8hだろうと、やったほうが学びは多い
  • 失敗しても、登壇のネタになるのでどんどん挑戦して失敗しよう

外部の勉強会で登壇

下記の勉強会でスクラム開発について、失敗とカイゼンについてお話した。

gaiax.connpass.com

Youtube Liveも実施された。

https://www.youtube.com/watch?v=PlFqb3z3MG8

いくつかフィードバック頂いたので、カイゼンの参考にする。ありがとうございました!!

以上