言語学習?

プログラミング言語と並行してフランス語の学習に精を出しているフラリモートスバルです。

21時になっても太陽が昇ったまま

そのため仕事終わりは

近くにあるプールでぷかぷか浮かび無の時間を楽しんだり、

海辺へ行って散歩をしたりしてます。

 

今の内に暇と退屈に対する感度を上書き保存しておこうと必死なのかもしれません。。

 

ServiceObject

本的な概念

<aside> 💡 A good service object is easy to test and follows the single responsibility principle.

</aside>

テストを書いたり、読み進めることが簡単であるべき。ServiceObjectには一つのビジネスロジックしか書かれていないから。

Amin Shah Gilaniは、ServiceObjectに切り出すべきか迷った時のフローチャートを示している。

Does your code handle routing, params or do other controller-y things?If so, don’t use a service object — your code belongs in the controller.

Are you trying to share your code in different controllers?In this case, don’t use a service object — use a concern.

Is your code like a model that doesn’t need persistence?If so, don’t use a service object. Use a non-ActiveRecord model instead.

Is your code a specific business action? (e.g., “Take out the trash,” “Generate a PDF using this text,” or “Calculate the customs duty using these complicated rules”)In this case, use a service object. That code probably doesn’t logically fit in either your controller or your model.

このコードってServiceObjectに切り出すべき、、?

  • routingやparams等のコントローラーっぽい処理をしている。

no, it should be in the Controller

  • 他のコントローラーと処理を共有している。

no, it should be in the Concern

  • 永続処理の不要なモデル処理をしている。

no, it’s non-ActiveRecord model (FormObject or something)

  • 詳しいビジネス処理(PDF作成、計算、ゴミ処理等)を行っている。

yes, ServiceObject should help it!!!


コントローラーって、責務を知らないと肥大になりがち。

with rendering and redirecting—normal controller concerns.

コントローラーは、renderかredirectという、コントローラの関心ごとにfocusさせたい。

class UserController < ApplicationController
  def create
    user = User.new(user_params)
    if user.save
      send_welcome_email
      notify_slack
      if @user.admin?
        log_new_admin
      else
        log_new_user
      end
      redirect_to new_user_welcome_path
    else
      render 'new'
    end
  end  # private methods
end

かといってモデルにロジックを移していくと、今度はモデルが肥大化しがち。

コントローラーとモデルの間に受け皿という形で層を設けることができたら、それぞれの処理が何をやっているのかが明確になって後で使用の把握に役立つ。

その「層」の役割を担うのがいくつかある。

その一つにService層がある。

Service objects in Rails

What are service objects?

Service objects are plain old Ruby objects (PORO’s) that do one thing.

単一責務のオブジェクト(PORO)

Serviceクラスにより詳細な機能を切り出すことで、

最終的にここまでコントローラーをスリムにすることができる。

class UserController < ApplicationController
  def create
    user = RegisterUser.new(User.new(user_params)).execute
    if user
      redirect_to new_user_welcome_path
    else
      render 'new'
    end
  end  # private methods
end

ServiceObject.new(arguments).executeの形が不恰好だと思ったら、下記のように独自にcallメソッドを定義しちゃってもいい。

class RegisterUser
  def self.call(*args, &block)
    new(*args, &block).execute
  end  def initialize(user)
@user = user
  end  def execute
    # old code
  end  # private methods
end

コントローラーはこうなる

class UserController < ApplicationController
  def create
    result = RegisterUser.call(User.new(user_params))
    if result.success?
      redirect_to new_user_welcome_path
    else
      render 'new', error: result.errors
    end
  end  # private methods
end

Serivice Classを理解する上で大事なことだから再掲

基本的な概念

<aside> 💡 A good service object is easy to test and follows the single responsibility principle.

</aside>

テストを書いたり、読み進めることが簡単であるべき。ServiceObjectには一つのビジネスロジックしか書かれていないから。

Amin Shah Gilaniは、ServiceObjectに切り出すべきか迷った時のフローチャートを示している。

Does your code handle routing, params or do other controller-y things?If so, don’t use a service object — your code belongs in the controller.

Are you trying to share your code in different controllers?In this case, don’t use a service object — use a concern.

Is your code like a model that doesn’t need persistence?If so, don’t use a service object. Use a non-ActiveRecord model instead.

Is your code a specific business action? (e.g., “Take out the trash,” “Generate a PDF using this text,” or “Calculate the customs duty using these complicated rules”)In this case, use a service object. That code probably doesn’t logically fit in either your controller or your model.

このコードってServiceObjectに切り出すべき、、?

  • routingやparams等のコントローラーっぽい処理をしている。

no, it should be in the Controller

  • 他のコントローラーと処理を共有している。

