エンジニアのひよこ_level10

毎日更新してた人。たまに記事書きます。

docker-composeで/etc/hostsを書き換える方法【504日目】

コンテナ間で通信をさせたい

nginxや、php-fpmの連携や、
seleniumなどのブラウザアクセスのために、
それぞれの /etc/hostsを書き換えたい。

2つの方法があります。

extra_hosts

任意の名前と任意のipで/etc/hostsを書き換える

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

このように、ipに対して、任意の名前を書くことができる。

links

任意の名前と任意のコンテナで/etc/hostsを書き換える

extra_hosts:
 - "somehost"
 - "otherhost:renamedhost"

このとき、somehostに割り当てられたipアドレスを自動的に紐づけてくれる。

さらに、otherhostでアクセスするのは嫌だ、別な名前にしたいってときは :でつなぐことで、別な名前になる。
この設定によって、 https://renamedhostと書けば、otherhostのサービスにアクセスすることができる。

ちなみに、同一のdocker-compose.yml内であれば、コンテナ名でaliasが既に張られている。その名前を変える時にこのリネームは便利。

if文でもエラーの握りつぶし、やってませんか?【503日目】

エラー握りつぶしって?

try {
    $value = $array[$key];
} catch (Exception $e) {
    $value = 1;
}

この時、$keyは、普通のユーザーの入力ではありえない値を取る時、
本来はエラーを出してほしいです。

例えば、バグやサーバーが壊れているときにExceptionが投げられると思います。

もし、そうしなかった場合・・・バグが起こっているのに、全く気が付かない。
苦しいですよ・・・一度味わうとエラー握りつぶしは二度としたくないって思います。

if文でエラー握りつぶし?

if ($key === self::TYPE_A) {
    $value = $array[$key];
} elseif ($key === self::TYPE_B) {
    $value = $array[$key] + 1;
} else {
    $value = 1;
}

Exceptionに限らず、
$keyがユーザー入力ではありえないことが起こっていたら、これも実質エラー握りつぶしとも言えると思います

バグやサーバーが壊れているときに、気づけないのは同じですから・・・

if else文を書く時にも、これはエラー握りつぶしてないか?バグ起こっても気づけるか?
その意識を少しするだけでも、後の自分の負担が軽くなります!

余談:エラーをどうしても出してほしくない

例外を出すべき時に、Exceptionがどうしても起こってほしくない。
それなら、せめて、ログを・・・ってことで、こんな感じに。

try {
    $value = $array[$key];
} catch (Exception $e) {
    Log::error($e . 'DBやばいことなってるかも');
    $value = 1;
}

これで、一応エラーの検知は出来ますね。

さらに余談:エラーログ出力攻撃

上の例で、Exceptionを投げる時ですが、
$keyは『ユーザーが想定している正しい値以外を行った時』という観点だと、
『エラーログ出力攻撃』みたいなことが起こってしまうかもしれません。

例えば、ブラウザをいじって送信した時や、curlなどで任意の値を渡すなど、
わざと想定外の値を送ることも、ユーザーは可能です。

