2023年振り返り

仕事

  • 2022年1月に転職して、丸2年働いた
  • 転職してからRuby/Railsを使うようになってきて、今年やっと自分のなかで自然なものになってきた感覚
    • 一方でPHPのことは忘れてはないけど、書かなくなったので分からなくなってきた
  • この2年は新しい機能の開発というより、基盤整備や技術負債の解消に当てる時間が多かった気がする
    • 進め方に戸惑うことが多かった昨年と比べて、今ではどう進めるとスムーズかが分かってきた
    • GitHub上で年間3,500弱だったみたい、転職前がどうだったか知りたいなぁ…

プライベート

  • 2月のフルマラソンで完走できなかった(悔しい)
    • 当日の大雨でコンディション最悪
    • コースの高低差が想像以上でしんどいの一言に尽きる、初見殺し
    • 来年にリベンジエントリーしたので練習中

(気が向いたら追記する)

転職活動メモ

概要

  • 転職活動をして、無事に次に働く会社が決まったので、転職活動の各フェーズにおいての反省点・改善点や不満などをメモ書き

事前にやったこと

  • 履歴書の作成
    • WEB上で作成できるサービスを利用した
  • 職務履歴書の更新
    • Google document で管理していたので、前職分を書き足した
  • 転職エージェント登録
    • オンラインでのヒアリングの時間も1時間ほど確保
  • 転職系サービスの情報更新
    • 前職分の業務経験、利用技術などの更新
  • 退職理由や転職時に求めたいことを洗い出し
    • 面接で必ず聞かれることだと思ったので、まずは思うがままに洗い出した。そして口頭で話すために情報を整理。

カジュアル面談 〜 エントリー

  • 間口を広くしすぎて(転職系サービスを最大5〜6利用)どこの会社はどこ経由だったかとか、連絡のやり取りの方法が変わってしまったので、かなり大変だった
  • エージェント経由だと、エントリー後の書類審査等にかなりの時間を要す場合もあり、だいぶストレスだった。2週間〜1ヶ月超も待った企業もある。担当の方によると催促してもレスがないらしい。
  • 最初はめちゃくちゃ連絡くれて色々と紹介してくれたけど、すぐにフェードアウトしていったエージェントさんもいた…
  • 居住地を記載しているにも関わらず、東京本社に週数回の出社が必要な会社からスカウトメッセージが来ること多数
    • 居住地を書くこと以外に何か回避する術はないのか?と考えていたけど、結局分からなかった。
  • 経験のある技術を記載しているにも関わらず、経験のない技術ばかりのポジションでのスカウトメッセージも多数
    • 「経験のない技術が多くキャッチアップ前提ですが、問題ないですか?」と回答したら、だいたいお断りされたのだが、これも回避法を知りたかった。
  • エントリーする企業ごとに技術課題を行うのは、だいぶ大変だった。
    • オンラインの技術試験サービスやコードのファイルを提出する形で、各企業によって色々とやり方があった。オンラインの技術試験サービスを利用している企業だと、全く同じ問題に当たることもある。(今回は3回あった)
    • 普通に頑張っても1週間程度かかりそうな課題を出す企業もあり、そこはさすがにエントリーできなかった。(めちゃくちゃ志望度が高いならまだしも)
      • 仕事と並行して転職活動するならアリ。しかし転職活動一本みたいな状態だと、1社にかけられる熱量はそこまで高められない。

面接

  • 物理的に先方企業に行く必要がなくリラックスして臨むことができたとはいえ、緊張しいなのでそれでもだいぶガチガチだった
    • モニターに事前にメモしたものを映しておいて、それを見ながら話すことができたからだいぶマシだった(オフラインだとこれができない)
  • 自分も先方も、端末が落ちることがあった。
    • ブラウザでタブを開きすぎたか。IDEを画面共有したときの死亡率はかなり高め。
  • どうしても聞き取りにくい場面がある
    • 双方の環境の問題もあるので難しい。自分は改善するしかないが…
  • 自分の映像が割と暗かったかもしれない
    • デスクにライトを設けているが、それでも改善はなかなか難しかった。冬で太陽光が入りにくかったからかも。Youtuberとかが使用している機材を使った方が良い気がした。

その他

  • ポジションのミスマッチ
    • メンバーポジションでカジュアル面談〜面接をしていたはずなのに、実はリードポジションでしたってことがあった。
      • カジュアル面談時にしっかり確認しようと思った。
  • 働き方のミスマッチ
    • フルリモートなのか、物理的な出社が必要なのか、このご時世だし各媒体さんには募集要項に枠を設けてほしいって思った。

dataProviderではCarbon::setTestNowをしてはいけない

概要

タイトル通り。

他のテストクラスに影響を与えてしまう。

ざっくりと詳細

今までテストクラスを一つずつ読み込んで実行してくれているものだと思っていたが、実はそうでなく、

全てのテストクラスとdataProviderを読み込んでから、テストメソッドが実行されている感じだった。(そこそこのPJでテストクラスが大量にある想定)

