第7回 Software Architecture: The Hard Parts 読書会@リモート

第7回 Software Architecture: The Hard Parts 読書会 - connpass


参加者トピック

ディスカッション

9. Data Ownership and Distributed Transactions

  • 「複数のサービスが同じデータベーススキーマにアクセスするのはOK、1つのサービスが複数のデータベーススキーマにアクセスするのはNG」
    • そういう割り切りありだなって思った
  • 普通はテーブルの所有権って考えるものなのか
    • モノリシックアプリケーションならともかく、マイクロサービスアーキテクチャを考えているなら考えるものだと思う
    • 仕事ではサービス=プロジェクトとして管理している
      • 誰が所有してるかはすぐ分かるようになっていて欲しい
  • audit だけ用途が違うから、別に複数のサービスが書き込んでいるとしても、複雑になってないと思ってしまった
  • Q 所有権って概念って一般的?
    • A モノリシックサービスが分解される過程で、データアクセス元のサービスを意識するようになった結果生じた概念では?
    • ...自分もそんな気はする。モノリスなサービスしか経験してないので誰が所有しているかはっきりしなくてもいい現場感?的な。
  • 共同所有権シナリオ、いい思い出がないので感情的に否定しがち
  • 経験談
    • Inventory Serviceで管理する在庫は自社在庫じゃない場合があった
    • 他社の在庫管理システムで扱ってる在庫の扱いが違うとかで大変

Table Split Technique

Data Domain Technique

  • どの辺がテクニックなんだろうと思ったけど、テーブルを宙に浮かせないで、境界づけられたコンテキストに納めて人間が認識できるようにするところがテクニックなのかな
  • その行を追加・更新したプログラムID、みたいな列があるのを今までのすべての会社で経験してて、ガバナンスやなって思いました

Delegate Technique

  • (全体的に)トレードオフ分析の表は、メリットとデメリットを対比してるわけでもないし、それぞれに重みがあるわけでもないし、この表だけで分析するのは難しそう
  • operational characteristics ってちょうどいい言葉(訳語)がなさそうで、「運用特性」以外の言葉が生まれて欲しい

Service Consolidation Technique

  • データの所有権を考えていたらサービスが肥大化する場合があるテクニック
    • デプロイ/リリースサイクルの向上が大正義な文脈では採用しにくいやつだ

Data Ownership Summary

  • どちらも永続化するのに、テーブルとキューで扱いが違うの面白い
    • テーブル:できるだけ境界づけられたコンテキストに配置する
    • キュー:境界づけられたコンテキストの外側に配置されている

Distributed Transactions

Eventual Consistency Patterns

Background Synchronization Pattern

  • トレードオフ
    • すべてのデータソースが結合する
      • 関連するサービスが共同所有権を持つようになってしまう
    • 境界づけられたコンテキストが守られない
      • きっかけは顧客プロファイルサービスでも、サポート契約、支払い請求について独自のビジネスルールがあるかもしれない
  • このパターンが有効な場面は、互いに通信せず、データも共有しない閉じた(自己完結した)異なる種類のシステムである。
    • 異なるサービスで同じデータを適用、参照できるのに綺麗に分離されてるってほんとかな
    • プロファイル、契約、請求が、外の世界の別々のサービスになっている様子を考えるとありそうな気がしてきました

Orchestrated Request-Based Pattern

  • 補償トランザクションで解消できなかった問題を解消するには人間の介入が必要で、redo ログ的な記録が肥大化したりするなど、重くなるのは避けられないんでしょうか?
    • 基本的にそれぞれのサービスが自身のトランザクションを補償するためのAPIを設けるはず
    • オーケストレーターはそれを呼び出すだけになるはず

Event-Based Pattern

Sysops Squad Saga: Data Ownership for Ticket Processing

  • 境界づけられたコンテキストとかドメインとかの言葉がどの文脈で使われてるかわからないので、なんか言葉に振り回されている感じがすごい
  • そのせいで、「チケット完了サービス」という単語がじわじわ面白くなってきてしまった