その、わざと想定外の値に対してExceptionを投げてログを残そうとすると、
ユーザーがとにかくエラーを起こす送信を何回も投げることで、
ログがたくさん・・・どこにほしいログがあるかとかわからなくなったり、
メール送信とかしてたら負荷がかかったりとか、いろいろ辛いことに(´;ω;`)

なので、バグやデータベースがおかしい時にログを残す必要は間違いなくありますが、
それ以外の場合は、ログを残すべきか慎重に考えましょう。

こういったエラーの設計は、ベストプラクティスとかを知らないので、
ご存知の方いらっしゃいましたら、教えていただきたいです。
それまでは、アンチパターンをたくさん覚えて、備えるようにしましょう・・・!

【Laravel】valueRetrieverで、第一引数がcallbackでも文字列でも使える関数生成【502日目】

Laravelの関数見たら疑問を持ちました

    $sorted_user = $users->sortBy('sort_number');

    $sorted_user2 = $users->sortBy(function ($user) {
        return $user->sort_number;
    });

    dd($sorted_user == $sorted_user2); //true

あれ?なんで、第一引数が、文字列だったりcallback関数だったり、
どちらでも動いているのだろう?

元コードを読んだらこれでした。

文字列を関数化

valueRetrieverという関数が内部で使われていました。

    /**
     * Get a value retrieving callback.
     *
     * @param  string  $value
     * @return callable
     */
    protected function valueRetriever($value)
    {
        if ($this->useAsCallable($value)) {
            return $value;
        }

        return function ($item) use ($value) {
            return data_get($item, $value);
        };
    }

最初の例だと、$valueが無名関数と文字列どっちも入るのですが、
無名関数ならuseAsCallableがtrueでそのままreturn。

もし文字列なら、その下で無名関数に変換してからreturnしてくれているのです。

なるほど、こうやって変換すれば、型変換だけでは足りない変換にも対応できるのですね。

勉強になりますLaravelさんφ(..)メモメモ

【Laravel】dataProviderでヘルパ関数を使う方法【501日目】

テストコードでdataProviderを使いたい

テストコードを書いているときに、dataProviderを使うことで、
テストパターンをシンプルに作りたい。

dataProviderでヘルパ関数が使えない

public function XxxDataProvider() {
    return [
        'value' => factory(User::class);
    ];
}

こんな感じに、ヘルパ関数が使えないー

createApplication

Laravelのプログラムを動かすには、一度createApplicationを書く必要がある。

public function XxxDataProvider() {
    $this->createApplication();
    return [
        'value' => factory(User::class);
    ];
}

これで書ける。

でも、毎回書くのは残念なので

__construct()に書く

__construct()内に、createApplicationを書くことにより、
該当テストクラスにおいては、ヘルパ関数が問題なく書けます。

ヘルパ関数の使用頻度に合わせて、どちらに書くか選びましょう!

500日ブログ書いてやれたこと、感想【500日目】

500日ブログ書きました

ブログ書ききりました。500日目ですやったー!

実は、このブログは500日で終了予定でした。

予定でした。

ってことで続きます(‘ω‘ )

なんでやめようとしてた?

技術ブログ以外の挑戦に移ろうかなーって思ってたのと、
一回やめたらどうなるんだろーって思ってました。

ただ、思ったよりブログ見てくださってる方がいて、
twitterや、Conferenceで直接あった人から、
ブログ見てました、助かってました、そんな話聞いたら。

これやめたら私戻ってこれない!
そしてそのリスクは私は負いたくない!

ってことで続けることにしました(‘ω‘ )
ここまでいろいろ続けてると、やめることがもはやリスクなのです。

500日どうだった?

ブログを書き続けて、いろいろ自信が持てたのは良かったですね!

サポーターズColabで登壇は間違いなくできなかったですし、
Laravelコントリビュートも、もしかしたら勉強ここまでしなくて、できなかったかも。
そしてアウトプットと挑戦大切なのがわからなかったら、Laravel JP Conferenceに登壇しようとも思わなかったかもですね。

これからどうしたい?

なんで500日で振り返るか。

そう、次に目指すは1000日です!!!

社会人4年目にその頃にはなってるでしょう。果たして続いてるのか。

となると、ちょうど折り返しのタイミングで決意を新たにするのが良いと思って、このブログを書いています。

ってことで、1000日までは続けるぞー!負けないー!

最後に雑談。

Laravel JP Conferenceでの写真が公開されましたね。

緊張してたのが写真でめっちゃ伝わるぅ。

登壇前の写真がいい感じだったので、facebookプロフィール画像に。
これからスライドとか作成するときに使えそうこれ(‘ω‘ )!

こういうのも、いろいろ挑戦したから得られたものだよなーってことでほっくほっく。

いろいろ挑戦するためにも、いろいろ積み重ねよう頑張ろうって思った今日でした!

それでは、これからもういろうをどうぞよろしくお願いいたします!

【一週間振り返り】カンファレンスやりきった+引っ越しの一週間【499日目】

1.今週一週間の感想(ざっくり)

カンファレンスをきっかけに行動したのを完遂。そして引っ越しの作業・・・

2.良かったこと

  1. 引っ越しについて進めれた

  2. 登壇のブログ書ききれた

  3. 初心者エンジニア向けのslack作れた

3.もっとこうしたかったこと

また契約が上手く進められなくて、要らない解約金を支払うはめに・・・

4.新しく気づいたこと

あれ?って思ったらとりあえずすぐに質問しよう・・・だいたいおかしい。

5.来週したいこと

引っ越し完遂している・・・はず。

6.その他

引っ越し頑張るぅぅぅ

【php】イミュータブルなクラスのフィードバック対応をしてみる【498日目】

昨日こんな記事書きました

www.nyamucoro.com

これで、イミュータブルっぽいクラスを作りました。

で、最初にフィードバックをもらった方に、あの記事を見てもらったら、こんな記事をおすすめしていただきました。

参考記事

qiita.com

qiita.com

あれー?昨日の記事よりわかりやすくて、内容が入ってるよー\(^o^)/

さすがsuinさんですね……!

実装書き換えてみる

class User {
    private $name;
    private $status;

    public function __construct(string $name, Status $status) {
        $this->name = $name;
        $this->status = clone $status;
    }

    public function setStatus(Status $status) {
        $new_instance = clone $this;
        $new_instance->status = clone $status;
        return $new_instance;
    }

    public function setName(string $name) {
        $new_instance = clone $this;
        $new_instance->name = $name;
        return $new_instance;
    }
}

疑問

privateなフィールドなのに、なんでcloneで別インスタンス作ったのに、フィールド値が書き換えられるの……?

PHP: オブジェクトのクローン作成 - Manual

PHP 7.0.0 以降では、新しくクローンしたオブジェクトのメンバーに、作成したその式の中でもアクセスできるようになりました。

し、しらなかったー!!!

ってことで、無事にいい感じのイミュータブルっぽいクラスが出来上がりましたねたぶん!やったー!

【PHP】イミュータブルなクラスを作ってみる【497日目】

始まりは突然に。

昨日のブログにツッコミが入りました(‘ω‘ )

なるほどたしかに!
changeStatusというフィールド値をUserに持たせたほうが、Userのフィールド値とか状態に触れる知識を外部に持たせないって出来ますね。
状態に対する関心も、あちこちに分散しない……!

ってことで、頂いたアドバイスを自分なりに解釈して実装してみる。
(で、出来たらちょっとレビューをお願いしてみる・・・!)

頂いたアドバイス

実装

class User {
    private $name;
    private $status;

    public function __construct(string $name, int $status) {
        $this->name = $name;
        $this->status = $status;
    }

    public function __set($name, $value) {
        throw new Exception('This object can't be set field value.');
    }

    public function setStatus(int $status) {
        return new User($this->name, $status);
    }

    public function setName(string $name) {
        return new User($name, $this->status);
    }
}

応用

フィールド値にインスタンスを持つ場合。
前に勉強したやつ実装してみる。

【デザパタ自作】イミュータブルパターン(インスタンス内包対応)【266日目】 - エンジニアのひよこ_level10

class User {
    private $name;
    private $status;

    public function __construct(string $name, Status $status) {
        $this->name = $name;
        $this->status = clone $status;
    }

    public function __set($name, $value) {
        throw new Exception('This object can't be set field value.');
    }

    public function setStatus(Status $status) {
        return new User($this->name, clone $status);
    }

    public function setName(string $name) {
        return new User($name, clone $this->status);
    }
}

感想?

こんな感じ・・・?
これで、たぶん値の変更は不可能になって、データは新しいオブジェクトを返すようになっているはず・・・?

使用感としても、ユーザーは内部に何を持ってるかを意識せず、関数だけ意識できる気がする。

// 全部違うインスタンスになる。たぶん変更出来ないはず
$user = new User('youkan', new Status(false));
$user = $user->setName('Uiro');
$user = $user->setStatus(new Status(true));

Tell Don't Askの観点とか知らない言葉が出てきてるので、いつか勉強したいというか、
早くぺちおぶ行きたいのに、Laravel JP Conferenceとかイベントに被るから行けなかった・・・(登壇者だからどうあがいても行けなかった)

また今度こそ、行きたいね・・・!