つまり、 Carbon::setTestNow('2020-07-01 00:00:00'); と書いたら、後続で読み込まれたdataProviderで、Carbon::now() とすると 2020-07-01 00:00:00 で取得できる。

どうする

特定の日付でデータを作っておきたい場合、固定の日付で入れておけばよいけど、それだと少し手間。

日付に変更を入れたいときにも手間がかかる

public function testProvider()
{
    Carbon::setTestNow('2020-07-01 00:00:00');
    $now = Carbon::now();

↑こうしてしまいがちだけど、

public function testProvider()
{
    $now = Carbon::now('2020-07-01 00:00:00');

素直にこうしたら解決した。

Carbon の diffInDays の仕様を理解していなかった

$a = new Carbon('2020-05-11 12:00:00');
$b = new Carbon('2020-05-12 00:00:00');

$a->diffInDays($b); // 1が返ってくると期待していたが、0が返ってくる。

$c = new Carbon('2020-05-12 12:00:00');
$a->diffInDays($c); // 1が返ってくる

$d = new Carbon('2020-05-12 11:59:59');
$a->diffInDays($d); // 実際には試してないがおそらく0が返ってくる

コードも読んでないし、詳細に検証もしてないけど、おそらく

🙅‍♂️ 単純な日にちの差分

🙆‍♂️ 24時間単位での日数計算

否定のor と andの否定

否定のor

if(!$a || $b !== $c) {
    // 
}

andの否定

if(!($a && $b === $c)) {
    // 
}

勝手に名前を付けているが、どちらが可読性が高いのかという疑問。

宗教論争的な話になると思うから、深くは考察しないけど、個人的には前者。

理由としては

  • and は 全ての条件を見る必要があり、否定の条件を加えるスタックが読んでて精神的に辛い

  • or は否定が入ってても、一つずつ脳内で処理できるから、精神的に楽

※リーダブルコード的には後者が良しとされているのかな?

MigrationとFactoryを別のディレクトリから読み込む

概要

現在、1つのDBの対して、4つのアプリケーション(すべてLaravel5)が稼働しているシステムに関わっており、そのMigrationとFactoryを共通モジュールとして利用できるようにした。

パッケージ開発

細かいところは公式ドキュメントを。

laravel.com

Migration

AppServiceProvider にて以下の記述

loadMigrationsFrom という便利なものが標準搭載されている。

public function boot()
{
    $this->loadMigrationsFrom(__DIR__ . '/path/to/migrations');
}

Factory

Migrationに続き、loadFactoriesFrom があるかなーと思って探したけどなかった。

AppServiceProvider にて以下の記述

public function register()
{
    $this->app->make('Illuminate\Database\Eloquent\Factory')->load(__DIR__ . '/path/to/factories');
}

Laravelの「max」ルール (sizeの処理を追ってみた)

はじめに

tkfric.hatenablog.com

以前書いたような記事に似た内容

概要

公式のドキュメントでは

readouble.com

max:値

フィールドが最大値として指定された値以下であることをバリデートします。sizeルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。


size:値

フィールドは指定された値と同じサイズであることをバリデートします。文字列の場合、値は文字長です。数値項目の場合、値は整数値です。配列の場合、値は配列の個数(count)です。ファイルの場合、値はキロバイトのサイズです。


こういう形で書かれているが、

'item_number' => 'max:10'

って書いても、数量10個のバリデーションではなく、文字長10文字のバリデーションになってしまったために本件に至る

Maxのバリデーション処理を読む

/**
 * Validate the size of an attribute is less than a maximum value.
 *
 * @param  string  $attribute
 * @param  mixed   $value
 * @param  array   $parameters
 * @return bool
 */
public function validateMax($attribute, $value, $parameters)
{
    $this->requireParameterCount(1, $parameters, 'max');

    if ($value instanceof UploadedFile && ! $value->isValid()) {
        return false;
    }

    return $this->getSize($attribute, $value) <= $parameters[0];
}

となっており、条件はあるが、size ルールを見ていることが分かった(ドキュメント通り)

Sizeのバリデーション処理を読む

/**
 * Get the size of an attribute.
 *
 * @param  string  $attribute
 * @param  mixed   $value
 * @return mixed
 */
protected function getSize($attribute, $value)
{
    $hasNumeric = $this->hasRule($attribute, $this->numericRules);

    // This method will determine if the attribute is a number, string, or file and
    // return the proper size accordingly. If it is a number, then number itself
    // is the size. If it is a file, we take kilobytes, and for a string the
    // entire length of the string will be considered the attribute size.
    if (is_numeric($value) && $hasNumeric) {
        return $value;
    } elseif (is_array($value)) {
        return count($value);
    } elseif ($value instanceof File) {
        return $value->getSize() / 1024;
    }

    return mb_strlen($value);
}

見ての通りで、数値でのmax判定をするためには条件があり、

maxとは別にLaravelが定義するnumericRuleを持っていることが必要な模様。

/**
 * The numeric related validation rules.
 *
 * @var array
 */
protected $numericRules = ['Numeric', 'Integer'];

とのことなので、numericinteger かを一緒に定義してあげれば良さそう

最後に

公式のドキュメントが少し不親切だなと思った