強いて言えば「集約どう実装するのかなを考える」会 に行ってきた #アーキ部

強いて言えば「集約どう実装するのかなを考える」会 に参加しました。オンライン開催。簡単に所感をまとめます。

architect-club.connpass.com

所感

ドメインモデルのトリレンマは初めて知りました。基本的には性能を保ちつつ完全性と純粋性のバランスを取るのがいいんだろうか。なんとなく repository をモックにするくらいならメリットに比べてテスト容易性が犠牲になってるとは思わないので、その程度なら許容してもいいかも。

「Parse, don't validate」や「Always-Valid Domain Model」のような設計はよさそうだけど、いわゆる「異なる概念」というのをいかに見つけ出すかが重要そう。当たり前だけど。

あと、最後の made functional の例を Java で書くとどうなるんだろう🤔 (あとで考える)

あとで読む。

以下、メモから抜粋。

  • カートの情報をDBから復元してメモリにすべてロードする
    • カートに追加
    • 不変条件を満たすかチェック
    • スタジアム
      • ランクごとの座席数上限
      • OutOfMemory
  • ドメインモデルのトリレンマ
    • 完全性
      • ドメインモデルにロジックを押し込める
      • 高凝集/変更容易性
    • 純粋性
      • 他のレイヤに依存しない
      • テスト容易性/移植性
    • 性能
    • すべてメモリにロードする設計だと上限次第では性能が犠牲になる
  • 完全性+性能
    • すべてメモリにロードしないが参照系では必要になる
      • 更新と参照で扱いたいモデルが違う
    • Read, Write を分離する
      • 参照はページネーションしたり
      • repository をドメインモデルで受け取って上限チェックとカート追加する?
      • テストではモックが必要 = 純粋性は失われる
    • 遅延ロードを使う
      • 意図しないところでクエリが流れるので難易度高め
  • 純粋性+性能
  • 性能を保ちつつ完全性と純粋性のメリットを享受したい
  • 状態の変更やチェック (不変条件) をドメイン層に実装する
  • 状態によって定義される振る舞いは違うはず
    • 状態によって型を分ける
  • 高凝集
    • 複数の責務が混ざってるものは高凝集ではない
    • 異なる振る舞いをするものは異なるものと見なす
    • 型で表現する
  • 複雑さ (異なる概念) を型で表現するのが重要
    • 重複してるかもしれないユーザーと重複していないことが保証されるユーザーは別の概念 (定義される振る舞いが異なる)
      • ユーザー重複チェックは重複してるかもしれないユーザーの振る舞い
      • ユーザー登録は重複していないことが保証されるユーザーの振る舞い
    • ↑を型で表現する
  • Parse, don't validate
    • バリデーションと同時に型を変換する
    • 失敗可能性を前へ
  • Always-Valid Domain Model
  • made functional
  • 構造が同じでも振る舞いが違うなら型を分ける

セキュア・バイ・デザイン (01)

セキュア・バイ・デザインの第1部を流し読み。

www.amazon.co.jp

設計の精度を上げることで自然とセキュリティ対策にもなる。なるほど、この本のタイトルの意味がよく分かった。

メモから抜粋。

  • セキュリティそのものではなく設計に目を向ける
  • CIA-T
    • 機密性 (Confidentiality)
    • 完全性 (Integrity)
    • 可用性 (Availability)
    • 追跡可能性 (Traceability)
  • バリデーション
    • サイズチェック: 入力値が期待する範囲内に収まっているか
    • 字句 (lexical content) チェック: 入力値に正当な文字や正しいエンコードが使われているか
    • 構文チェック: 正しいフォーマットに従っているか
  • 多層セキュリティ (security in depth)
  • 浅いモデリング/深いモデリング
    • 概念を明示的に表現する
    • ビジネスルールをコードで表す
  • モデリングの際に上限や下限について聞く

2022年のふりかえりと2023年に向けて

年末年始は帰省先で過ごしています。2022年はあっという間に終わってしまった感。昨年も同じこと書いてるけど。

2021年のふりかえりと2022年に向けて - kntmr-blog

特に、自分の役割的にスクラムやプロジェクトマネジメントのスキル&経験を積むのが最優先かもしれない。前に PMBOKガイド 第7版 を買ったけど、積読しちゃってるので読もうっと。

