Slide 1

Slide 1 text

入門『状態』 Kaigi on Rails 2024 2024/10/26 しんくう@shinkufencer

Slide 2

Slide 2 text

はじめに:今回取り上げる『状態』について 2 ● 『状態』とは聞いたりするけど、人によっては身近に感じることは 無いかもしれません。 ● また、『状態』が多いとつらい、という話を聞いたりもしますが ピンとこないこともあるかと思います。 ● そこで今回はオブジェクトにまつわる『状態』を起点にして 身近にある『状態』について知ってもらい 普段のRails開発にも利用できる話をできればと思います。 ● ターゲットは初学者の方を想定しています。 プログラミングでの『状態』に触れる足がかりになれば幸いです。

Slide 3

Slide 3 text

今回しゃべること 3 ● オブジェクトと『状態』について ● 『状態』を扱う上でつらくなるポイントと対策 ● Ruby on Railsで遭遇する身近な状態の付き合い方

Slide 4

Slide 4 text

オブジェクトと『状態』 4

Slide 5

Slide 5 text

オブジェクトが持つ『状態』 ● オブジェクトにおける『状態』とはどのように表現されるでしょうか? ● 「明かりが点いている、点いていない」が表現できる電球のクラスを例に オブジェクトの『状態』を考えていきます。 5

Slide 6

Slide 6 text

電球を表現した LightBulb クラス 6 class LightBulb attr_accessor :is_on def initialize @is_on = false end end インスタンス変数 @is_on で 電球が点いているか、いないかを表現

Slide 7

Slide 7 text

オブジェクトが持つ『状態』 ● LightBulbは「電球が点いているか」を@is_onというインスタンス変数で 保持することで表現しています。 ● オブジェクトの『状態』はこのように内部が持つインスタンス変数で表現 できます。 ● 『状態』はインスタンス変数の追加でバリエーションを増やせます。 ● 例えば明るさの%を表すための変数を追加してみます。 7 bulb = LightBulb.new # 『電源が付いた状態』に変更する bulb.is_on = true # 『電源が消えた状態に変更する bulb.is_on = false

Slide 8

Slide 8 text

明るさを追加した LightBulb クラス 8 class LightBulb attr_accessor :is_on, :brightness def initialize @is_on = false @brightness = 0 end end 明るさを表す要素として @brightnessを新規で追加 0〜100を入れてもらう想定

Slide 9

Slide 9 text

オブジェクトが持つ『状態』 ● オブジェクトに明るさを表現する@brightnessが増えたことで 明度も『状態』として表現できるようになりました。 ● このようにオブジェクトは複数のインスタンス変数の組み合わせて 『状態』の表現を増やすことができます。 9 bulb = LightBulb.new # 電源を入れて明度を50の状態にする bulb.is_on = true bulb.brightness = 50

Slide 10

Slide 10 text

『状態』がどのようにつらさを招くのか ● 『状態』に関してオブジェクトを題材に紹介しました。 ● では、このような『状態』はどうするとつらくなっていくのでしょうか? 10

Slide 11

Slide 11 text

『状態』を 扱う上でつらくなるポイント 11

Slide 12

Slide 12 text

『状態』はどのようなときにつらくなるのか? ● 『状態』は表現される幅が増えるとつらさが露見してきます。 ● どういう部分がつらいのかを先程のLightBulbを題材に交えたコードで 説明していきたいと思います。 12

Slide 13

Slide 13 text

『状態』にまつわる話がつらくなっているコード 13 # インスタンス変数 @bulb と @bulb_message を初期化するメソッド # @param [Integer] default_brightness 初期設定したい明るさの値 (%)、0から100を想定 def setup(default_brightness:) @bulb = LightBulb.new if @bulb.nil? @bulb_message = "明るさ:電球の明度は普通です。 " @bulb.is_on = true @bulb.brightness = 50 if default_brightness > 0 @bulb.is_on = true @bulb.brightness = default_brightness if @bulb.brightness >= 70 @bulb_message = "明るさ:電球の明度が高いです。 " elsif @bulb.brightness <= 30 @bulb_message = "明るさ:電球の明度が低いです。 " end elsif default_brightness == 0 @bulb.is_on = false @bulb.brightness = 0 @bulb_message = "明るさ:電球はOFFです。" end end ▼初期セットアップの仕様 ・LightBulbとメッセージをインスタンス変数  としてセットアップしていく ・LightBulbの明るさの初期値として設定できる ・初期値が0の場合は電球はOFFの状態とする。 ・初期値とともに明るさのメッセージもつくる  明るさのメッセージは以下の通り  ・明るさが70以上だと明度が高いメッセージ  ・明るさが30以下だと明度が暗いメッセージ  ・それ以外の場合は明度が普通であるメッセージ  ・電球がOFFの場合はOFFであるメッセージ

