owned this note changed a year ago
Linked with GitHub

【第28週】パRails輪読会🚂 (2024-02-26~ 2024-03-01)

tags: パRails🚂

目次


2024-02-26(月)

ファシリ

@sadanora

ドライバー

@sharoa

読んだところ

10-4 「環境によって可変する設定値や秘匿情報の管理」から
10-4-3 「クラウドサービスの活用」まで。
PR:

次回

10-5 「ログ出力」から。🚂

学んだこと・感想

  • @sharoa

    • Dockerって本当に難しい。けど、将来的に必ず出会う子ではあるので、ざっくりでも覚えておけたらな、と思う。
    • 単純な環境変数化には限界がある。ので、クラウドサービスを活用する。
    • このあたりのお話も難しいな〜という感じで、うまく表現できないのですが、とにかく Dockerに触れる機会ができたらパRailsを思い出す!!
  • @ayu-0505

    • 環境変数(起動時に可変してしまう設定値を注入する)を利用して環境ごとの差異をまとめ上げる
    • そのほかの秘匿情報はcredentials.yml.encを利用する。こちらは暗号化されているのでマスターキーを環境変数として実行時に渡せば復号化してくれる。
    • デプロイ先のクラウドサービス(AWS,GCPなど)で権限管理システムが提供されていることが多いので、そちらを利用する。
  • @sadanora

    • Dockerむずかしい(N回目)
    • 環境変数での管理にも限界があって、いい感じに管理するためにはクラウドサービスの仕組みを利用したり工夫が必要
    • 秘匿情報の管理とかは、GitHub ActionsでCI設定するときにやったことと同じような話かもしれないと思いました。
  • @motohiro-mm

    • 環境変数をDockerのコンテナイメージに含めることで、秘匿情報を個々で管理する必要性はなくなる
    • が、その環境変数に指定する値を誰がどこで管理するのかという問題は生じる
    • そのため(権限管理のため)のクラウドサービスがある、そうすると管理しやすくなる
      • KeyManagementService(KMS)
  • @sugiwe

    • VSCode上で⌘ jは、ターミナルを開くショートカット
    • IAMアイアムと読む
    • 権限管理はAWSなどのプラットフォーム側に任せられるサービスがある
    • 今日もフムフム過ぎた(=よくわからなかった…)
    • というか書籍のこれ以降はほぼフムフムな内容なのでは…頭の中にインデックスを作る意識を持って食らいつきたいと思います。
  • @moegi29

    • コンテナは完結したファイルシステムの状態でパッケージングされその状態のまま起動することがメリット。環境変数をつかってコンテナ起動時に可変する設定値を注入することができる
      • docker-compose.ymlを記述することで簡単に読みこむことが出来る
      • dockerを使う場合、-eオプションで環境変数を引き渡す
    • IAM:ユーザー権限管理するサービスのこと。
    • S3:ファイルを保存しておくサービス。
    • KMS:アプリケーションと AWS のサービス全体で暗号キーを作成するサービス

2024-02-27(火)

ファシリ

@shodan

ドライバー

@ayu-0505

読んだところ

10-6 HTTPサーバとの通信 から 10-6-2 コンテナ内部のネットワーク設定 まで

PR:

次回

10-6 457p コラム「真の本番環境へ」から。🚂