no, it should be in the Concern

  • 永続処理の不要なモデル処理をしている。

no, it’s non-ActiveRecord model (FormObject or something)

  • 詳しいビジネス処理(PDF作成、計算、ゴミ処理等)を行っている。

yes, ServiceObject should help it!!!

(*args, &block)

テンプレートのレンダリングで見かけた記法。

rails/rendering.rb at 04972d9b9ef60796dc8f0917817b5392d61fcf09 · rails/rails

スプラット(液体が地面に落ちた時などの音)がついた変数には配列が入る。

下記のように展開される。

*a = 1
a #=> [1]

a, *b = 1, 2, 3, 4
a #=> 1
b #=> [2, 3, 4]

a, *b, c = 1, 2, 3, 4
a #=> 1
b #=> [2, 3]
c #=> 4

self.call(*args, &block) vs self.call(args)

They allow you to specify a callback to pass to a method. This callback can be invoked two ways - either by capturing it by specifying a final argument prefixed with &, or by using the yield keyword:

&blockは明示しなくてもいい

その代わりに、メソッドの内部でyieldとしてあげるだけでも同じ挙動をする。

def meth_captures(arg, &block)
  block.call( arg, 0 ) + block.call( arg.reverse , 1 )
end

irb> meth_captures('pony') do |word, num|
       puts "in callback! word = #{word.inspect}, num = #{num.inspect}"
       word + num.to_s
     end
in callback! word = "pony" num = 0
in callback! word = "ynop" num = 1
#=> "pony0ynop1"
irb> def meth_yields(arg)
       yield(arg, 0) + yield(arg.upcase, 1)
     end
#=> nil
irb> meth_yields('frog') do |word, num|
       puts "in callback! word = #{word.inspect}, num = #{num.inspect}"
       word + num.to_s
     end
in callback! word = "frog", num = 0
in callback! word = "FROG", num = 1
#=> "frog0FROG1"

また、&に渡すblockは、塊として定義しておくことができる

そうするには、Procオブジェクト、→、lambdaを使用することで代用することができる。

irb> callback = lambda do |word, num|
       puts "in callback! word = #{word.inspect}, num = #{num.inspect}"
       word + num.to_s
     end
#=> #<Proc:0x0052e3d8@(irb):22>
irb> meth_captures('unicorn', &callback)
in callback! word = "unicorn", num = 0
in callback! word = "nrocinu", num = 1
#=> "unicorn0nrocinu1"
irb> meth_yields('plate', &callback)
in callback! word = "plate", num = 0
in callback! word = "PLATE", num = 1
#=> "plate0PLATE1"

What's this &block in Ruby? And how does it get passed in a method here?

エンティティ

システムでオブジェクトの同一性が重要な意味を持つもの

「中野」の体重が変わっても、変わる前と変わった後で「中野」であることに変わりは無い。

体重が変わったら「中野」じゃなくなるわけではない。

前後の同一性を判断するための識別子(id)というものを持っている。

値オブジェクト

「何であるか」が重要なもの

そして、値が同じであれば同一とみなしていいもの

神奈川県に対する思いや印象は人それぞれでいいが、神奈川県は神奈川県である。

住所は住所

そのオブジェクトが持っている値が同じかどうかで同一性が比較される。

値オブジェクトは、それだけのクラスに切り出すことができる。

例えば、住所という概念は、UserやCompany,Organizationクラスで使われるかもしれない。

そんな時は、Address(住所)という独立クラスを作成して複数のクラスから参照できるようにするとベター。

クリーンアーキテクチャ

最も柔軟なシステム

それは、ソースコードの依存関係が、具象だけではなく、抽象だけを参照しているものを指す。

安定度の高いシステムを作る

そのためには、すべての具象コンポーネントがI(Instability)の低いコンポーネント(抽象コンポーネント)を指し示すようなシステムを作る必要がある。

安定度の指標として、下記のような単語がある

ファンイン クラス内部のメソッドが外部から依存を受けている数

ファンアウト クラス内部のメソッドが外部のクラスに対して依存している数

