Ghost Inspector 動的に年を取得(年を跨いでも大丈夫)

システムの動作テストにGhostInspectorを活用しています。
自動でテストしてくれるのは非常に便利ですね。

そのGhostInspectorで自動テストしていたのですが、年を決め打ちしていると年月が経ってその決め打ちした年ではうまくテストできなくなるということが起こりました。
決め打ちしている値を変更することでも対応はできるのですが、また年月が経ったときにテストがうまくいかなくなってしまいます。

そこで、動的に年を取得するよう修正を加えました。
これでいつまでも安心してテストし続けることができます。

ユニットテストメモ(概要や注意点など)

ユニットテストをつくってみて、注意点など忘れそうなのでメモにまとめました。
どこまでテストをつくるかは難しいですが、必要な箇所をチームメンバーと確認して漏れがないようにカバーしておくべきかと思います。

〇ユニットテストについて
範囲を絞った状態の自動化されたテストをつくることでコード上の欠陥をみつけることができます。
・1つのテストに1つのアサーションをして、どこの部分がダメかわかるようにする。(テストの失敗の原因を分かりやすくする)

OCでは、UnitTestsとIntegratedTestsの2つの自動化されたテストがあります。

<UnitTests>
メソッドのテストのみを行う。
→クラスのメソッドに引数を渡して期待通りの処理をするかなど

・基本的には、getterやsetter以外のpublicメソッドは全てテストをつくる。

・privateメソッドのテストについては、重要なものであればテストつくったほうがよい。

・別クラスなどからメソッドが呼び出されている場合は、そのメソッド自体と呼び出し元のメソッドの両方ともテストをつくる。
例)以下の場合であれば、saveDriverStatusもinsertStatusDBもupdateLastDriverStatusもテストを作る。

public function saveDriverStatus($status){

 $isSuccess = $this->insertStatusDB($status);

 if($isSuccess){

  $this->updateLastDriverStatus($status);

 }

}

<IntegratedTests>
大きな機能そのものを一連の流れを通してテストします。
→1つの大きな機能を最初から最後まで実行して問題なく機能するか(シナリオテストも含む?)
→複数のメソッドまたはクラスを組み合わせても問題ないかなども確認する
→範囲の大きい他ファイルを実行するようなテストにしてしまうとどこで欠陥が発生しているか分かりづらいので、範囲を作成した機能部分のみにするなど対象範囲を広げすぎないようなテストにする

・機能の設定でON/OFFなどの条件があるものは、それぞれの条件でのテストをつくる
例)「配送先が近くにある場合でも停滞検知するか」という設定項目がある場合→設定ONでのテストと設定OFFでのテストをそれぞれ作成

「なぜ,あなたはJavaでオブジェクト指向開発ができないのか」を読みました。


オブジェクト指向をより理解するために「なぜ,あなたはJavaでオブジェクト指向開発ができないのか」という本を読みました。
メモ程度の内容ですが、まとめたので共有します~

〇感想
なぜオブジェクト指向で書くかという部分への理解が深まりました。オブジェクト指向でコードを書く目的を理解した上でのプログラミングがよりできると思います。
オブジェクト指向が何かという前に、どういう考えのもとでオブジェクト指向プログラミングをするかというのは重要ですね。
(じゃんけんやカードゲームに例えたらどういう役割なのかとか、非オブジェクトとの比べたときのメリットとか)

<1章>
プログラミングの手順
①コンピュータに行わせたいことを理解する
②理解したことを説明できるレベルまで整理する
③コンピュータに分かる言葉に翻訳する

<2章>
オブジェクト指向って本当に必要なのかについて
プログラミングにおいて最も難しいのは、一度作ったソフトウェアに対して変更や機能追加をしていくこと。
ex) 名前を付与する、数を増やす、仕様を追加する

非オブジェクト指向だと拡張が大変になる!
→拡張性をよくする、変更を素早く、簡単にする

拡張性については、非オブジェクト指向で開発したときに不足している点だと感じました。また、ただオブジェクト指向で開発するのではなく、拡張性を意識した上で開発するとまた開発内容が変わってくるのかなと思います。

<3章>
オブジェクト指向=人間の理解をできるだけ分かりやすくコンピュータに伝える方法
役割分担を明確にするということがオブジェクト指向による考え方の第一歩
役割=クラス担当者=インスタンス(オブジェクト)

属性とは、インスタンス固有の性質(人であれば、それぞれの名前やジャンケンに勝った回数など)
各クラスでそれぞれの対象の属性(性質)を管理させる

カプセル化
→処理が保護される
→外部から見て、どのような処理内容かを気にする必要がなくなる

アクセス修飾子・・・どこからアクセス可能であるかを決める(private, publicなど)

コンストラクタの特徴
インスタンスが生成されたときに自動で呼び出される。
メソッド名がクラス名と同じ
戻り値を返せない

JavaDoc→Javaでドキュメントを自動生成できる