2021年から2022年の秋頃にかけての1年ちょっと、toB 寄りのプロダクトチームでリーダーをやってましたが、昨年の秋頃からは少し大きめのプロジェクトチームに参画。4チームに分かれているうちの1チームをリードする役割に。ちなみに PMBOKガイド 第7版 はまだ積読のまま...😇

以前のプロダクトチームでは、最大で10名以上のタスクを見てるような状態でちょっと手一杯感があったしスクラムにもなってなかったと思われる...。

今は5-6名程度のチームなので、改めてスクラムチームとしてチームビルディングして開発をリードしたい気持ち。

それから、今後は、単純に自分の意見を発信するだけではなくて、意思決定に関わるような立ち回りができるようになった方がいいかもしれない。物事を動かすためには人を動かす必要があり、人を動かすためには何かしらの理由や動機付けが必要なのかなって思うのですが、手元にある限られた情報でいかにこれらを判断できるかが重要な気がしています。あと、こういう判断をどれくらい早くできるか。特に自分はこのあたりの瞬発力が足りない気がしている。

今後、SRE のスキルを身に付けて Embedded SRE の役割を担えるようになりたい。

個人的にはアラートや負荷対策への立ち回りは以前よりできている気がするけど、Embedded SRE の活動当初に比べて、SRE チームとプロダクトチームの橋渡しの役割が少し薄れてきてしまっている気がする今日この頃。現状、プロダクトチームから離れてプロジェクトのメンバーになっているのもあるかもしれない。特に中長期の改善活動みたいなのがあまりできていない気がするのでなんとかしたい。

あと、昨年の夏頃から友人の会社で副業を始めました。主にデザイン制作をやっている会社でコーディングのサポートをしています。がっつりフロントエンドというわけではなくて jQuery 中心の少しレガシーな感じの実装だけど、前職の頃にわりとよくやっていた開発と似ているのでそこそこ自分の経験やスキルは生かせそう。あとは、ソースコードのバージョン管理だったり開発環境周りのアドバイスとかできたらいいかなって。

iframe 組み込みの YouTube Player をモーダル表示して自動再生したい

iframe 組み込みの YouTube Player をモーダルに表示して、さらにモーダルを表示したタイミングで自動再生したい。あと、同一ページで2つの YouTube 動画を扱うパターン。

YouTube のモーダル表示については軽くググったらいい感じのライブラリがあった。

kakechimaru.com

が、YouTube の仕様でモバイル環境では自動再生 (autoplay) ができない模様...。

YouTube Player API Reference for iframe Embeds - Google Developers

「警告: ユーザーが費用負担する携帯電話ネットワーク経由で要求していないダウンロードを防止するために、iOSSafari では組み込みメディアを自動再生できません。必ずユーザーが自分で再生します。」

少し調べた感じでは、このライブラリを使う以上はモバイル環境での自動再生が厳しそうなので自分で API を叩くことにしました。備忘録。

サンプルコード。

<!-- それぞれの YouTube 動画を再生するためのボタンがあるイメージ -->
<div class="btn" data-video-id="xxxxx" data-channel="youtube">YouTube 1</div>
<div class="btn" data-video-id="yyyyy" data-channel="youtube">YouTube 2</div>

<!-- モーダルは普通のやつ -->
<div id="modal-overlay">
  <div id="modal-wrap">
    <div id="modal-content">
      <div class="inner">
        <!-- ここに iframe の YouTube Player が差し込まれる  -->
        <div id="player"></div>
      </div>
      <p class="modal-close">閉じる</p>
    </div>
  </div>
</div>

イベントハンドラYouTube API の呼び出し。

$(function() {
  $('.btn').click(function() {
    $('#modal-overlay, #modal-content').fadeIn();
    //player.playVideo();
    player.loadVideoById($(this).data('videoId'));
  });
  $('#modal-overlay, .modal-close').click(function() {
    $('#modal-overlay, #modal-content').fadeOut();
    player.stopVideo();
  });
});