I(Instability: 安定性

= ファンアウト➗(ファンイン+ファンアウト)

<aside> 💡 つまり、外部のクラスに一つも依存していないクラスが、一番安定しているクラスと言える。

</aside>

May the result of pcr test be negative!

東京〜フランス間のフライトがトランジット含めて31時間かかることに発狂している7月末です。

「Clean Architecture」「Clean Code」「独習UML」を借りました。これを読んで8月は開発者としてのプロ意識を高めていきたいです。

もっぱら小説に対する欲が薄れていて、開発に関する書籍を読みたい欲に変わってしまいました。いいのか悪いのか。。

そしたら今週の振り返りをつらつらと。。

 

 

高凝集 低結合

凝集度 結合度とは

ソフトウェアの品質を表す指標を指す。

クリーンなソフトウェアを構築していくためには、「ソフト」なアプリ、つまり柔軟なアプリを作成することを心がける必要がある。

柔軟なアプリとは、仕様変更に柔軟に対応できるアプリ、つまり運用保守性の高いアプリを指している。

そのために、過去の賢人達が様々なデザインパターン(効率的にソフトウェアを作り上げる手段)を考案されている。

そこで出てきた重要な単語が凝集度 結合度だった。

凝集度

下記のような特徴がある。凝集度は高い方が良い。

  • クラスの責務、クラスのメソッドとデータ(機能要素と情報要素間)の関連性の強さ

クラスの責務が単一であればあるほど良い。

なぜなら、クラスを修正した時の影響範囲を追いやすくなり運用保守性が高まるから。

  • クラスの責務とは、「そのクラスが何をするクラスなのか?」に対する答え

クラスを設計するときは、一体これは何をするべきクラスなのか?と問いながら作成するといい。

結合度

モジュール間の依存度を示す指標で、こちらは低い方がいい(疎結合、低結合)

なぜなら、依存度が高いということは、依存先の修正の影響を受けやすいと言っていると同義だから。

凝集度を低くしないためには下記二つを意識するといいみたい。

  • そのクラスが何をしているのかを明確に答えられるようにする。(クラスの責務を明確にする)
  • クラス内のデータと関係のないメソッドをなくす

オブジェクト指向は1回忘れよう。10分でわかる設計のツボ 「高凝集/低結合」

git restore

リモートにプッシュしてしまったコミットを無しにしてくれる

開発を進めている中で、いらないファイルをコミットしてしまった場合に下記のコマンドが使える。

-sはsoftの略で、ファイルの変更内容は残しながら、コミットは無かったことにすることができるコマンド。

git restore -s HEAD^ foo.txt

Git初心者なら必ず覚えるべきgit restoreコマンド

initialize

クラスのインスタンス作成時に自動で読み込まれる

ここに変数を記述しておくことで、他のメソッド内において属性をハンドリングすることができるようになる。

  • attr_readerと同じ処理
  #@nameを外部から参照するためのメソッド
  def name
    @name
  end
  • attr_writerと同じ処理
   #@nameを外部から変更するためのメソッド
  def name=(value)
    @name = value
  end

全てまとめたクラス

class User
  def initialize(name)
    @name = name
  end
  
  #@nameを外部から参照するためのメソッド
  def name
    @name
  end

   #@nameを外部から変更するためのメソッド
  def name=(value)
    @name = value
  end
end

上記のクラスからインスタンスを生成する時に、その親クラスから継承してきた属性に入れる値を決める。

User.new('Subaru')

これを外部から参照するときは、

User.new('Subaru').name
#もしくは
user = User.new('Subaru')
user.name
#=> Subaru

これを上書きするときは、

user.name = 'Nakano'

name=(value)メソッドが呼び出されて、インスタンスの中身が上書きされる。

Block Proc

Block

ブロックとは、mapやeachの後によく見られる、do ~ end, {}で囲われた引数となる部分をさす。

メソッドに引数として渡される塊。

def yield_block_contents
  yield
end

#
yield_block_contents do
  p "Hello, block!"
end

#=> "Hello, block!"

引数にブロックが渡されることを明示する。

#メソッド定義
def yield_block_contents( &block )
  block.call
end

#実行
yield_block_contents do
  p "Hello, block!"
end
=> "Hello, block!"

引数のblockの前にある&でblockをProcオブジェクトに変換している。

(&:to_s)

to_s(何でもいい)メソッドを呼び出すオブジェクトにto_procが定義されている場合、(&:to_s)のような書き方ができる。

Array.map(&:to_s)

SymbolオブジェクトをProcオブジェクトに変換して新しい配列を返す書き方。

Symbolオブジェクトがto_procを組み込みで持っている為、(&:to_s)のように、

シンボルに対してBlockに渡すことができている。

to_procメソッドを作成してeachにFooインスタンスを渡してみる。

class Foo
  def to_proc
    Proc.new {|v| p v}
  end
end

#Fooのto_procが呼び出されてProcに渡されている。
[1,2,3].each(&Foo.new)

=> 1
   2
   3

Proc

先ほど学んだ、Blockをオブジェクト化させたもの。

ブロックはそのままでは存在できない。その為、Procオブジェクトとして保管して置く必要がある。

使用するときは、Procオブジェクトから作成したインスタンスをレシーバとしてcallメソッドを呼び出す。

procedureの略。

下記のような方法がある。

[1, 2, 3].map do |n|
  :to_s.to_proc.call(n)
end
# => ["1", "2", "3"]
# Proc オブジェクトを直接呼び出す場合は call メソッドを用いる

[1, 2, 3].map(&:to_s.to_proc)
# => ["1", "2", "3"]
# 明示的にto_proc して Proc オブジェクトをブロックの代わりに渡している

[1, 2, 3].map(&:to_s)
# => ["1", "2", "3"]
# to_proc を持つオブジェクトとして :to_s を渡している。

Ruby block/proc/lambdaの使いどころ - Qiita

Ruby のブロックをちゃんと理解する

近づくな、Covid-19インスタンス

 

頼むからCovid-19インスタンスを中野クラスをスーパークラスに持つスバルインスタンスに移譲させないでくれと願う今日この頃です。

 

暇と退屈の倫理学のあらすじに興味深い描写があります。

時間とお金に余裕ができたら、好きなことをする。

19世紀だったら、需要(自分が好きなこと)が供給(好きなことを満たしてくれるサービス)の先に来ていたけど、

今は供給(広告が提供するサービス)が需要(自分の好きなこと)の先に来てしまっている。

 

「時間とお金に余裕ができたら、好きなことをする」

自分の本当に好きなことって時間とお金に余裕ができてからじゃないとできないのだろうか?

 

今のままだとお金に余裕ができる頃には、時間に余裕ができなくなって、結果として好きなことができないじゃないか、と2年前の新卒銀行員時代に考えていたこととリンクして、「暇と退屈の倫理学」の沼にハマっていきました。。

 

オブジェクト指向に対する理解を深めようとした一週間でした。

 

ウイルスクラスからCovid-19インスタンスが作られる。

ウイルスクラスには免疫力を下げるというメソッドがある。そして繁殖力が強い、飛沫感染するといった属性を持つ。

 

 

 

振る舞いとデータ、カプセル化

データは変数に入る

振る舞いは、データを扱う

この二つを一緒に格納することをカプセル化という。

カプセル化したものを設計図としてクラスに保管しておく。

Ruby

ビジネスロジック

アプリケーションをプレゼンテーション・ビジネスロジック・データアクセスの 3 つに分けたとき、「プレゼンテーションでもデータアクセスでもない部分がビジネスロジック

アプリケーションの中核をなすロジックを書く場所で、3層アーキテクチャ(プレゼンテーション層、ビジネスロジック層、データアクセス層)の一部を指している。MVCでいう、モデルとコントローラーが担う場所。

なんだか似ている用語が多くて戸惑ってしまう。

それぞれに対応するそうは下記のような画像で強引に理解することにする。

 

OSI 7階層参照モデルとは?

「ビジネスロジック」とは何か、どう実装するのか - Qiita

Gofデザインパターン

Rails wayに沿ってアプリの設計をしていくときに、開発者同士で共通の認識があったら効率がいい。

過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものを指しているそう。(cited: wikipedia

このGofgang of four)を参考にすると、オブジェクト指向型のアプリ設計がしやすくなる。

大きく下記三つのパターン分けがされていてる。

生成に関するパターン、構造に関するパターン、振る舞いに関するパターン

振る舞いに関するパターンは、クラスを設計するときに特に参考になった。

Java言語で学ぶデザインパターン入門

GoFのデザインパターンまとめ - Qiita

インターフェースと抽象クラス

前者が外部向けの設計図、後者が内部向けの設計図と表現されることが多い。

Javaで使われる用語だが、rubyにもインターフェースやダックタイピング、ポリモーフィズム等通ずるところが多いため、学習する価値はあると思う。

【詳解】抽象クラスとインタフェースを使いこなそう!! - Qiita

インターフェース

CAN DOの関係あるといえる。

テレビcan 音量調節、テレビcan 電源消し付け

継承先に対して、定義したものの実装を強制することができる

「Inputする値とOutputされる値が同じ」という規約がインターフェース。と認識している。

このインターフェースを継承させて多態性を作っていくと、ダックタイピングにつながってくる。

<aside> 💡 中(具体的な処理)は意識せず、外(他のクラス)から見てテレビが出来ることを定義する感じ

</aside>

インターフェース名には、作成したいインスタンス群を抽象的にした概念名をつけて、そのインターフェースを継承したインスタンスに保持しておいてほしいメソッドを、空のまま定義しておく。

ex)