学んだこと・感想

  • @sharoa

    • コンテナ上のファイルシステムに新しくデータを保存しないことは、コンテナを利用してWebアプリケーションを運用する際に重要なこと。
    • コンテナ運用の鉄則らしいです。
    • Dockerには、logging driverというログをどこに出力するかをコントロールできる機能が組み込まれている
    • エラーが発生した時に情報を手早く収集するためには、外部の専門サービスを利用するのが良いとのこと。(セルフホストで運用するにはかなりの手間がかかるらしい。)
    • レイテンシ(latency)⇨データ転送における指標のひとつで、転送要求を出してから実際にデータが送られてくるまでに生じる通信の遅延時間のこと
    • docker-composeを利用すれば、簡単に複数のコンテナ間での相互通信環境を構築することができる。
    • 10章もあとコラムのみ!!
  • @sugiwe

    • 色々な読み方を知った
      • fluentd(フルエントディー)
      • syslog(シスログ)
      • occurence(オカレンス)
    • ログ出力はDockerの中に溜まっていくと見に行くのが大変なので、RollbarやSentryといったエラートラッキングのサービスを活用すると良い(Slackに通知とかもしてくれる。想像すると、確かにターミナルに出すとかログファイルを見に行く等よりも圧倒的に便利そう)
    • PumaとUnicornはどちらもアプリケーションサーバ(動物縛りなのだろうか)
    • Railsは直接HTTPを受け取って処理できるのだけど、unicornの特性によりI/O待ちによる無駄な時間が発生してしまうので、それを防ぐために、内部ネットワークで高速通信できて大量のコネクションをバッファして置ける場所としてHTTPサーバが必要になる。
  • @shodan

    • Dockerのコンテナイメージはdisposableであることが大事。
    • ログファイルはデフォルトではDocker内のアプリのディレクトリ内に溜まっていくので、外部に出力させることが大事。
    • Railsのログ出力先はconfig/environments以下の各環境の設定ファイルから変更できる。
    • エラー内容を検知して保持・通知してくれるWebサービスもある。
    • Railsアプリケーションを本番運用する際は、ほとんどのケースでnginxなどのHTTPサーバを前段に置く。
    • pumaやunicornなどのアプリケーションサーバでも外部のクライアントからのHTTP通信を処理できるけれど、それだとレイテンシが起きたりするから。
  • @moegi29

    • Dockerのコンテナ上のファイルシステムには新しくデータを保存しないことが重要でコンテナ運用していくうえでの鉄則。
    • Dockerにはログをどこに出力するかコントロールできるlogging driverという機能がある。
    • コンテナでRailsを運用したい場合はログを標準出力に出すよう設定変更しておく
    • 多くのエラートラッキングサービスはGitHubやSlack等との連携機能があり自動的にIssueを立てたりすぐ通知してくれるのは便利、だけど現場のひとは大変そう。。
  • @sadanora

    • コンテナ上のファイルシステムには新しくデータを保存しないことが鉄則らしい
      • エラーも標準出力に出力するようにしたりする
      • railsのviewファイルとかは普通に追加したり編集したりすると思うけど、そういったものとは別の話?dockerわからないのでいまひとつピンときてない。
  • @ayu-0505

    • コンテナはイメージをもとに起動したら常に同様な環境で起動できることが利点。(使い捨てできること)
    • そのため、新しいデータの保存はコンテナ外であることが望ましい(ActiveStrageの画像等は外部ストレージを使う)
    • Dockerにはログ出力先をコントロールする機能がある。
    • Railsのログ出力のデフォルトはプロジェクトルートのlogディレクトリなので、標準出力に変更しておく
    • エラー検知システムをセルフホストで運用するのは大変なので、外部サービスを利用するとよい。(例:Rollbar)
    • アプリケーションサーバの負担を減らすために、HTTPサーバを利用するが、Dockerではコンテナ間の相互通信環境を構築することができる。

2024-02-28(水)

ファシリ

@moegi29

ドライバー

@ayu-0505

読んだところ

10-6 457p コラム「真の本番環境へ」から
11-2-1 「エンティティと値オブジェクト」まで。
PR:

次回

11-2-2 「いつ導入すべきか」から。🚂