var player;
function onYouTubePlayerAPIReady() {
  player = new YT.Player('player', {
    width: '640',
    height: '360',
    videoId: '',
    playerVars: {
      'autoplay': 1,
      'controls': 1
    },
    events: {
      'onReady': onPlayerReady,
      'onStateChange': onPlayerStateChange
    },
  });
}
function onPlayerReady(event) {
}
function onPlayerStateChange(event) {
}

モーダルを表示したタイミングで Player#playVideo を呼び出せばイケると思ったけど、任意の動画IDが指定できない。そこで、YT.PlayervideoId を空で初期化しておきつつ、再生したいタイミングで Player#loadVideoById に任意の動画IDが指定して呼び出す。

JJUG CCC 2022 Fall に行ってきた #jjug_ccc

JJUG CCC 2022 Fall に参加しました。オンライン開催。簡単に所感をまとめます。

jjug.doorkeeper.jp

所感

サーキットブレーカーは設定値の決め方がポイントな気がする。業務要件やメトリクスで基準があるとよさそう。あと、サーキットブレーカーみたいな仕組みは発動しないに越したことはないのよね...。

SELECT FOR UPDATE でロックするのはよくあるけど、ロックよりアプリケーション側でリトライする方がコントロールしやすいのかなと思いました。その点、Cloud Spanner とかはそういう思想になってるっぽいので腹落ちしたような気がする。

コンテナについてはまだまだ知らないことが多い。知らないと性能を十分に生かせなかったりハマったりすることが多そうなのでちゃんと勉強しないと...。

ビズリーチの話は共感するところが多くてよかったです。負債解消やシステムのリアーキだけじゃなくて、組織構造まで考えてたり、仕様や設計をシンプルに再構成するために PdM や事業側と調整するのが特にいいと思いました。あと、不確実性の高いことが多いからこそ、計画や予実管理するスキルが重要という話が刺さりました。

Spring Framework, Spring Boot のメジャーバージョンアップは5年ぶりなんですね。Spring 標準がいろいろな機能をサポートすることで依存ライブラリが減らせるのがよさそう。

サイボウズの kintone チームの話は、改善活動をプロジェクト制にして組織的に進めてるのがよさそうでした。組織の活動にすることでビジネスサイドに説得しやすいし優先度判断で迷うことが減りそうでよさそう。

セッションの資料とアーカイブはこちらにまとめられています。ありがたい。

以下、メモから抜粋。

Javaで実現するフォールトトレランス 〜Resilience4jを使ったサーキットブレーカーの実装〜

#jjug_ccc_b

  • サーキットブレーカーパターン
    • カスケード障害への対策
    • 障害を検知したサービスへのリクエストを遮断する
    • システム全体に障害が波及しないように
  • Resilience4j
    • サーキットブレーカー
    • リトライ
    • 流量制限
  • vavr (依存ライブラリ)
  • サーキットブレーカーOPEN
    • RabbitMQ にメッセージ送信している (リトライあり)
    • あとでバッチ同期
  • 設定値はシステム要求仕様に合わせる
  • タイムアウトの温度感
    • ユーザーから見えるところは短めに
    • バックグランドは長めに/リトライ多めに

カード決済基幹システム レガシーの克服と無停止更改の挑戦

#jjug_ccc_d

  • 必要以上にDBアクセスが多い
  • SELECT FOR UPDATE によるレコードロック待ち
  • SQL実行の長時間化
  • インメモリDBによるスループット向上
    • Hazelcast
    • im-memory data grid
    • クラスタリング
    • ロードバランサがあるわけではない
    • いずれかのノードがプライマリになっているはず
  • 生存期間の短いデータを RDB で扱うのは非効率
  • イベントリスナ
    • 業務処理の一部を Hazelcast に実装
  • カナリアリリース
    • 並行稼動中は新システムは RDB と Hazelcast を見るように
    • 新システムのログはすべて見る
    • 旧システムの性能が劣化していないか
  • SELECT FOR UPDATE
  • Hazelcast + AtomicInteger
    • あまり性能は向上しない
    • AtomicInteger 側のロック待ちになりそう

コンテナ環境でのJava技術の進化