Slide 14

Slide 14 text

つらいポイント① 変化を繰り返すと追いづらくなる ● 前述のとおりオブジェクトの『状態』はオブジェクト内の変数の値のかけ 合わせで決まりますが、その変数の値を変更することが多いと 最終的な『状態』が追いかけづらくなります。 ● その点に焦点を当てて、setupのコードを読んでいきます。 14

Slide 15

Slide 15 text

@bulbのインスタンス変数を何度も書き換えている 15 def setup(default_brightness:) @bulb = LightBulb.new if @bulb.nil? @bulb_message = "明るさ:電球の明度は普通です。 " @bulb.is_on = true @bulb.brightness = 50 if default_brightness > 0 @bulb.is_on = true @bulb.brightness = default_brightness if @bulb.brightness >= 70 @bulb_message = "明るさ:電球の明度が高いです。 " elsif @bulb.brightness <= 30 @bulb_message = "明るさ:電球の明度が低いです。 " end elsif default_brightness == 0 @bulb.is_on = false @bulb.brightness = 0 @bulb_message = "明るさ:電球はOFFです。" end end @bulbのオブジェクトが持つ インスタンス変数を 処理の途中で適宜再代入しているので 一見して is_on と brightness がわからず 状態が把握しづらい

Slide 16

Slide 16 text

@bulb_messageも都度再代入をしている 16 def setup(default_brightness:) @bulb = LightBulb.new if @bulb.nil? @bulb_message = "明るさ:電球の明度は普通です。 " @bulb.is_on = true @bulb.brightness = 50 if default_brightness > 0 @bulb.is_on = true @bulb.brightness = default_brightness if @bulb.brightness >= 70 @bulb_message = "明るさ:電球の明度が高いです。 " elsif @bulb.brightness <= 30 @bulb_message = "明るさ:電球の明度が低いです。 " end elsif default_brightness == 0 @bulb.is_on = false @bulb.brightness = 0 @bulb_message = "明るさ:電球はOFFです。" end end @bulb_messageに関しても 再代入をする箇所が多いので 最終的な値がわかりにくい

Slide 17

Slide 17 text

つらいポイント② 変化の幅が大きいと考慮点が増える ● 『状態』が変化できる幅が大きいと考慮点が増えます。 ● 変化の幅というのは、変化のさせやすさと変化するバリエーションのこと を指しています。 ● その点に焦点を当てて、setupのコードを読んでいきます。 17

Slide 18

Slide 18 text

attr_accessorなので入ってくる値もタイミングも自由 18 class LightBulb attr_accessor :is_on, :brightness def initialize @is_on = false @brightness = 0 end end 仕様としては0〜100と定めているが 特段制限は設けられていない

Slide 19

Slide 19 text

0〜100以外の値が入ることが考慮されていない 19 def setup(default_brightness:) @bulb = LightBulb.new if @bulb.nil? @bulb_message = "明るさ:電球の明度は普通です。 " @bulb.is_on = true @bulb.brightness = 50 if default_brightness > 0 @bulb.is_on = true @bulb.brightness = default_brightness if @bulb.brightness >= 70 @bulb_message = "明るさ:電球の明度が高いです。 " elsif @bulb.brightness <= 30 @bulb_message = "明るさ:電球の明度が低いです。 " end elsif default_brightness == 0 @bulb.is_on = false @bulb.brightness = 0 @bulb_message = "明るさ:電球はOFFです。" end end @bulb.brightnessは状態として 0〜100以外の値も取りうるので その点を考慮する必要がある

Slide 20

Slide 20 text

つらいポイント まとめ ● 『状態』の変化が多いと、最終的な状態を把握するのに労力がかかったり 一見して判断ができなくなってしまう。 ● 『状態』を決定づける要素がバリエーション豊かになると、オブジェクト を利用する側は、取りうるバリエーションを想像しながら対処を検討する 必要がでてきてしまう。 ● このつらい部分をどのようにすると抑えることができるでしょうか? 20

Slide 21

Slide 21 text

『状態』の つらさをおさえていくためには 21