学んだこと・感想

  • @sharoa

    • プロフェッショナルな現場でのコンテナ活用は当たり前ですけど、とっても難しそう。コラムのことは覚えておこうという感じです。
    • Skinny Controller, Fat Model(コントローラは薄く、モデルを厚く)」というRailsアプリケーションを開発するときに基本となる考え方がある。
    • アプリケーションの核となるロジックはモデルに実装すべきという設計原則のこと。(コントローラやビューではない。)
    • ドメインモデルとアクティブレコードの項というか11−1の節は全てにおいて大事そうな内容で、そして難しいな、と思いました。
    • エンティティや値オブジェクトは今後の実装例などを読み進めていって理解ができたらいいな、と思っています。
  • @sugiwe

    • Railsの基本の考え方の1つ「Skinny Controller, Fat Model」は重要。
    • アプリが対象とする問題領域のことをドメインと呼ぶ。「エンジニアもドメイン知識を学ぶべきである」みたいな言説を見かけるけど、このドメインの意味であろうと思った。
    • ドメインを分析して構成概念を抽出することをモデリングと呼び、その結果得られた概念のことをドメインモデルと呼ぶ。
    • ドメインモデルに関連する属性と振る舞いを持ったオブジェクトとして定義される。その振る舞いのことをドメインロジック(ビジネスロジック)と呼ぶ。
    • Railsのモデルは、ドメインモデルとドメインロジックを実装するレイヤーである。
    • ドメインモデル単体ではアプリケーションにならない。別でデータベースがあり、データベースとデータのやり取りをすることで初めてアプリケーションになる。その、ドメインモデルからデータベースを操作するための仕組みがActiveRecord、ということになる、か?Railsアプリの全体感がふわ〜っと掴めたような掴めていないような…という気持ちになりました。
    • RailsのActiveRecordとは別の広い概念としてアクティブレコードがある。
    • 一意に識別されるオブジェクトのことをエンティティと呼ぶ。日本人を例にすると、マイナンバーという識別子を持つ日本人というエンティティ、ってこと?
  • @moegi29

    • コラムでプロの現場でコンテナ活用するにはどんなものが活用されているのか紹介されていてKubertnetesとかcapistrano等知らないツールが知れた
    • 今日でてきたアクティブレコードはRailsのActiveRecordとは違う話だった。11章に入りDockerとは別の方向に難しい。まだ消化しきれてないので後程読み直しておきます
  • @motohiro-mm

    • 明日は最初から参加できそうなので、ついていけるように今日のところまで読んでおきます…!
  • @sadanora

    • RailsのActiveRecordのアーキテクチャパターンはアクティブレコードパターン
      • テーブルの1行と1つのインスタンスが対応し、ドメインロジックを記述するクラスを作成するパターン
      • アーキテクチャパターンという言葉を初めて聞いた。デザインパターンと何が違うのか気になる。
    • エンティティ
      • 識別子をもっている。一意に識別できる。
    • 値オブジェクト
      • 所持するインスタンスが異なっても同じ値として扱ってもいいもの?
        • 生年月日とか。同じ生年月日のユーザーが二人いたとしても、日付としての値は同じもの。
  • ayu-0505

    • コンテナオーケストレーションツール =コンテナ管理ツール
    • ドメインモデル(アプリケーションが対象とする問題領域をモデル化したもの)
    • ドメインロジックはようするにモデルにおけるメソッド(モデルのふるまいかな?)
    • アクティブレコードはアーキテクチャパターンの一種(なのでRailsもモデルとクラスを関連づけるものをActiveRecordと呼ぶ)
    • 単一テーブル継承、要復習。
    • 識別子によって一意に判断できるオブジェクトをエンティティ、内容が同じであれば同一とみなすオブジェクトを値オブジェクトと呼ぶ

2024-02-29(木)

ファシリ

@motohiro

ドライバー

読んだところ

11-2-2 「いつ導入すべきか」から
11-2-3 「実装例」まで。
PR:

次回

11-3 「サービスオブジェクト」から。🚂