Chapter 10. Distributed Data Access

“分散システムにおけるデータの扱いについては、『データベースリファクタリング』の共著者であるPramod Sadalage、『Data Mesh』の刊行を控えたZhamak Dehghaniを共著者として迎え” 気合が入っている章らしいです

参考情報

ALONE〜孤独のサバイバー〜シーズン2を観た

邦題「ALONE〜孤独のサバイバー〜」を一気に観た - yujioramaの日記に続いてシーズン2も観た。シーズン3以降は有料。

 

シーズン1と違って参加者のスキルが高くなっていて、やり方の違いより、効率性を追求してるところが見どころだった。

筋トレ始めたり、トレーニング設備作って楽しんでる人もいれば、最初からずっと辛いひもじいを続けてる人もいて、多様性があるなぁと思った。

開始地点に平地が無くてずっと困ってるところや、熊の親子と共存してるところにアザラシが割り込んで食料の取り合いになってしまうところは、生存競争してる感じで印象深い。

 

Perl Carton Buildpack のプロトタイプで遊んでた

背景

  • Heroku や Cloud Foundry などで利用されている Cloud Native Buildpacks という技術がある
  • いわゆる S2C (Source Code to Container Image)
    • Dockerfile の関門をスキップできる
  • .NET Core/Go/Java/Node.js/Python/PHP/Ruby には対応している
  • 入門ドキュメントは一通り読んでるし、自作できるのでは?

できたもの

yujiorama/perl-carton-buildpack

  • シェルスクリプトでいろいろ書かれている、テストのないプロトタイプ
  • Perl アプリケーションのコンテナイメージを1コマンドで作成
  • Carton に対応
  • .perl-version によるバージョン指定に対応
  • Plack に少し対応( plackup する)

コンテナイメージ your-app を作成する様子(一部)。

$ pack build your-app \
--builder paketobuildpacks/builder:full \
--buildpack yujiorama/perl-carton-buildpack \
--path /path/to/your-app 
full: Pulling from paketobuildpacks/builder
Digest: sha256:4cfa401f11219ac10e8f756c244a6acc2d7cdd7aca42759a4e2aa616da7f1dfa
Status: Image is up to date for paketobuildpacks/builder:full
full-cnb: Pulling from paketobuildpacks/run
Digest: sha256:4f113e8c504574b4f298ed7fc14dcfe25f347cf51a6bbd77e7765f896b668e60
Status: Image is up to date for paketobuildpacks/run:full-cnb
ghcr.io/yujiorama/buildpacks/yujiorama_perl-carton-buildpack@sha256:ce9edb0104d2b03e29c0aef75e02e22d264d81285b34853fea360b1f4a43c00a: Pulling from yujiorama/buildpacks/yujiorama_perl-carton-buildpack
614925ba7a2b: Pull complete
Digest: sha256:ce9edb0104d2b03e29c0aef75e02e22d264d81285b34853fea360b1f4a43c00a
Status: Downloaded newer image for ghcr.io/yujiorama/buildpacks/yujiorama_perl-carton-buildpack@sha256:ce9edb0104d2b03e29c0aef75e02e22d264d81285b34853fea360b1f4a43c00a
===> ANALYZING
Previous image with name "hello-world-plackup" not found
===> DETECTING
yujiorama/perl-carton-buildpack 0.0.2
===> RESTORING
Restoring metadata for "yujiorama/perl-carton-buildpack:xbuild" from cache
Restoring data for "yujiorama/perl-carton-buildpack:xbuild" from cache
Restoring data for SBOM from cache
===> BUILDING
---> Perl-Carton Buildpack
---> Configure xbuild layer

やったこと