オブジェクト・・・互いにメッセージを送り合うことによってシステムを構成
クラス・・・オブジェクトの役割(属性(フィールド)と操作(メソッド))を定義
属性・・・オブジェクトが固有に持つ性質(例、名前)
操作・・・メッセージをきっかけとしたオブジェクトの振る舞い(メソッド)
インスタンス・・・クラスという役割に対する実態(「プレイヤー」という役割(クラス)に対する「山田さん」という登場人物(インスタンス))

各単語の意味などは分かっているつもりでしたが、誰かに説明しようとするとなかなか難しいものだと思います。積極的に業務中に使っていきたいと思います。

<4章>
クラスの継承
・多くの共通部分と少しの異なる部分がある
・外から見れば同じ扱いだが、中から見れば別の扱いをする

メソッドの上書き・・・オーバーライド

継承したクラス・・・サブクラス
継承元のクラス・・・スーパークラス

<5章>
インタフェース・・・仲立ち、オブジェクトへの操作方法とそれに対応する振る舞いの組み合わせを規定

インタフェースを実装する(implement)
自動車であれば、インタフェースは「右側のペダルを踏むとアクセル、左側を踏むとブレーキ」のような操作と振る舞いになる。

大規模になる場合は、インタフェースで実装することで変更を加える手間が少なく済む。

インタフェースも使いどころを考えながら利用していければと思います。これも拡張性など考慮すると使ったほうがいい場面がある気がしますね。あとは、実際に拡張することを考えると初めにどのようにインタフェースを定義するかも重要に思います。

<6章>
モデリング手順
1仕様を決める
2クラスを抽出
3オブジェクト間のメッセージを考える
4各クラスの操作を洗い出す
5各クラスの属性を洗い出す

モデリングとは、「物事を本質をできるだけシンプルに表現すること」。
モデリングに正解はない。
行きつ戻りつしながらよりよいモデルを練っていくしかない。

ユースケース・・・ユーザがどのように利用するかというシナリオを文章として記述
名詞抽出法・・・概要説明などを書いてみて、その中から名詞を抽出して、その名詞からクラスを選定。
シーケンス図・・・オブジェクト同士による操作の呼び出し関係を図にしたもの
UML・・・統合モデリング言語(Unified Modeling Language)

『モデリングに正解はない』という部分が大事かと思いました。どうクラスの操作や属性を決めるかは悩むポイントですが、やっていく中で改善していければと思います。

存在チェックのSQL処理速度比較メモ

存在チェック(該当データがあるのか)の処理について忘れがちなのでメモします。
SQLの内容それぞれに対して、ローカル環境ですが、クエリの実行時間を調べてみました。
結論から言うと、SELECT EXISTS( SELECT * FROM ○○ WHERE ××)のような書き方が速いですね。


SELECT
                *
            FROM
                driver_status    
	        WHERE
                driver_id = 1678
            AND
                created
            BETWEEN 
                "2021-07-18 12:27:25" AND "2021-07-18 15:27:25"

まず、WHERE句を含んだSELECT文です。カラムは全てのカラムが対象です。
クエリの実行時間: 0.0054 秒

  SELECT
                id
            FROM
                driver_status    
	        WHERE
                driver_id = 1678
            AND
                created
            BETWEEN 
                "2021-07-18 12:27:25" AND "2021-07-18 15:27:25"

次に、 上と同じくWHERE句を含んだSELECT文ですが、こちらはカラムがidのみ対象です。
クエリの実行時間: 0.0044 秒

    SELECT
                *
            FROM
                driver_status    
	        WHERE
                driver_id = 1678
            AND
                created
            BETWEEN 
                "2021-07-18 12:27:25" AND "2021-07-18 15:27:25"
	    LIMIT 1

さっきのカラム全選択にLIMIT 1を付けたもの。
クエリの実行時間: 0.0009 秒

  SELECT
                id
            FROM
                driver_status    
	        WHERE
                driver_id = 1678
            AND
                created
            BETWEEN 
                "2021-07-18 12:27:25" AND "2021-07-18 15:27:25"
	    LIMIT 1

カラムidのみでLIMIT 1。
クエリの実行時間: 0.0007 秒

SELECT EXISTS (SELECT
                id
            FROM
                driver_status    
	        WHERE
                driver_id = 1678
            AND
                created
            BETWEEN 
                "2021-07-18 12:27:25" AND "2021-07-18 15:27:25")

SELECT EXISTS( SELECT ~ ) でカラムにidを指定。
クエリの実行時間: 0.0009 秒

SELECT EXISTS (SELECT
                *
            FROM
                driver_status    
	        WHERE
                driver_id = 1678
            AND
                created
            BETWEEN 
                "2021-07-18 12:27:25" AND "2021-07-18 15:27:25")

SELECT EXISTS( SELECT ~ ) でカラムは全て。カラムは選択しないで全て取ってきた方がSELECT EXISTS( SELECT~)だと速いらしいです。
クエリの実行時間: 0.0003 秒