Slide 22

Slide 22 text

『状態』のつらさをどうやって抑制するのか 今回紹介する抑制させるための観点は以下の3つです。 これら3つの観点をもとに、先程のsetupとLightBulbを見直していきます。 22 1. 『状態』を可能な限り変化させない 2. 『状態』の変化幅を限定的にする 3. 『状態』をなるべくシンプルに少なく保つ

Slide 23

Slide 23 text

つらさ抑制①『状態』の変化を可能な限りさせない ● 『状態』は変化を繰り返すことで分かりづらくなります。 ● そのため、可能な限り変化を減らすことがわかりやすく保つための近道に なります。 ● そのときに着目するとよいのはオブジェクトの状態を司るインスタンス変 数や、オブジェクトそのものをしまっている変数などです。 ● このときに「再代入」が変化を促進させているので、再代入をさせない方 法を考えてみます。 23

Slide 24

Slide 24 text

つらさ抑制①『状態』の変化を可能な限りさせない ● 変数に着目したときに再代入が多いと最終的な値がわかりづらいです。 そのため、再代入をさせないようにすると変化が追いやすくなります。 下記の例はmessageの再代入をなくしてみる例です。 ● @bulbにも類似のアプローチを適用することで変化を減らせます。 24 def create_message(sei, mei) message = "呼び出し:" if !sei.nil? && mei.nil? message += sei else message += "#{sei}#{mei}" end message += "さん" if sei.nil? && mei.nil? message = "お名前不明の呼び出し " end return message end def create_message(sei, mei) is_only_sei = !sei.nil? && mei.nil? is_no_seimei = sei.nil? && mei.nil? name = is_only_sei ? sei : "#{sei}#{mei}" no_name_mesage = "お名前不明の呼び出し" name_message = "呼び出し:#{name}さん" message = is_no_seimei ? no_name_mesage : name_message return message end

Slide 25

Slide 25 text

Before: @bulbが持つインスタンス変数を何度も再代入している 25 def setup(default_brightness:) @bulb = LightBulb.new if @bulb.nil? @bulb_message = "明るさ:電球の明度は普通です。 " @bulb.is_on = true @bulb.brightness = 50 if default_brightness > 0 @bulb.is_on = true @bulb.brightness = default_brightness if @bulb.brightness >= 70 @bulb_message = "明るさ:電球の明度が高いです。 " elsif @bulb.brightness <= 30 @bulb_message = "明るさ:電球の明度が低いです。 " end elsif default_brightness == 0 @bulb.is_on = false @bulb.brightness = 0 @bulb_message = "明るさ:電球はOFFです。" end end

Slide 26

Slide 26 text

After: 書き換えるのを1回だけに 26 def setup(default_brightness:) @bulb = LightBulb.new if @bulb.nil? @bulb_message = "明るさ:電球の明度は普通です。 " light_on = default_brightness > 0 ? true : false @bulb.is_on = light_on @bulb.brightness = light_on ? default_brightness : 0 if default_brightness > 0 if @bulb.brightness >= 70 && @bulb.brightness <= 100 @bulb_message = "明るさ:電球の明度が高いです。 " elsif @bulb.brightness <= 30 && @bulb.brightness > 0 @bulb_message = "明るさ:電球の明度が低いです。 " end elsif default_brightness <= 0 @bulb_message = "明るさ:電球はOFFです。" end end If文の中に混じっていた変更を 一箇所に集約することで 変化させる部分を最低限にできた

Slide 27

Slide 27 text

After: 書き換えるのを1回だけに 27 def setup(default_brightness:) @bulb = LightBulb.new if @bulb.nil? light_on = default_brightness > 0 ? true : false @bulb.is_on = light_on @bulb.brightness = light_on ? default_brightness : 0 @bulb_message = if @bulb.brightness >= 70 && @bulb.brightness <= 100 "明るさ:電球の明度が高いです。 " elsif @bulb.brightness <= 30 && @bulb.brightness > 0 "明るさ:電球の明度が低いです。 " elsif @bulb.brightness <= 0 "明るさ:電球はOFFです。" else "明るさ:電球の明度は普通です。 " end end @bulb_messageも 1回の代入で済むような 書き方に変更をする

Slide 28

Slide 28 text