所感

  • 標準化された仕様にたどり着くまでが長かった
    • 最初に Reference を読み飛ばして進めたのが敗因
    • 最終的に buildpacks/spec を読めばいいことが分かっていろいろ捗った
    • 既存の Buildpack が使用しているAPIバージョンは必ずしも最新化されておらず、見るものによって仕様の記述と合わなくて混乱していたのも敗因
  • 具体例のない仕様に手こずった
    • 特に buildpacks/rfcs - 0031-bionic-mixins
    • ビルドフェーズで makegit を利用するために必要だった
    • Buildpack API には記載されているけど使い方とかが何もわからないという
    • paketobuildpacks/run:full-cnb などのイメージラベル io.buildpacks.stack.mixins に指定できる要素が並んでいるところを発見したりした
  • APIが明確でテストも書きやすい Go で作ったほうがいい
    • 既存の Buildpack はだいたい Go で書かれていたのだけど、本質的には Go じゃなくてもいい
    • 特にテスト容易性が高まるので Go で書いた方がいい

邦題「ALONE〜孤独のサバイバー〜」を一気に観た

 

舞台は野生の熊や狼が徘徊する無人島。ヘリコプターでばらばらの場所に配置された十人の参加者が、最後の一人になるまでサバイバルし続けている。

YouTubeでブッシュクラフトの動画を見るのが好きなんだけど、こういう作られた感を排除した作り話も好きです。

 

序盤はみんな元気で、それぞれなりにブッシュクラフトしているのが面白い。熊や狼の存在がアピールされるのはこの辺だけで、ひやひやしながらも安心して見れる。

脱落者が出てくる頃になると、泣きながら家族に会いたいと言っていた翌朝にはまだ頑張れるぜ、と意気込んでいたりするので、見てる方の感情を無駄に揺さぶられる感じになってくる。食料を求めて海岸をさまよったり網漁したり設置罠しかけたり、いろんなアプローチが見どころかな。

終盤は逃げていた過去に向き合ったり、新しい自分を見つけてしまったり、神に感謝したり、いろいろなことが起き始める。人数が減ると一人ひとりの時間が長くなるので、30分くらい自分語りしてる回もあった(気がする)。大雨、暴風、昼間でも氷点下、ととにかく環境がひどいことになっているので、見ていると不安になってくる。

ほとんどの参加者はやりきった、あるいは、やることを見出して去っていくんだけど、その後の様子が収録されてないのは残念だった(最後まで残った人のエピソードはあってよかった)。

心の中のもやもやを解消する方法

背景

  • 常用してるIntelliJ IDEAを開発してるJetBrainsから開発者向けアンケート調査が届いていた
  • 暇つぶしに回答してたら「メンタルヘルスを解消するためにやってることを教えて」みたいな項目があった
  • 「知らん、何もやってない」と回答した後に、やってることがあったので今この文章を書いているけど、普通のことしかやってなかった

心の中のもやもやを解消する方法

1. 寝る

  • ただ寝るだけでもかなり効果がある
  • 人間なら寝ない日はほとんどないはずなので、基本的には毎日もやもやが解消されているはず
  • 解消しない場合は異常事態なので次の手段に進む
2. 人に話を聞いてもらう
  • 相談ではなく「話を聞いてもらう」ことがポイント(だと思ってる)
  • 自分で解消できないからもやもやしているので、アドバイスいただいたり応援していただいても、たぶん残ってしまう
  • 相手がいることで、謎のおもてなし精神が活発化し、見逃していた条件や論理矛盾が発見される(場合がある)
  • 解消しない場合は最終手段に進む

3. 文字にする

  • 解消するのは不可能だと諦観し、それを平常運転だと受け入れるための儀式(だと思ってる)
  • 文字にすると思考ループから追い出すことができるので余力が生まれる
  • できた余力を、現実を受け入れるほうに向ける
  • SNSには書かない(内心をむき出しにするポリシーなら書いてもよい)
  • 少しでも普遍性のあるもやもやなら、検索エンジンやフィードなど、アクセスにワンクッション挟むメディアに書く

TLA+に再挑戦(2022.4)

英語のドキュメント を読んだけどあまり理解できてなかったので 日本語 で再挑戦する会。

進捗