学んだこと・感想

  • @sharoa

    • Railsには複数のモデルから扱われる特定の意味を持った値を実装するレイヤーが用意されていない。本の中の例でいうと、解決方法としては値オブジェクトを導入すると良いとのこと。
    • 値オブジェクトには実装上の利点やモデリングの上での利点がある。
    • 質の高いアプリケーションを開発するには、ドメインモデルを正確に抽出することはもちろん、抽出したドメインモデルを実装に反映させることも同じくらい重要とのこと。
    • 値オブジェクトを導入することで、ドメインモデルをより正確に実装に反映できる。
    • composed_ofは、モデルの属性を値オブジェクトとして表現するための仕組みのこと。
    • classify⇨与えられたテーブル名に対応するクラス名を返す
    • 今日も難しい。
  • @moegi29

    • 値オブジェクトの実装例で出てきたDelegateはあるオブジェクト(一般的にはモデルオブジェクト)から別のオブジェクトへのメソッド呼び出しを委譲するために使用されるもの。
    • テーブル名をクラス名にするclassifyするという
    • DBに紐づくモデルと紐づかないモデルがある。app/models/以下に何も継承しないクラスを作って良い
    • 今日も断片的にわかったようなわかってないような理解レベルなので読み直しておきます
  • @sadanora

    • 昨日参加したイベントで技術的負債の返済の中でドメインモデルを見直したという話がありました
    • 途中からでしたが、オブジェクト指向っぽい話で面白かったです
    • オブジェクト指向よくわからないので勉強したいと思いました
      • 継承、委譲、合成とか理解したい
    • 眼科でものもらい(霰粒腫)をとってきてすっきりしました。
  • @shodan

    • DBと紐づかないクラスはbootcampにもあるはありますね。
    • compose_ofという仕組みは、アクティブレコードに基づいたモデルのカラムと、アクティブレコードに基づかない値オブジェクトを紐づけることができる。
    • Fatなコントローラ・モデルをなんとかしろ!と言われた時に、思い出せるようにしたい。
  • ayu-0505

    • 値オブジェクト利用は、複数のモデルで再利用されやすいロジックをまとめるための一手法
    • 正確なドメインモデルを正確に実装に反映させる
    • アクティブレコードによるRDBへの紐付きがないクラス(テーブルを持たないクラス)による利点がある
    • composed_ofを使用すると、より少ない記述で値オブジェクトを活用できる。
    • self[:column]で値を取得できる(NULL時に例外エラーを起こさずにNULLを取得できる)
  • @motohiro-mm

    • 複数のモデルで共通のロジック(メソッドとか)をもたせたいときに、値オブジェクトを使う
      • クラスとして作成してdelegateをつかう(詳細は分かってない…)
      • 持たせたいクラスにはcomposed_ofで値オブジェクトのアクセサメソッドが簡単に定義できる
    • 値オブジェクト以外の方法は、前回でてきた単一テーブル継承
  • @sugiwe

    • .phone_number[:phone_number]の違い(該当するものがないとき、前者はno methodエラーになり、後者はnilが返る?)
    • composed_of、何が何やらさっぱりだったけどayuさんがおっしゃっていたattr_readerとの比較でちょっとだけイメージが湧いたような気がします
    • 例えばUserモデル内にphone_numberがあり、Companyモデル内に同じくphone_numberがあって、それぞれに同じロジック(mobile?など)を作るのはDRYじゃないので、それをうまく整理するための仕組みの紹介、というのが今日学んだこと…?
      • 詳細はさっぱりわからなかったのですが概念的にはなるほど〜と思いました。

2024-03-01(金)

ファシリ

@ayu-0505

ドライバー

読んだところ

11-3 「サービスオブジェクト」から
11-3-4 「導入時のポイント」まで
PR:

次回

