投稿

文字列が適切か考える

はじめに 初心者向けです。 初心者にありがちなことと、TSに入りたてでありがちなことを書きました。 文字列が適切でない選択である可能性を意識する 文字列使いがち問題 自分が以前見かけたコードに下記のようなものがありました。 Next.js にも例としてこのようなコードが載っています(このコード自体は問題ないです)。 < Link href = " /about " > < a > About </ a > </ Link > このコード単体で見ると、問題ないですが、この書き方をそのままプロダクションでも行われるとすぐに面倒なことになります。 自分が問題視しているのは、 /about の部分です。 自分が見たコードは、全て(どこでも)hrefの中身が文字列で書かれていました。そのため、タイポっていても実行時にしかわからず(どの部分でも実際にリンク踏むまで正しいかわからない)、再利用性はなく、TypeScriptを利用しているにも関わらず、型の恩恵も受けられない部分になっていました。 本来は、 下記のようにパスを定義しておき、 const aboutPath = ( ) => '/about' 下記のように定義したパスを使うなどすべきです。 <Link href={aboutPath()}><a>About</a></Link> こうすることにより、型の恩恵を受けられ、タイポすることもなくなります。 * 前提として(当然ながら)リンクはどこからでも使われるというのがあります。一箇所でしか使わないならそのまま文字列を直接使っても良いかもしれませんが、整合性の観点からは全て、関数や定数にすべきだと思います(特にパスの場合は、idなどを埋め込むことになると思うので関数にすべき)。 string型使いがち 使用するものが決まっている場合には、enumを使うべき(TypeScriptならunion typeでも一応可) // enum版 enum Color { red = 'red' , green = 'gleen' , blue =

開放閉鎖原則についてのまとめ

はじめに 対象読者は初心者です。 開放閉鎖原則とは 定義 Robert C.Martinの著書「アジャイルソフトウェア開発の奥義」では、 ソフトウェアの構成要素(クラス、モジュール、関数など)は拡張に対して開いていて、修正に対して閉じていなければならない と説明されています。 「拡張に対して開いている」とは、雑に言い換えると「機能追加がしやすい」です。 「修正に対して閉じている」とは、雑に言い換えると「変更が他の場所に影響を及ぼさない」です。 厳密ではないけどわかりやすいであろう言い方としては、「クラスや関数は機能追加しやすく、変更が他の場所に影響を及ぼさない作りになっているべき」です。 例 開放閉鎖原則の具体例として、自分が考えたものは、くじ引きです。 一般くじとプレミアムくじというものがあり、それぞれが違う抽選ロジックを持っているとします。 開放閉鎖原則に従って実装したくじ引きのコードは、下記のようになります(インターフェース(publicなメソッド)部分が重要なので細かい部分は除いています)。 class GeneralLotteryLogic # 一般くじの抽選ロジック def initialize ( params ) @params = params end def exec # 抽選ロジックの実装がある end end class PremiumLotteryLogic # プレミアムくじの抽選ロジック def initialize ( params ) @params = params end def exec # プレミアム抽選ロジックの実装がある end end class Lottery # 実際にくじ引きを行うクラス def initialize ( logic ) @logic = logic end def draw ( count ) raise ArgumentError . new ( 'count must be positive integer' ) if count <= 0 A

単一責任の原則についてのまとめ

はじめに 対象読者は初心者です。 個人的にいくつかの書籍を読んで、内容や自分の考えをまとめたものです。 単一責任の原則とは Robert C.Martinの著書「アジャイルソフトウェア開発の奥義」では、 クラスを変更する理由が複数存在してはならない と説明されていました。 一方で、比較的最近の彼の著書である「クリーンアーキテクチャ」では、 「モジュール 1 はたったひとつのアクター 2 に対して責務を負うべきである。」 とも説明されていました。 まとめると、「クラスを変更する理由は複数のアクター起因であってはならない」と言えると思います。 単一責任の話の具体例として自分が考えたものは、よくある管理画面、ユーザー画面に別れているものです。 作りとしては、見た目上分かれているが、アプリケーションとしては別れていない、モノリシックな構成です(たぶんRails採用しているところにありがち)。 単純に捉えて、管理画面側のアクターとして管理者がおり、ユーザー画面側のアクターとしてユーザーがいるとします。 商品の登録は管理者が行い、商品の予約をユーザーが行う場合に、下記のようなProductクラスがあった場合、単一責任の原則に違反しています。 このProductクラスは、ユーザーが商品を予約できる機能と、管理者が商品を登録できる機能を別々のクラスに分離する対応が必要です。 class Product def register ( name , price ) # 登録の処理 end def reserve ( user_id ) # 予約の処理 end end なぜ単一責任の原則を守るべきなのか なぜ単一責任の原則を守るべきなのでしょうか? 先程の続きで考えてみます。 ある日、管理者側のメンバーが登録処理の実装の変更を依頼してきました。開発者は登録処理の変更を正しく行いリリースしました。ところがユーザー画面側で予約処理に不具合が出ているという報告を受けました。開発者は再度修正を入れ、管理画面側でもユーザー画面側でも影響がないことを確認した後リリースして事なきを得ました。 この話を聞いてどう思ったでしょうか? 開発者が最初のリリースで予約処理への影響を確認しなかったのが悪

RubyではテストしやすくするためにDIを使わない

結論 Rubyでは、動的にクラスに生えているメソッドを書き換えられるため、テスタビリティを上げるためにDIを使わない。 個人的にはストラテジーパターン使いたいときぐらいしか、DI使わないんじゃないかなーって思っている。 Rubyでテスタビリティ向上のためにDIを使わない理由 DIを使う理由は、結合度の低下、テスタビリティの向上が主な理由だと思います。 一般的な言語の場合には、引数にインターフェースを指定して、インターフェースに依存するようにすることでテスト時にモックオブジェクトを注入できるようにすると思います。しかし、Rubyの場合には、動的にクラスに生えているメソッドを書き換えれるためテスタビリティを上げるためにDIをするのは意味がないです。 Rubyでは、rspecを用いて下記のように書くだけでクラスのメソッドを書き換えることができます。これによりテスト実行時にはクラスのメソッドの内容が変わった状態でテストが実行されます。Rubyのこの柔軟性により、テストを容易にするためにDIを行うという行為は意味がなくなります。 before do google_drive_session = class_double ( GoogleDrive : :Session ) . as_stubbed_const ( transfer_nested_constants : true ) session = instance_double ( 'session' ) allow ( google_drive_session ) . to receive ( :from_service_account_key ) . and_return ( session ) end RubyでDIを使う局面 Rubyを使ってDIを使うとしたら、それはストラテジーパターンを使用したいときぐらいだろうと思ってます。 最近言語周りで思っていること 特定の言語には、特定の言語の流儀があるので、それに従おう。 一般論とか、別の言語の流儀の知識だけで、考えずに突き進むのはやめよう。 参考サイト Dependency injection is not a virtue