つらさ抑制②『状態』の変化幅を限定的にする ● LightBulbの場合は、@brightnessがattr_accessorになっており、どこか らでも変更でき、入ってくる値の制御ができないため、無限の可能性を考 慮する必要がありました。 ● そのため、@brightnessの値を変更するメソッドを用意してあげて 想定にない値がセットされないように抑制できるようにします。 そうすると考慮しなければいけない範囲を限定的にできます。 28

Slide 29

Slide 29 text

Before: どこからでもどのようにでも値が変更可能 29 class LightBulb attr_accessor :is_on, :brightness def initialize @is_on = false @brightness = 0 end end attr_accessorなので どこからどのようにでも値が変更可能で 設定する側も参照する側も入る値の予測がしづらい

Slide 30

Slide 30 text

# 電球をオンにする # @param [Integer] brightness オン時の明るさ def turn_on(brightness: 50) @is_on = true tune_brightness(brightness) end # 電球をオフにする def turn_off @is_on = false @brightness = 0 end def tune_brightness(level) is_over_range = level > 100 || level < 0 set_value = is_over_range ? 0 : level # 範囲外は0 @brightness = set_value end end After: 値を変更するルートと幅を限定的にした 30 class LightBulb attr_reader :is_on, :brightness # 初期状態では電球はオフで、明るさは0 def initialize @is_on = false @brightness = 0 end attr_readerにして 直接変更は不可に オブジェクト外から変更する場合は メソッド経由にし、変更方法を制限する また、意図から外れる数値の対応策もして 変更できる範囲に制約をかけれるようにする

Slide 31

Slide 31 text

つらさ抑制③ 『状態』をシンプルに少なく保つ ● LightBulbが持つ『状態』は電源ON/OFFと明るさ0〜100%をかけ合わせ 202パターン表現することが可能になっています。 ● しかし、現時点の使い方を鑑みると『状態』のパターン表現は 以下の4つだけでも充分そうです。 ○ 「電源が点いていない」 ○ 「電源が点いていて、明度が高い」 ○ 「電源が点いていて、明度が低い」 ○ 「電源が点いていて、明度が普通」 ● そのため、直接的に値を見て『状態』を判断する形式をやめて LightBulbに上記 4つのパターンが判断できるメソッドを加えてみます。 31

Slide 32

Slide 32 text

# 明度が高いかを判定 def high_brightness? @is_on && @brightness >= 70 && @brightness <= 100 end # 明度が低いかを判定 def low_brightness? @is_on && @brightness > 0 && @brightness <= 30 end # 明度が普通かを判定 def normal_brightness? @is_on && @brightness > 30 && @brightness < 70 end # 電球がオフかを判定 def off? !@is_on end end After:『状態』の読み取らせかたを変えたLightBulb 32 class LightBulb def initialize @is_on = false @brightness = 0 end def turn_on(brightness: 50) @is_on = true tune_brightness(brightness) end def turn_off @is_on = false @brightness = 0 end def tune_brightness(level) is_over_range = level > 100 || level < 0 set_value = is_over_range ? 0 : level @brightness = set_value end attr_readerで変数を見て『状態』を読み取らせるのをやめ 『状態』を読み取るためのメソッドを用意する

Slide 33

Slide 33 text

つらさ抑制③ 『状態』をシンプルに少なく保つ ● こうすることにより、is_onとbrightnessのかけ合わせで表現できる 無数のパターンから色々と検討させるのではなく 用意したメソッドから4つのパターンだけ考えれば良いようになります。 ● 『状態』を決定づける源泉はインスタンス変数ではありますが ままその値を使う以外の形で表現することができました。 ● setupもこの定義を行ったメソッドを利用するように変更してみます。 33

Slide 34

Slide 34 text

# 明るさの状態に応じてメッセージを生成 # @param [LightBulb] bulb メッセージを作る基準となる電球 def build_bulb_message(bulb) header_message = "明るさ:" return "#{header_message}電球の明度が高いです。" if bulb.high_brightness? return "#{header_message}電球の明度が低いです。" if bulb.low_brightness? return "#{header_message}電球の明度は普通です。" if bulb.normal_brightness? return "#{header_message}電球はOFFです。" if bulb.off? "" # この状態は存在し得ないが明示的に空文字を返却する end After: 変更したLightBulbを利用したsetup処理 34 def setup(default_brightness:) @bulb = LightBulb.new if @bulb.nil? if default_brightness > 0 @bulb.turn_on(brightness:default_brightness) else @bulb.turn_off end @bulb_message = build_bulb_message(@bulb) end 状態を示す書き方がシンプルになり 直感的にも処理的にも 見通しが良くなった