#jjug_ccc_c

  • コンテナ認識
    • Java自身がコンテナで動作していることを認識する必要があるか
    • エルゴノミクス機能
      • ヒープサイズ自動設定
      • ForkJoinPool 並行度
        • 論理CPU数-1
    • cgroup の情報を利用してコンテナを認識している
    • ヒープは物理メモリの 1/4 を割り当てる
    • OverlayFS
  • ネイティブ化
    • Project Leyden #jjug_ccc #jjug_ccc_c
    • ネイティブイメージの標準化
    • GraalVM は OpenJDK プロジェクトではない (標準ではない)
      • (追記) GraalVM CE は OpenJDK に移管される予定
  • CRIU
    • Linux プロジェクト (experimental)
    • プロセスごとにスナップショットが取れる
      • ヒープメモリ分もスナップショットを取る
    • プロセスの状態をディスクに保存
    • データからプロセスをリストア
    • コンテナのライブマイグレーション
      • 入れ替わったコンテナですぐに再開できるようにするため?
  • CRaC
    • CRIU を Java から簡単に利用する
    • 起動性能改善
    • チェックポイント前やリストア後に任意の処理ができるように (JDBC 再接続とか)
      • Resource#beforeCheckpoint
      • Resource#afterRestore
    • 1つのチェックポイントから複数コンテナ起動可

ユーザー数100万人規模の事業成長を止めずにレガシーコードと戦う

#jjug_ccc_c

  • レガシーコード
  • 変更容易性
  • 品質劣化はリードタイムの増加を招く
  • 事業急成長 → 技術的負債を生む意思決定が起こりやすい
  • QCDSのうちコスト/納期/スコープが固定される → 品質低下
  • 密結合/低凝集度 → テストが書きづらい
  • 認知負荷増大
  • データ増によるスロークエリ発生
  • 暗黙知が多い
  • 半年間新規開発ストップ
  • Datadog モニタリング強化
  • スロークエリ改善
  • ログレベル見直し
    • 重要なエラーログを見逃さないように
  • 脆弱性検査
  • 変更容易性とテスト容易性の改善
    • 5つの品質特性は「保守性」に依存している
    • 仕様/設計をシンプルに再構成する (PdMや事業側と調整する)
  • あるべきアーキテクチャ/組織構造への変革
    • 組織は戦略に従う
    • コンウェイの法則
    • コンウェイ戦略
    • 成果をあげる構造を作り出すために目的/戦略から考える
    • 境界づけられたコンテキストでシステムを分離する
      • APIを通してほかチームとコミュニケーションする
      • コミュニケーションパスを設計する
        • 最低限のコミュニケーションになるように
      • ストラングラーパターン
  • 組織変革

5年ぶりのメジャーアップデート! Spring Framework 6 & Spring Boot 3

#jjug_ccc_b

  • Jakarta EE 10
    • javax.*jakarta.*
    • Servlet API に依存するコードやライブラリは要注意
    • EE 9 runtime でも動作可
  • Micrometer 1.10
    • metrics + trace が同時に計測可
    • カーディナリティが高い Tag は trace のみに送られる
  • Java Interface Client
    • interface 定義のみで HTTP Client が使える
    • WebClient ベース (non-blocking)
    • デフォルトは reactor-netty の HttpClient
      • reactor-netty を exclude して標準の HttpClient に差し替え可
    • RFC 7807: Problem Details for HTTP APIs
  • AOT & Native Support
  • proxyBeanMethods = false
  • Mockito は netive 対応していない

組織と技術の両輪で開発を加速させるkintoneチームの取り組み

#jjug_ccc_a

  • LeSS
    • 開発速度低下
    • チーム体制のモノリス
      • コミュニケーションコスト増
      • 認知負荷増
  • チームトポロジー
    • インタラクションモード
  • 領域専任チーム体制
    • フィーチャーチーム
    • 担当領域を明確に → 認知負荷を下げる
    • クロスファンクショナル
    • コンウェイ戦略
    • 機能ごとにパッケージ分割
  • プロジェクト制
    • 探求時間
      • バックログ開発以外の改善活動など
      • 状況に合わせて割合は変える (だいたい2割くらい)
    • 目的/ゴールを説明して承認を得る
      • プロジェクト憲章テンプレート
  • JUnit テストの並列実行
  • IntelliJ IDEA Type migration
  • DateTimeFormatter
    • ResolverStyle.STRICT
    • 存在しない日付を丸めずにエラーにする
  • Google Closure Tools
  • semgrep