53の設定をインポートするときに、aws_route53_recordのドキュメントを読んでいた。53のゾーンを作るときに自動で作られるNSレコードとSOAレコードの管理方法について記述がある。コード例にはNSレコードについての記載しかない。importとあるが、ゾーン作成時に一緒に作成されたNS/SOAレコードをインポートしたいだけのときは合わないユースケースに見えた(自分が把握できていないユースケースがあるのかもしれない)。これらのNS/SOAレコードをTerraformで管理するには、あらかじめaws_route53_record.example_nsとaws_route53_record.example_soa(名前は例)をインポートする。planで差分が出ないようにする。changed"タブと同じファイルの内容を取得する方法*1。origin/main...HEADやっていることは次と同じ。HEADたぶん実用的にはchanged-filesアクションを使えばよいが、とりあえずインラインで書きたい、なんらかの理由で外部アクションに依存したくないという時用。コントローラで例外処理しているアプリケーションが扱うドメイン特有のエラーを例外として表現する場合に、その例外をコントローラで処理するコードを書くと、ほとんどの場合でコードが読みにくくなったり、コードを変更しづらくなったりする結果となる。開発の効率が落ちたり不具合を作りやすくなったりする。具体的な問題は次のとおり。コントローラのアクションの凝集度が下がるコントローラのアクションに、たとえば複数の決済方法のエラーのような微妙に異なる種類の例外に対する処理を書くと、コントローラが肥大化し、凝集度が下がる。結果として、エラーが関わる変更を入れるときに、本来ビジネスロジックだけの変更であっても、コントローラとモデルの両方を必ず変更しなければならなくなる。関係の薄いさまざまな例外が1箇所で処理されることになり、コードが読みにくくなる。endendさらに、こういうコードは「ここで例外処理しているから今回のも追加しておくか」という心理を誘発しやすい(割れ窓)。持続的なWebアプリケーション開発は割れ窓との戦いである。spec)を書く必要がある。プレーンなクラスやいわゆるモデルなどと比較するとテストの準備が大変になるし、テストの実行速度も落ちる。異常系はとくにだが、しばしばリクエストやコンテキストを含めた複雑な事前状態を作る必要があり、読みにくいテストになる。テストがしづらいところにがんばってテストを書くことはできるが、それは問題解決になっていない。原因そもそもコントローラはHTTPのことをやるところだが、それ以上の責務を負わせているのが上述した問題の主な原因といえる。コントローラは、外から来るリクエストを受け取って、レスポンスを作って返すというのが本来の責務。HTTPに基づいてパラメータやヘッダのパース、Cookieの管理、レスポンスの生成などを実行する。コントローラはレイヤードアーキテクチャのUI層やプレゼンテーション層にあたる。これらの責務やレイヤーには、アプリケーションの中核となるビジネスロジック(アプリケーションが解決する問題領域に固有のロジック)は含まれない。ビジネスロジックはモデルで扱う。これはレイヤードアーキテクチャで言うとドメイン層やモデル層と呼ばれるところ。ビジネスロジックを実行中に処理を継続できなくなったら発生させたいエラーは本来ビジネスロジックとして処理するべきだが、このエラーがモデルを外から利用しているコントローラにまで侵食してくると、上述したような問題が発生する。本当に例外を使うべきか考えるビジネスロジックにおけるエラーは「例外」ではないはず、とまず考えたい。ユーザーが変な値を送信してきたときにそれを不正としてエラーを返すのは、例外的ではなく想定内のはず。別の側面だと、例外は制御構造から大域脱出するので、多用するとコードを読むときの負荷を高めうる。設計・コンセプト』の12章に「例外とはルーチンコールの失敗を引き起こす可能性のある実行時イベントである」とある。例外とは、ルーチン(メソッド)の実行時に最後まで期待どおり実行できない可能性がある事態の発生を表す*1。どのようなエラーを例外として表現すべきか。技術的な例外としては外部サービスとの通信の失敗や、NoMethodErrorなどの実行時エラーがある。ビジネスロジックの例外としては、データとビジネスルールのあいだの不整合などで一度開始したトランザクションを続けられない状態になったとき発生させる例外が考えられる。これらのケースを除くと、本当に例外が必要ではないケースもそれなりにある。そこで、エラーをできるだけ例外ではない方法で表現できないかを考える。ビジネスロジック実行前のデータの検証失敗時に例外を起こすのではなく、検証の実行結果を取得できるような設計にする。これは、RailsだとActiveModel::Validationをうまく使い、入力値に関するエラーは戻り値、またモデルやフォームオブジェクトの属性として取得する事になる。モデル層で適切にビジネスロジックを書くビジネスロジックに関するエラーをコントローラで処理するようになることが問題の原因だと書いた。Recordのモデル(つまり、アクティブレコードパターンに基づいたDBのテーブルに対応しているクラス)だけではなく、必要に応じてふつうのクラスを作るようにする。そのなかでエラー処理をやる。(ActiveModel::Model)を使ってもよい。このようなクラスをうまく作るためには、リソースだけではなくアプリケーションにおけるイベントもモデルとして抽出したり、ユースケースを見出してクラスにする必要がある。この話題については、非常にわかりやすくまとまっている次の文献を参照されたい。Deckトランザクションを張る場合は、例外を発生させることでトランザクションをロールバックする形になる。このケースにも対応するための案としては、次のようにビジネスロジックの一部としてロールバックと例外処理を実行し、このモデルを使う側からは実行結果だけが取得できるよう方法がある。これができると、コントローラは薄くなり、scaffoldしたときの構造に近くなる。endendDBと通信できないなどの技術的な例外はそもそもプログラムの実行を続けられないはずなので、ここで処理せず呼び出し元まで例外を突き抜けさせるのがよい。404、500などのエラーにしたいときはコントローラより上の層で例外処理する必要があるのでは?利用しているフレームワークにもよるが、404や500などの一般的、技術的エラーはアプリケーション共通の処理を定義していることが多いので、そういうケースで例外を発生させるのは問題なさそうに思う。/foos/:foo_id/bars/:bar_idのようにパスパラメータとしてIDが入るリソース設計にすると、fooとbarは最初にコントローラでDBから探すそれらのレコードが見つかったら、そこからビジネスロジックに処理を依頼するという流れになる。このときは、fooかbarがなければ、コントローラで例外処理をすることになる。09:46Tweetもっと読むコメントを書く2022-09-23Macのセットアップでやること2022Mac新しくMacBookをセットアップする機会があった。開発環境はdotfilesである程度作れるようにしているが、macOSについてはいつもの設定を覚えておくしかない状態だったのでメモを残しておく。書いているのはデフォルトから変更している箇所だけ。後述するがOSの言語を英語に設定しているので設定名も英語で書く。languagesEnglish、日本語の順番。画面1枚で仕事するので、次の記事の手法を参考にしている。開発dotfilesのセットアップスクリプト実行で自動化できていないものがある。Elementsを使っていた(左Commandキーで英語、右Commandキーで日本語に切り替え)。Elements依存をなくせるのではないかと思い、OSの機能だけを使ってControlキーで入力ソースをトグルする運用に切り替えてみた。両方のCommandキーをそれぞれ英語と日本語に割り当てると、入力ソースの状態を意識する必要がなくなるという利点がある。一方でCommandキーはキーバインドで多用されるので、文字を入力しながら入力ソースを切り替えるつもりが、誤ってキーバインドを発動させてしまうという問題がよく起きていた。Controlキーの運用は全然しっくりきてないがしばらく使ってみる。作業をやっていたときに知ったことについて書いておく。...なぜか外部キーを持つテーブルのスキーマを変更するためにpt-oscを使うと、自動で外部キーの名前が変更されるから。pt-oscはスキーマに変更を加えるテーブル(旧テーブルと呼ぶ)に対して、スキーマを変更済みの新テーブルを新しく作り、トリガーを使って旧テーブルから新テーブルへレコードをコピーする。旧テーブルが外部キーを持つなら、新テーブルも同じ外部キーを持つことになる。MySQLでは、外部キーなどの制約の名前はデータベース内で一意でなければならない1。pt-oscで新テーブルを作るときにそのまま外部キーをコピーしてしまうと、この決まりを守れない。そこで、外部キーを持つテーブルのスキーマをpt-oscで変更しようとすると、外部キーの変更有無に関わらず、外部キー名を変更するようになっている。pt-oscは外部キー名の先頭にアンダースコアを付与したものを新テーブルの外部キー名とする。この方式で外部キーを持つテーブルのスキーマを繰り返し変更するとアンダースコアが増えていってしまう2。そこで、アンダースコアは2個を上限として、さらにスキーマを変更するとアンダースコアなしに戻るようになっている3。よって、pt-oscで外部キーを削除するときは、新テーブルを作成したあと--alterに渡されたオプションをもとに外部キーをDROPするので、新テーブルでの外部キー名を指定する必要がある。引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。