Slide 35

Slide 35 text

つらさ抑制 まとめ ● 『状態』は役目を終えるまで変化をなるべくさせないようにし バリエーションに関しても数が多くならないようにシンプルに保つことで つらい部分を抑制することができるようになりました。 ● ではこの考え方をRailsを書く時にどう取り入れるといいのでしょうか? 35

Slide 36

Slide 36 text

Ruby on Railsでの つらい『状態』のいなし方 36

Slide 37

Slide 37 text

Rails実装でのつらい『状態』のいなし方 ● これまでのオブジェクトを題材にしながら『状態』のつらくならないため の向き合い方を見てきました。 ● 普段書くRailsのコードを題材にし、普段遭遇しそうな 『状態』がつらくなっている事例とそのいなし方を考えていきます。 37

Slide 38

Slide 38 text

今回の事例コードで取り扱うものについて ● 今回はActiveRecordとしてEventモデルがあり、その内容を表示するよう なものを考えていきます。 38 categoryは数値で意味づけをしている 0がノーマルイベント 1がスペシャルイベント

Slide 39

Slide 39 text

事例①Controllerでのインスタンス変数再代入 ● EventControllerにindexアクションを定義する際に Viewに渡すためのインスタンス変数を定義すると思います。 ● そのようなときに次のようなコードに遭遇することがあります。 39

Slide 40

Slide 40 text

EventsControllerのindexアクション 40 class EventsController < ApplicationController def index @list = Event.where(is_public: true) # クエリストリングでonly_special=1が指定されている場合は更に絞り込む if params[:only_special] == 1 @list = Event.where(is_public: true, category: 1) end # クエリストリングでforce_nothing_result=1の場合は何も表示しない if params[:force_nothing_result] == 1 @list = [] end end end @listに再代入を繰り返している。 そのため最終的にどんな状態になるか 上から下まで読まないと把握ができない

Slide 41

Slide 41 text

事例①Controllerでのインスタンス変数再代入 ● Viewに渡して一覧表示するためにインスタンス変数を用意しますが URLのパラメータに応じて表示するものを絞り込んだり変更する場合が あると思います。 ● そのときに再代入を繰り返して状態を変化させるのではなく 1回の代入で済むようにしてあげるとインスタンス変数の変化を 上から下まで追わなくて済みます。 41

Slide 42

Slide 42 text

After: @listの再代入をなくしたindexアクション 42 class EventsController < ApplicationController def index is_special = params[:only_special] == 1 is_force_nothing = params[:force_nothing_result] == 1 @list = making_list(is_special, is_force_nothing) end def making_list(is_only_special, is_force_nothing) return [] if is_force_nothing return Event.where(is_public: true, category: 1) if is_only_special Event.where(is_public: true) end end @listが代入されるのは1回のみに @listの内容を決定するための情報を引数とした 中身の作成を担うメソッドを用意

Slide 43

Slide 43 text

事例②View内でのインスタンス変数を利用した分岐 ● Viewで条件分岐をする際にいろいろなことを考慮すると分岐が増えがち になります。 ● さきほどの延長線上で@listをViewで表示するときに次に紹介するような 記述になることがあります。 43

Slide 44

Slide 44 text

EventのindexアクションのView 44 <% @list.each do |event| %> <% ## 中略 ## %> <% if event.open_at > Time.zone.now %> 開催期間前です。 <% elsif event.close_at < Time.zone.now %> 開催が完了しました。 <% else %> <% if event.open_at <= Time.zone.now && event.end_at >= Time.zone.now && event.type == 1 %> 開催期間中のスペシャルイベントです。 <% elsif event.open_at <= Time.zone.now && event.end_at >= Time.zone.now && event.type == 0 %> 開催期間中の通常イベントです。 <% else %> 開催中のイベントです。 <% end %> <% end %> <% end %> 長い判定式がいくつもあるので 一見してどういうことをしているかがわかりにくい

Slide 45

Slide 45 text

事例②View内でのインスタンス変数を利用した分岐 ● Viewの判定文が入り組んでしまっているのでやっていることを読み解く ことが難しくなっていました。 ● よくよく読むと「開催中」「開催前」「開催後」などの『状態』が 暗黙的に存在するがそれがコード上で表現されていないので 具体的な値を見ることで『状態』の判断をしている。 ● そのため、それらの『状態』を定義してあげることで整理しやすくなる。 ● 今回はModelに『状態』のためのメソッドを追加してみます。 45