学んだこと・感想

  • @sharoa

    • サービスオブジェクトとは、モデルに実装すると不自然なドメインロジックが出てくることがあり、こういったロジックを独立したオブジェクトとして定義したもののことを言う。
    • サービスオブジェクトはモデルとは異なるので、自身の動作を変更するような状態を持たない。(注意ポイントらしい)
    • サービスオブジェクトを導入することに当たって特に注意すべきポイントとして、
       - モデルに実装すべきロジックまで実装しない
       - イベントの見落としがないかを確認する
    • がある。
    • 472pの最後の文章の塊がすごく大事な気がするので覚えておきたい。
  • @sadanora

    • 複数のモデルのオブジェクトを組み合わせて表現するようなロジックなどはモデルに実装すると不自然
      • そのようなロジックを独立したオブジェクトとして定義したものをサービスオブジェクトという
      • ロジックではなくイベントとして扱うことが自然なら、サービスオブジェクトではなくイベントを表現するモデルとした方がいいケースもあり、一長一短がある
  • @shodan

    • Railsアプリが複雑になってくると、複数のモデル・オブジェクトが絡むドメインロジックをどのモデルのインスタンスメソッドに書くか、という問題が出てくるらしい。
    • それに対するアプローチの一つが、「サービスオブジェクト」の導入。
    • その複雑なロジックそのものを独立したクラス(とそのオブジェクト)として定義すること。
      • 本の例で言えば「複数のBankAccountオブジェクトが絡んだ、銀行口座の送金サービス」。複雑。
    • そのロジックが何かを「記録」するものであれば、DBと紐づくモデルのロジックとして定義した方がいいかも。
      • その方がRailsのレールに乗れるから。
    • 難しいですね……。
  • @motohiro-mm

    • サービスオブジェクト:ドメインロジックを定義する、Databaseに保存する必要のないロジックをいれる
      • モデルとは異なり、自身の動作を変更するような状態をもたない、引数が同じなら同じ結果を得られる
      • モデルに実装すべきロジック、と、サービスオブジェクトに定義してよいロジック、の違いがよく分かっていない…
    • Databaseに残した方が良いイベントがあるときはモデルとして実装する
      • そのほうがコントローラもscaffoldで作ったものをそのまま使える
      • ただしテストがしづらい
    • モデルに実装すると不自然なドメインロジック、というのがたぶんピンときていない…(たぶん上記と同じことが分かっていない)
  • @sakanobu

    • 実装レベルでも難しいのにサービスオブジェクトなど概念レベルでも難しいので理解度がかなりフワフワしている
    • 11-1-2であった「データベースのテーブルをクラス、レコードをクラスのインスタンス、カラムをインスタンスの属性に対応させる」というのを忘れず、複数のオブジェクトを扱うロジックなのにモデルのインスタンスメソッドとして実装しようとしたら「これはマズい!」と気付けるようにしたい!
      • どうすれば実現できるかで手一杯なのに、どこにロジックを実装すべきかも考えるのは本当に難しいなと感じています
      • 「データベースのテーブルをクラス」として表すよくあるケースは User.all のような SQL で検索を書けるようなクラスメソッドのことを指すのかなと思いました
    • 都道府県ごとの手数料の違いというケースだと BankAccount モデル、Money モデル、BankAccountMoneyTransfer モデル、更には別のクラスを新設すべきか…などどこに実装すべきか、メッチャ悩みどころでスゴい良い疑問だと思いました!
      • 北海道、本州、沖縄などで大まかに分けるとしても更に別の複数のクラスが必要なので複雑な設計になりそう…
    • 人や物をテーブルとして表すのは直感的なので気付きそうですが、送金という実態のないものをテーブルとして表すことを見落とさないかは少し不安になりました
      • 「送金する」のような動詞を「送金」という動名詞として捉えるみたいな発想もテーブルやクラスの発見に必要なのかなと思いました
  • @ayu-0505

    • サービスオブジェクトとは、モデルに実装すると不自然なドメインロジックを抽出してオブジェクト化したもの(複数のオブジェクト操作を必要とするなど)
    • モデルに実装すべきロジックまでサービスにしてしまわないように注意!
    • イベント(DBなどに記録が必要なものなど)の見落としがないか注意!
    • イベントをDBに紐づくクラスとして作る方法もある(イベントクラス)。それならばRailsの規約に沿うことが可能。
    • イベントクラスにするか、サービスクラスにするかは一長一短あるので、適宜使い分ける。

Select a repo