テレビ(インターフェース)薄型テレビ(インスタンス)、ブラウン管(インスタンス

テレビに音量調節(メソッド)、電源消し付け(メソッド)、チャンネル切り替え(メソッド)といった空のメソッドを定義しておく。

抽象クラス

Is Aの関係にあると言える。

薄型テレビ is テレビ、ブラウン管 is テレビ

インターフェースと同様、継承先に対して、定義したものの実装を強制することができる。

継承されることを前提としてて作られているクラスなので、抽象クラスを直接インスタンス化させることはできない。

振る舞いの型(電源をオンオフする、音量調節する)を継承をし、具体的な処理を個性(属性、値)に合わせて上書き(オーバーライド)する。

インターフェースと抽象クラスの使い分け、活用方法 - Qiita

【Java入門】インターフェースとは?抽象クラス(abstract)との違い

雨模様の天気と裏腹な心模様

RUNTEQの開発合宿に行って勝手に刺激をもらってきたRUNTEQ卒業生駆け出しエンジニアスバルです。

合宿は、好きな開発テーマ毎にメンバーを割り振る形で進んでいました。

Flutterでなんか作る、GraphQL理解する、github actionsでセルフレビューLGTM生成CI環境作成などのチームがある中、僕はreactとtypescriptのチュートリアルを通して五目並べゲームを作成しました。

vueのcomposition APIの書き方がreactの書き方を真似ていたこともあり、意外とreactの基礎理解した!という気分になりました笑

開発って楽しい!

あと、「暇と倫理の退屈学」面白すぎて他の小説が読めなくなってしまった。。

雨続きだけど心は晴れやかな今日この頃です。

 

 

ポリモーフィック関連付け

ダックタイピングの一種。

インスタンスにも親クラスと同じメソッドを持たせておくことで、親クラスを呼び出した時の出力を定義すること。

このように、「違うものがある決まった振る舞い/入出力を持つことで、同じように扱えるようにすること」をダックタイピングと呼びます。そして、その「ある決まった振る舞い」「入出力の定義」のことをインターフェースと呼びます。

コード例に沿って表現すると、DuckCatは違うクラスですが両方とも#soundというメソッド(インターフェース)を持つので、Animalの中ではどちらのオブジェクトであるかを意識せず#soundを呼ぶことができる、というのがダックタイピングです。

呼び出すのは親クラス。下記が今回のインターフェイスということになる。

Animal.new(インスタンス名).sound を実行したときに、鳴き声が返ってくる」

入力: Animal.new(インスタンス名).sound を実行

出力: 鳴き声が返ってくる

この定義を守ることで、どんな動物のインスタンスを入れたとしてもその動物の鳴き声が出力されることが担保される。

これを実現してくれるのがポリモーフィック関連付けという。

Railsのポリモーフィック関連とはなんなのか - Qiita

 

浅いネスト

ネストしたリソースを書くときにshallowをtrueにするとshow/edit/update/destroyのような、idを必要とするアクションを省略して表現することができる。

resources :articles do
  resources :comments, shallow:true
end
POST /articles/:article_id/comments(.:format) comments#create article_comments_path
GET /articles/:article_id/comments/new(.:format) comments#new new_article_comment_path
GET /comments/:id/edit(.:format) comments#edit edit_comment_path

Rails のルーティング - Railsガイド

Storybook

画面遷移のモックを開発中のアプリに作成することができるライブラリ。

reactやvueの書き方で既存のプロジェクトに画面遷移のモックを実装できるから学習コストが少ない。

下記参照記事が詳しい。

storybookを理解する

Component Story Format 3.0

例えば、プロジェクトの実装で挨拶ページを作成したいと思ったとする。

下記のようにpugという拡張子のファイルと**.stories.jsというファイルを作成する。

#greeting.pug

mixin Greeting (props = {})
  .container.p-4
    block
    .row
      .col
        p=props.hello_ja
      .col 
        p=props.hello_en
#greeting.stories.js

import startCase from 'lodash/startCase';
import Greeting from './greeting.pug';
import { renderer } from 'storypug';

const { render } = renderer({ startCase });
export default {
  title: '挨拶',
};

export const Basic = () => {
  // setup props
  const props = {
    hello_ja: 'おはよう',
    hello_en: 'hello',
  };

  const contents = `<h3>| 挨拶</h3>`;
  const wrapper = render(Greeting, props, contents);
  return wrapper.$root;
};

これだけで下記のような画面が表示される。



不要なマイグレーションファイルの削除

$ rails db:migrate:status #不要なマイグレーションファイルの日付を確認
  database: hoge_development

   Status   Migration ID    Migration Name
  --------------------------------------------------
     up     20220712031711 Create users table
          up     20220712031711 Create posts table
     up     20220712062672 Change users age to integer
     up     20220713032240 Change posts body to text

$ rails db:migrate:down VERSION=20220713032240 #確認したファイルの日付を=の後に入れる

ファイル名を適当な名前に変える

class Hoge < ActiveRecord::Migration[6.0]
  def change
  end
end
$ rails db:migrate:status #不要なマイグレーションファイルがdownになっていることを確認

database: hoge_development

   Status   Migration ID    Migration Name
  --------------------------------------------------
     up     20220712031711 Create users table
          up     20220712031711 Create posts table
     up     20220712062672 Change users age to integer
    down    20220713032240 hoge

$ rm 20220713032240_hoge.rb #不要なファイルを削除

【Rails】ロールバック(rollback)で何が起こっているか?schema_migrationsとは?意味と役割。UPとDOWNとは?それぞれの使い方

クエリのキャッシュ制御

一度実行したクエリはキャッシュとして保存されている。

# データベースからbooksを取得する
author.books.load
# booksのキャッシュコピ-に対してsizeメソッドを実行する
author.books.size

キャッシュを破棄して新しいキャッシュを作成したい場合は下記のようにreloadを使う。

author.books.reload.size

Active Record の関連付け - Railsガイド

 

ボンジュール、夏

ポストに手紙が挟まれてた。エミと名乗る外国人女性から、「一言で言うと、仲良くなりたいです。」という手紙が。

そんなフィクションのようなノンフィクションが昨夜起きました。麦茶を片手に世田谷公園まで散歩して、いろいろとお話をしてきました。

忘れられない夏が始まりそうな予感!

それはともかく、「暇と退屈の倫理学」という本が人生のペアプロをしてくれて最近は読書が楽しいです。

「消費、浪費、退屈、興奮、暇、忙殺、労働、自由」等、僕には近づき難かった哲学的思想を噛み砕いて一緒に考えてくれます。最初50pでもいいから読んで感想を聞かせて欲しいです。笑

 

 

docker-compose とは

docker-composeはdockerを使って行う環境構築をより簡潔に行うことができるファイルのこと。

docker-compose.ymlにフロントエンドとバックエンド、データベース、インフラで使うパッケージ()を記述してdocker-compose build を実行後、docker-compose upを実行するだけでDockerネットワークを構築することができる。

Docker Composeとは?使い方やコマンドを紹介(Rails,MySQL,Nginx)

Cmposed Methodパターン

単一責任原則を実現する時に使う、肥大化した関数を分割する方法の一つ。

def a
 puts 'a'
 puts 'b'
 puts 'c'
end
def a
  puts 'a'
  b
  c
end

def b
  puts 'b'
end

def c
  puts 'c'
end

「文章のように読めるメソッドを作る」 Composed Method パターン - Qiita

Rubyのクラスメソッドがリファクタリングに抵抗する理由(翻訳)|TechRacho by BPS株式会社

Extract Function

データモデリング

アプリのモデルを設計したいときは、メインの機能をまず抽出。

そして、「何が」「誰が」「何を」「どうする」「どんな」などを意識して、エンティティを抽出していく。

そうすることでテーブル設計(正規化)がしやすくなる。

  • 業務ルールの確認

業務で使われている帳票や、すでにあるシーケンス図を確認する

  • エンティティの抽出

「人」「物」「金」「時間」「やり取り・活動・行為」に注目してテーブルの要になるエンティティを抽出する。

  • 過不足の確認

業務ルールを表現するためのエンティティに過不足がないかを確認する

  • リレーションの確認

それぞれのエンティティをつなぎ合わせる関連づけを行う

git ls-files —stage

現在ステージに上がっているファイルのパスを確認するコマンド

Git - git-ls-files Documentation

集約操作(GROUP BY句)

データセットを見ていると国によっては複数のレコードを持っていることが分かります。GROUP BY 句を利用すると指定したカラムの値でグループ分けした結果に対して COUNT 関数などを利用した集計を行うことができます。

    SELECT
      <カラム>
    FROM
      <テーブル>
    WHERE
      <条件>

    GROUP BY
      <集約するカラム> -- 複数指定可能
    HAVING
      <集約後の結果に対する条件>
  • HAVING

集約後の結果に対する条件付与

→GROUP BYで特定のデータ条件に絞って集約

→その結果に対してさらに条件を絞る

  • WHERE

集約前の結果に対する条件付与

FROMやJOIN ONで調べた結果に対して条件を絞る

SQLの評価順序が下記のようになっているため、条件を絞るタイミングを意識してクエリを作成するといい。

基本的にSQLは以下の順番で実行される。

1.from  2.where  3.group by  4.having  5.select  5.union  6.order by  7.distinct

※上記の基本があるため、下記のようにselect句で別名をつけても、where句では評価されない。

select nickname AS n
  from Person
 where n = 'subaru'

-> エラー発生

下記数字の順番で読み込まれるため、2のnが何を示しているのかが読み取られていない。
3 select nickname AS n
1  from Person
2 where n = 'subaru'

 http://www.postgresql.jp/document/8.1/html/sql-select.html

 

機能要件 非機能要件

機能要件は、「ソフトウェアやシステム開発において、クライアントから求められる『機能』のこと」。

一方、非機能要件とは『機能以外』のユーザービリティ、性能、拡張性、セキュリティなどの品質的に関連するもの全般を指す。

機能だけを追加すればいいのではなくて、その機能を追加した結果、どんな体験、安全性を与えてくれるかまでを定義しないといけないんですね。

機能要件とは?システムの品質向上にかかわる非機能要件との違い|発注成功のための知識が身に付く【発注ラウンジ】

叙述トリックにハマった、24歳梅雨明け

もうやんカレー旨かった。

殺戮にいたる病を読み終えた。衝撃のラストってやつ。最後に近づくにつれ、心の中でえーーーーーがこだましてた。笑

「カエルの楽園」を読み終えた。公な場でカエルの楽園に対する書評を連ねると右翼が黙ってなさそうだから控える。選挙間際になるとなぜかメディア(特に朝日)で過度に首相の取り組みに対して批判を煽る報道が増えている理由が少しわかった。

今週は「暇と退屈の倫理学」を読み進める。まだ50P程しかみていないが、ここ2年くらいぼんやりと考えていたことを少し代弁してくれている。

人生のペアプロをしてくれる哲学本?楽しみ。

 

 

 

sakilaを活用したSQLの練習

テーブル設計も載っている。

MySQL :: Sakila Sample Database :: 5 Structure

使用していくデータをインポートしてくる。

sakila sample databaseというものを使うみたい。

URLへアクセスして、example databasesにあるsakila sample databaseをダウンロード

MySQL :: Other MySQL Documentation

ダウンロードしたSQLファイルをデータベースに入れていく

How do I import an SQL file using the command line in MySQL?

ここまでやって気づいたけど、簡単にsakilaのデータベース環境を整えられるリポジトリを発見した。

https://github.com/tadatakuho/mysql-docker

READMEにある通り、下記の3ステップで環境を整えることができる


$ git clone git@github.com:tadatakuho/mysql-docker.git

$ cd mysql-docker

$ docker-compose up -d

dockerを立ち上げたら、docker内のmysqlへ潜り込んでいく

root@d69b65147102:/# mysql -u root -proot

Welcome to the MySQL monitor.  Commands end with ; or \\g.
Your MySQL connection id is 10
Server version: 8.0.29 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sakila             |
| sys                |
+--------------------+
5 rows in set (0.07 sec)

mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

usage guideへアクセスして、使い方を学んでいく。

MySQL :: Sakila Sample Database :: 6 Usage Examples

サンプル数が少ないので、キータの記事を参考にして、練習問題にチャレンジする。

SakilaとしたいSQLのお勉強-1 - Qiita

課題1を解いてみる

「nickさんの出演している映画」

必要なテーブルは三つ

Actor, FilmActor, Film

  1. まずは、欲しい情報の名詞を探す。

今回は「映画」

  1. first_nameかlast_nameがnickという名のActorを探すことになる。
  2. 先ほどActorから取得したidと一致するactor_idを持つFilmActorを探す。
  3. そのFilmActorテーブル内にあるfilm_idを取得する。
  4. そして、取得したFilmActorテーブル内のfilm_idと一致するidを持つFilmを取得する。

恐らく、テーブルを全て連結させてからデータを取得した方が無駄なクエリーは走らないはず。

だから、三つをくっつけてからwhereで取得する方法を探していく

三つ連結させる方法

Table1, Table2, Table3という三つのテーブルがあるとする。

それぞれをtable1を起点に、共通する部分のみの値を取得したいときは、下記の様にInner Joinを使う。

SELECT * FROM table1 
INNER JOIN table2 ON table1.id = table2.id 
INNER JOIN table3 ON table1.id = table3.id;

nymemo

Visual Representation of SQL Joins

クエリーに落とし込んでみる。

  1. SELECT * FROM Film f
  2. INNER JOIN FilmActor fa ON fa.actor_id = (SELECT id FROM Actor a where a.first_name = ‘nick’ or a.last_name = ‘nick’)
  3. INNER JOIN f ON f.film_id = fa.id

楽しい

配列展開 ハッシュ展開

Ruby 配列展開 *Array - Qiita

Ruby と ECMAScript の配列展開の挙動の違い

知っておきたいrubyの書き方

nilや””を検知する書き方、配列操作のシンプルな書き方が載っている。

Ruby on Railsの現場でよく見る書き方【実例あり】 - Qiita

差をつけるRuby - Qiita

Ruby on Railsでの良い書き方について - Qiita

テンプレートを探す

render ‘new’がどのようにして対応するテンプレートを探しているのかが分からなかった。

ActionViewのrenderメソッドの裏側が書いてある。

Railsのテンプレートレンダリングを分解調査する#1探索編(翻訳)|TechRacho by BPS株式会社

gemをrequire falseにする理由

bundlerによってgem自体はアプリにインストールされる。

アプリケーション内で複数回使用しないのであれば、gem 'simplecov', require: falseのように、後ろにfalseと使う。

使用したい場合は、明示的にファイル内でrequire ‘gem名’とする必要がある。

https://stackoverflow.com/questions/4800721/ruby-what-does-require-false-in-gemfile-mean#:~:text=You use %3Arequire %3D> false,as with gem install whenever .

git grep ’探したい文字列’

git grep の後に探したいメソッド名などを付ける。正規表現を使って絞り込みをすることもできる。

$ git grep hello
app/javascript/packs/hello_typescript.ts:// Run this example by adding <%= javascript_pack_tag 'hello_typescript' %> to the head of your layout file,
config/locales/en.yml:#     I18n.t 'hello'
config/locales/en.yml:#     <%= t('hello') %>
config/locales/en.yml:  hello: "Hello world"
lib/api/v2/qiita_api_client.rb:          user_id = get_user_id('subaru-hello')['id']

grepコマンドの詳細まとめました【Linuxコマンド集】

sendと_send_

sendメソッドとは

レシーバーが持っているメソッドを、文字列(またはシンボル)で指定して呼び出すことができる。

Object#send (Ruby 3.1 リファレンスマニュアル)

class Foo
  def bar?
    true
  end

  def send(*args)
    false
  end
end

foo = Foo.new
foo.send(:bar?)
# => false
foo.__send__(:bar?)
# => true

sendとの使い分け

sendは様々なクラスで使い回されているため、sendの本来の挙動を使用したい場合に_send_を使用する。

定数と変数のようなイメージ?sendはすでに他のクラスで上書き(メタプロ)されている可能性があって、_send_は上書きされない。

Ruby send vs send

小説と出会った6月

プログラミング以前に、言葉に含まれている意味を理解する能力が乏しいのではないかと思い、小説を読み始めた今日この頃。

とりあえず友達に勧められたものを読み進めようと思い、学芸大学前のTSUTAYAへ。

1000円程で「沈黙のパレード」「時生」「葉桜が咲く季節に君を想うということ」を購入し、一週間で読み終えてしまいました。

推理小説二冊、タイムスリップ物の小説一冊を読んだところで言葉の意味を理解する能力が向上したとは思えませんが、何だか集中力が上がった様な気がしてます。

今週は「カエルの楽園」「殺戮にいたる病」「昨夜のカレー、明日のパン」を読もうと思ってます。

ちなみに、ブクログというアプリで自分の読んだ本を管理してます。便利。

Nakano Subaru(すばる)の本棚 (Nakano Subaru(すばる)) - ブクログ

 

 

外部結合と内部結合

InnerJoinとOuterJoin(left, right)について書かれている。

通常、データを保存する場所を作成する時は、正規化(比較・演算などの操作のために望ましい性質を持った一定の形にすること)が行われるため、データを複数のテーブルに分割して保存される。

しかし、あるデータを検索したい時に、複数のテーブルに対して一つ一つ検索をかけていたら手間。

そこで、検索する前にテーブルを結合させてからデータを取得するという手法が取られる。

そんな時に使われるのが、前述した内部結合と外部結合という手法。

下記の様な違いがあるそう。

InnerJoin

テーブルAとテーブルBに共通するデータを全て取得する

Left Outer Join

左側のテーブルにあるデータ+右側にあるデータ-右側のみに存在するデータ を取得する。

Right Outer Join

右側のテーブルにあるデータ+左側にあるデータ-左側のみに存在するデータ を取得する。

SQL素人でも分かるテーブル結合(inner joinとouter join)

テンプレートの検索

コントローラーで実行されているrenderメソッドの裏側はどうなっているのかが気になった。

ActionPackActionViewの仕組みを教えてくれる記事。

Railsはどのようにテンプレートを見つけているか - Qiita

外部API連携

外部API連携をする時は、下記手順を踏む

1 APIキーを取得

2 curlを用いて通信が成功するか確認

3 取得したい情報が取れるエンドポイントを公式ページから探す

4 1日に実行できるリクエストの上限を調べる

5 外部APIに対するリクエストの実行をアシストしてくれるコードを探す(faraday,httpclient等)

6 レスポンスとして返ってきたオブジェクトを解析して、欲しい情報だけを抽出して配列に入れる

Qiita API連携

Qiita APIを触ってみる - Qiita

Slack API連携

Slack APIを使ってみよう!【Slack + Rails】 - Qiita

Rubyで外部APIにリクエストする - Qiita