Slide 1

Slide 1 text

今年 会社でのレビ 今年 会社でのレビ ューで話した事 ューで話した事 銀座 Rails #16 Dec 13, 2019

Slide 2

Slide 2 text

⾃⼰紹介 ⾃⼰紹介

Slide 3

Slide 3 text

@ryosuke_sato

Slide 4

Slide 4 text

サトウリョウスケ サトウリョウスケ 株式会社フィードフォース ソーシャル PLUS バックエンドエンジニア 開発リーダー

Slide 5

Slide 5 text

今年の振り返り 今年の振り返り

Slide 6

Slide 6 text

銀座 RAILS に 3 回登壇しました 銀座 RAILS に 3 回登壇しました 銀座 Rails #07, Mar. 26 rubocop_challenger という gem を作った 銀座 Rails #10, June 21 My API Client 銀座 Rails #16, Dec. 13 今年 会社でのレビューで話した事 ← New!!!

Slide 7

Slide 7 text

RUBOCOP_CHALLENGER という GEM を RUBOCOP_CHALLENGER という GEM を 作った (#07) 作った (#07) https://github.com/ryz310/rubocop_challenger

Slide 8

Slide 8 text

MY API CLIENT (#10) MY API CLIENT (#10) class ExampleApiClient < MyApiClient::Base endpoint 'https://example.com/v1' error_handling status_code: 200, json: { '$.errors.code': 10 }, raise: MyApiClient::ClientError attr_reader :access_token def initialize(access_token:) @access_token = access_token end # GET https://example.com/v1/users def get_users(condition:) https://github.com/ryz310/my_api_client

Slide 9

Slide 9 text

来年も登壇がんばりたい

Slide 10

Slide 10 text

今⽇話すこと 今⽇話すこと

Slide 11

Slide 11 text

今年 会社でのレビューで話した事 今年 会社でのレビューで話した事

Slide 12

Slide 12 text

クラスの設計がムズいという声を受けて 会社の勉強会では 45 分 x 2 回話した 今⽇はその中から⼀部を抜粋して持ってきまし た

Slide 13

Slide 13 text

1. 抽象度を揃える 2. 継承について考える 3. 現実から学ぶ

Slide 14

Slide 14 text

1. 抽象度を揃える 1. 抽象度を揃える

Slide 15

Slide 15 text

Q. これは何でしょう? トマトとモッツアレラチーズのサラダ 娼婦⾵スパゲティ ⼦⽺背⾁のリンゴソースかけ プリン

Slide 16

Slide 16 text

A. トニオさんのレストランのメニュー

Slide 17

Slide 17 text

例えばこの美味しそうなスパゲティを

Slide 18

Slide 18 text

仗助に材料別のところまでもどされると

Slide 19

Slide 19 text

いきなり違和感が出てきた トマトとモッツアレラチーズのサラダ スパゲティ茹でてニンニクと唐⾟⼦とプチトマ トを良い感じに炒めて絡める ← ⼦⽺背⾁のリンゴソースかけ プリン

Slide 20

Slide 20 text

▶ 抽象度を揃えよう 材料と調理⽅法について知っているのはトニオ さん(シェフ)だけで良いはず このクラスを扱う⼈はどのようなレベル感で対 象を知っているべきなのかを考えよう ※ 抽象化の⽅法はクラス化する、メソッド化す る、とかです。

Slide 21

Slide 21 text

抽象度が揃わないよくあるケース ワンライナーだからメソッド化しなかった の条件式だから ( 略 ) 単純な処理だから ( 略 )

Slide 22

Slide 22 text

処理が短くても抽象化すると ⾒えてくる事があります。

Slide 23

Slide 23 text

イタリアンの中に唐揚げ??? トマトとモッツアレラチーズのサラダ 娼婦⾵スパゲティ 若鶏の唐揚げ ← プリン

Slide 24

Slide 24 text

抽象化されてないとちょっと気付きづらいかも トマトとモッツアレラチーズをスライスして特 製ドレッシングをかける スパゲティ茹でてニンニクと唐⾟⼦とプチトマ トを良い感じに炒めて絡める チキンに下味をつけて油で揚げる プッチンする

Slide 25

Slide 25 text

抽象度を揃えるメリット クラスが単⼀責任の原則に従っているかどうか を確認しやすくなる 可読性が上がる リファクタリングしやすくなる

Slide 26

Slide 26 text

レビュー依頼に出す前に 抽象度が揃っているか確認しよう

Slide 27

Slide 27 text

抽象度の揃ってないコードで レビュー依頼に出してきたら …

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

2. 継承について考える 2. 継承について考える

Slide 30

Slide 30 text

クラスの継承にはいくつかの パターンがあると思います。

Slide 31

Slide 31 text

Interface Pattern Layer Pattern DSL Pattern and so on.

Slide 32

Slide 32 text

それっぽい名前つけましたが 僕が勝⼿に呼んでるだけです

Slide 33

Slide 33 text

結論から先に⾔うと

Slide 34

Slide 34 text

⾊んな継承パターン混ぜて使うのは やめた⽅が良いです

Slide 35

Slide 35 text

INTERFACE PATTERN INTERFACE PATTERN

Slide 36

Slide 36 text

クラスの使い⽅を規格化するための継承。 ⾝近な例だと Ruby webserver interface の 。 Rack

Slide 37

Slide 37 text

def call(env) [ 200, # (Integer) { 'Content-Type' => 'text/plain' }, # (Hash) ['Hello World'] # (String ] end

Slide 38

Slide 38 text

Rack の規格(簡略版) メソッドを定義すること 引数 を受け取ること 戻り値は

Slide 39

Slide 39 text

楽器やってない⼈にはさっぱりかもですが、 エレキギターのエフェクターは 分かりやすい例だと思います

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

規格が揃っているから ⾊んなメーカーのエフェクターを 同じように組み合わせられる

Slide 42

Slide 42 text

LAYER PATTERN LAYER PATTERN

Slide 43

Slide 43 text

OSI 参照モデルと同じような考え⽅。 継承の階層ごとに扱う問題を分ける。

Slide 44

Slide 44 text

例えば JWT で認証するような API を作っている時。

Slide 45

Slide 45 text

ヘッダから JWT を検証する処理は で実装する。 class ApplicationController < ActionController::API before_action :verify_authentication_header def verify_authentication_header decode_authentication_header rescue InvalidAuthenticationScheme render status: :bad_request rescue VerificationFailed, Expired render status: :unauthorized end end

Slide 46

Slide 46 text

継承先の⼦クラスでは JWT 認証の事は考えずに済む。 class SomeController < ApplicationController def index end def show end end

Slide 47

Slide 47 text

DSL PATTERN DSL PATTERN

Slide 48

Slide 48 text

⾝近な例だと ActiveRecord とか。 class Company < ApplicationRecord has_many :employees validates :name, presence: true scope :xxx end

Slide 49

Slide 49 text

親クラスを継承することで DSL ( ドメイン固有⾔語 ) が使えるようになる、 というパターン。

Slide 50

Slide 50 text

拙作の も DSL Pattern です(宣伝) class ExampleApiClient < MyApiClient::Base endpoint 'https://example.com/v1' error_handling status_code: 200, json: { '$.errors.code': 10 }, raise: MyApiClient::ClientError https://github.com/ryz310/my_api_client

Slide 51

Slide 51 text

3 つのパターンをご紹介しましたが、 親クラスに複数のパターンが 適⽤されている場合は 責務を負い過ぎている可能性があります。

Slide 52

Slide 52 text

特に DSL パターンはみんな (?) やりたがりますが、 プロダクトのコードではやらない⽅が 良いと思います。

Slide 53

Slide 53 text

どうしてもやりたい場合は gem にしましょう

Slide 54

Slide 54 text

3. 現実から学ぶ 3. 現実から学ぶ

Slide 55

Slide 55 text

世の中の事象は設計に役⽴つ事が多い 世の中の事象は設計に役⽴つ事が多い

Slide 56

Slide 56 text

⽔道は蛇⼝を右にひねれば⽔が⽌まる

Slide 57

Slide 57 text

右利きの⼈間の割合が世の中的に多い 右腕は右にひねる⽅が得意 ⽔を⽌める事 の⽅がやりやすい UI の⽅が安全

Slide 58

Slide 58 text

▶ 突き詰めて考えれば、 ⾃ずと仕様が決定される

Slide 59

Slide 59 text

時計は少しずつ早い時間にずれていく⏳

Slide 60

Slide 60 text

時計の誤差は少しずつ蓄積されていく 早まる⽅向に誤差を貯めた⽅が事故を防ぐこと に繋がりやすい (電波時計が無かった頃の話ね)

Slide 61

Slide 61 text

▶ どうやってもズレる事を防げないのであれば、 安全な⽅向に倒す

Slide 62

Slide 62 text

普段から⽇常を観察しておくと こういう知識が仕様決める時に役に⽴つ(かも)

Slide 63

Slide 63 text

他にも話したい事はたくさんありますが、 時間がないのでブログに書きます

Slide 64

Slide 64 text

ちなみにブログはまだ開設すらしてません (来年の⽬標です)

Slide 65

Slide 65 text

今年も⼀年お世話に 今年も⼀年お世話に なりました なりました

Slide 66

Slide 66 text

来年も宜しくお願い 来年も宜しくお願い 致します 致します END