Slide 46

Slide 46 text

After: Modelで『状態』をわかるようにし、Viewもテコ入れ 46 class Event < ApplicationRecord def before_open? open_at > Time.zone.now end def finished? end_at < Time.zone.now end def in_progress? now = Time.zone.now open_at <= now && end_at >= now end def normal? category == 0 end def special? category == 1 end end 判定文であった内容を Modelのメソッド化して 明確に状態として定義する <% @list.each do |event| %> <% ## 中略 ## %> <% if event.before_open? %> 開催期間前です。 <% elsif event.finished? %> 開催が完了しました。 <% else %> <% if event.in_progress? && event.special? %> 開催期間中のスペシャルイベントです。 <% elsif event.in_progress? && event.normal? %> 開催期間中の通常イベントです。 <% else %> 開催中のイベントです。 <% end %> <% end %> <% end %>

Slide 47

Slide 47 text

事例②View内でのインスタンス変数を利用した分岐 ● ただの判定式だった内容が『状態』として定義されることで読みやすさが 明快になりました。 ● 定義がされることによってわかりやすさや抜けや漏れが無いかに気づきや すくなります。 47

Slide 48

Slide 48 text

事例③用途が迷子になったControllerインスタンス変数 ● ControllerはViewに値を受け渡しする兼ね合い上、いろいろなものがイ ンスタンス変数として使われます。 ● しかしインスタンス変数はController内のどこでも操作可能になるので、 メソッドが呼びされたタイミングでどうあるべきか また中身がどうなっているかを判断する必要が出てきます。 ● そのため、必要以上にインスタンス変数を増やさないようにすることがシ ンプルさを保つ近道にになります。 48

Slide 49

Slide 49 text

事例③用途が迷子になったControllerインスタンス変数 ● 例えば右記のような ControllerとViewがある場合 ● 一見すると問題ないように 見えますが、Viewでは @userは利用していませんし @postsもカウント数を 利用しているだけです。 ● 改修を加えていくと何のための インスタンス変数かが把握できず 考慮すべきかわからなくなります 49 class UsersController < ApplicationController def show @user = User.find(params[:id]) @posts = @user.posts end def edit @user = User.find(params[:id]) end end この人の投稿数は<%= @posts.size %>です。 app/controllers/users_controller.rb app/views/users/show.html.erb

Slide 50

Slide 50 text

事例③用途が迷子になったControllerインスタンス変数 ● 本当に必要なのはcountだけなので インスタンス変数もcountを 表現するためのだけのものに 変更しました。 ● 必要なものだけに絞られたので Controllerとして持っている 『状態』がシンプルになりました 50 class UsersController < ApplicationController def show user = User.find(params[:id]) @post_count = user.posts.count end def edit @user = User.find(params[:id]) end end この人の投稿数は<%= @post_count %>です。 app/controllers/users_controller.rb app/views/users/show.html.erb

Slide 51

Slide 51 text

事例③用途が迷子になったControllerインスタンス変数 ● 例で出したパターンはとても簡素な例ですが、成長したアプリケーション だと不要になったインスタンス変数が残ってしまっていたりなど 『状態』を読み取る難易度を上げていることがあります。 ● インスタンス変数が増えれば、それらがどうなっているかを含め 『状態』を気に掛ける必要が出てくるため、多くしないことが肝心です。 51

Slide 52

Slide 52 text

まとめ 52 ● 『状態』は身近なところにもある ● 『状態』は何回も変化したり、パターンが増えると辛くなる ● 『状態』はなるべく変えず、シンプルに保つとよい ● Railsのアプリケーションを書くときにも頭にとどめておくと つらさをいなすことができる場面がある

Slide 53

Slide 53 text

53 Rails: ビューには可能な限りロジックを書かないこと(翻訳)|TechRacho by BPS株式会社 https://techracho.bpsinc.jp/hachi8833/2023_03_10/55778 書くときにひと呼吸おいて考えてから 書いてほしいRailsコードの書き方 https://speakerdeck.com/shinkufencer/rails-programing-code-that-i-hope-you-will-consider-if-you-really-need-it 状態論 (1) | Marginalia https://blog.lacolaco.net/posts/theory-of-state-01/ Thanks! 参考/次点で読むといい話など: しんくう / shinkufencer a.k.a ikuo.takada   @shinkufencer コード日進月歩 https://shinkufencer.hateblo.jp/