7.4 アルゴリズムの特性

二分探索を例に、性能や境界条件を検査する。

  • 補助関数
    • OrderedSeqOf(set, n)
      • set を値域とする要素数 n のシーケンスのうち、すべて昇順になっているシーケンスを生成する
    • Range(f) == { f[x] : x \in DOMAIN f }
      • DOMAIN f は f の取り得るすべての入力
        • f がシーケンスならすべての添え字になる
      • つまり f のすべての値を返すようになっている
      • 途中でいきなり PT!Range(f) に置き換えられている…
  • 入力
    • found_index
      • 初期値の 0 は要素が見つからないとき
  • 出力?
    • if target \in Range(seq) がわからない
    • なんで if target \in seq じゃないんだろう
    • \in に渡せるのは集合だけど、seq はシーケンスだから
      • 型変換しているだけだったというオチだった
  • 時間計算量の検証
    • 二分探索の時間計算量は O(log(n)) になるはず
    • 逆にループ回数を計測して 2^n < length(n) で判断することもできる
      • 実際には 2^{n-1} で判断する
  • 二分探索アルゴリズムの有名なバグ
---------------------------- MODULE binarysearch ----------------------------
EXTENDS TLC, Integers, Sequences

PT == INSTANCE PT

\* set を値域とする要素数 n のシーケンスのうち、すべて昇順になっているシーケンスを生成する
OrderedSeqOf(set, n) ==
    { seq \in PT!SeqOf(set, n):
        \A x \in 2..Len(seq):
            seq[x] >= seq[x-1] }

MaxInt == 7

(*--algorithm binarysearch
variables
    seq \in OrderedSeqOf(1..MaxInt, MaxInt),
    low = 1,
    high = Len(seq),
    target \in 1..MaxInt,
    found_index = 0,
    counter = 0,
    m = 0,
    lh = 0;

define
    Pow2(n) ==
        LET f[x \in 0..n] ==
            IF x = 0
            THEN 1
            ELSE 2 * f[x-1]
        IN f[n]

    NoOverflows ==
        \A x \in {m, lh, low, high}:
            x <= MaxInt
end define;

begin
    Search:
        while low <= high do
            counter := counter + 1;
            lh := high - low;
            m := high - (lh \div 2);
            if seq[m] = target then
                found_index := m;
                goto Result;
            elsif seq[m] < target /\ m < high then
                low := m + 1;
            else
                high := m - 1;
            end if;
        end while;
    Result:
        \* 計算量を評価
        if Len(seq) > 0 then
            assert Pow2(counter - 1) <= Len(seq);
        end if;
        \* 結果を評価
        if target \in PT!Range(seq) then
            assert seq[found_index] = target;
        else
            assert found_index = 0;
        end if;
end algorithm; *)

7.5 マルチプロセスアルゴリズム

  • すべてのプロセスが終了する前にアサーションを検査する
    • ハードコードするのではなく、活性要件(不変条件と違う?)として記述する
    • <>[]アルゴリズムが確実に終了することを検査する
  • ステップを GetIncrement に分けると検査が失敗する
    • 複数のプロセスが同時に Increment へ進入すると、いずれかのプロセスによる counter の更新が上書きされてしまう
    • GetIncrement を統合するか、クリティカルセクションを設けるしかない
counter: 0
goal: 3
pc: <<"Get", "Get", "Get">>
----
counter: 0
goal: 3
pc: <<"Increment", "Get", "Get">>
----
counter: 1
goal: 3
pc: <<"Done", "Get", "Get">>
----
counter: 1
goal: 3
pc: <<"Done", "Get", "Increment">>
----
counter: 2
goal: 3
pc: <<"Done", "Done", "Increment">>
----
----
counter: 2
goal: 3
pc: <<"Done", "Done", "Done">>
----

8.1 リンクリスト

  • ユースケース
    • 循環を持つリンクリストをアルゴリズムが生成しないようにする。
      • 検証したいのはアルゴリズムで、リンクリストを部品として使用するっぽい
    • 循環を見つけ出すアルゴリズムを記述する。
      • リンクリスト自体を検証したいっぽい
    • 循環を持つリンクリストが与えられてもシステムが正しく動作するようにする。
      • 検証したいのはシステムで、リンクリストを部品として使用するっぽい
  • データ構造は関数、構造体として表すのが一般的
    • データ構造の名前と同じ演算子を定義する慣例になっている LinkedLists(Nodes)
  • Nodes はメモリアドレスの集合である なんでいきなりメモリの話してるの?
  • リンクリストは関数集合 [ Nodes -> Nodes ] の集合になる 構造体の表記を関数と呼んでいる?

参考リンク

第6回 Software Architecture: The Hard Parts 読書会@リモート

第6回 Software Architecture: The Hard Parts 読書会 - connpass


参加者トピック

  • ACMプロフェッショナル会員の特典だったO'Reilly Learning Pathの無料アクセスが6月に終了する
  • ブラックフライデーに割引クーポンが出がちなのでそれを待とうかな
  • 本はともかくAudio Bookが代替できなくて辛い
    • 人間が読んでいる
  • 有明テニスの森公園でテニスやってくる
  • 原因不明の体調不良が続いてたので、運動不足を疑っている
    • 卓球フィットネス始めた、全球スマッシュを強要するのでとても体力を使う
    • Oculusで遊べるテーブルテニスVRお勧め
  • BlueMix経由でO'Reilly Learning Pathを利用してる
  • VPで遊んでいると筋肉が増える

ディスカッション

Part II. Putting Things Back Together

Chapter 8. Reuse Patterns

Chapter 8. Code Replication

Chapter 8. Shared Library

  • バージョン管理のところは、セマンティックバージョニングを前提にしているよね

Chapter 8. Shared Service

  • 仮にそれぞれのサービスがマイクロサービスになっているとして、なんで Shared Service にアクセスしないといけないのか理解できない
    • どういう役割なのかわからない
    • 誰がオーナーなのかわからない
    • 個人的に最高のアンチパターン
  • 後方互換性を保つために必要なコスト
    • 古いバージョンのアプリ用のコンテナ動かし続けるの大変そう
    • サービスの動作を保証し続けるのも大変そう

Chapter 8. Sidecars and Service Mesh

  • 前の章とつながってない
    • 値引き機能みたいな具体例がいなくなっているのはなんでだろう
    • バージョン管理とか後方互換性の話がなくなっているのはなんでだろう
  • ヘキサゴナル・アーキテクチャサイドカーを結びつける論点が弱い

Chapter 8. Sysops Squad Saga: Common Infrastructure Logic

  • 結局 JSONtoXML ライブラリをサイドカーに入れたのか入れないのか
    • 入れてない
    • サイズは重要(たいした大きさじゃないからよしとする)
    • 利用したいチームが全体の半数を超えてないから入れない
      • 17チームいて半数に満たないってどれだけ巨大な組織なの…
  • 質問にちゃんと答えてない感じがする
  • Sysops Squad Saga 全体的に納得いかないところが多い

Chapter8. Code Reuse: When Does It Add Value

  • ソフトウェアアーキテクチャの基礎第16章と同じ話だった
  • 過剰な再利用がもたらす危険性は、20世紀に流行したオーケストレーション駆動のサービス指向アーキテクチャで、多くのアーキテクトが学んできたことだ。
    • 再利用が問題視されていたのは、オブジェクト指向プログラミングのほうの文脈じゃない?
    • 共有にしたサービスが知らない知識を取得するため、さらに他のサービスに依存してしまう、みたいなところはたしかに問題っぽい

Chapter 8. Sysops Squad Saga: Shared Domain Functionality

  • Taylenの主張が面白い
    • Taylen: それがどうした。どれもバックエンド機能だから気にする人なんていない。バックエンド機能が高速に応答する必要はないし、失敗したとしてもすぐに復旧するはずだ。

参考情報