[[📚テスト駆動開発]]のメモ。 - [[📰テスト駆動開発 読書メモ ~TypeScript編~]] を[[Rust]]でチャレンジしなおしたもの - もともと[[Rust]]版を先にやっていたが、**設計思想が異なり難しすぎた**ので[[📰テスト駆動開発 読書メモ ~TypeScript編~]]に切り替えた経緯がある ## オレオレルール 本書は[[Java]]で書かれているが、言語は[[Rust]]で同じ意味の内容を書いていく。狙いは2つ。 - [[Rust]]の復習やキャッチアップを行うため - 丸写しできない環境をつくることで理解度を深めるため なお、[[IDE]]は[[Neovim]]を使用する。これは単に[[Neovim]]力を高めたいから。具体的には操作スピードと環境の向上である。 <div class="link-card"> <div class="link-card-header"> <img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" class="link-card-site-icon"/> <span class="link-card-site-name">minerva.mamansoft.net</span> </div> <div class="link-card-body"> <div class="link-card-content"> <div> <p class="link-card-title">📜2023-09-10 RustでTDD写経するためにNeovimを使った環境構築</p> </div> </div> <img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/minerva-image.webp" class="link-card-image" /> </div> <a class="internal-link" data-href="📜2023-09-10 RustでTDD写経するためにNeovimを使った環境構築" ></a> </div> %%[[📜2023-09-10 RustでTDD写経するためにNeovimを使った環境構築]]%% ### リポジトリ リポジトリは[[GitHub]]に公開する。 <div class="link-card"> <div class="link-card-header"> <img src="https://github.githubassets.com/favicons/favicon.svg" class="link-card-site-icon"/> <span class="link-card-site-name">GitHub</span> </div> <div class="link-card-body"> <div class="link-card-content"> <div> <p class="link-card-title">GitHub - tadashi-aikawa/rust-tdd</p> </div> <div class="link-card-description"> Contribute to tadashi-aikawa/rust-tdd development by creating an account on GitHub. </div> </div> <img src="https://opengraph.githubassets.com/ea6ef0d37a3e39be418dc9b3ac78b04cdcf5c8f9adbf90e632e1263668c5ba4d/tadashi-aikawa/rust-tdd" class="link-card-image" /> </div> <a href="https://github.com/tadashi-aikawa/rust-tdd"></a> </div> ## Are you ready? ここからが本編。 # まえがき ### テストの価値 - 開発が予測可能になる - チームの信頼感が増す - 書いていて気持ちいい ### 作業の順序 | 用語 | 意味 | | ---------------- | -------------------------------- | | レッド | 動作しないしコンパイルも通らない | | グリーン | テストが成功する? | | リファクタリング | 重複の除去 | ### 勇気と不安 - テスト熱中症 ### 本書を読み終えたあとの姿 - シンプルに始める - 自動テストを書く - リファクタリングで設計判断を1つずつ行う # 第I部 多国通貨 ### 対応順序 1. テストを1つ書く 2. 全テストを実行させ、1のテスト失敗を確認する 3. 小さな変更を行う 4. 全テストを実行させ、1のテスト成功を確認する 5. リファクタリングで重複を削除する ## 第1章 仮実装 細かいステップを踏み続けられる(can)であることが大事。 > [!positive] 普段の開発でもログ出力やダミー実装で休憩ポイントを設けて、少しずつ開発していってるからこれは分かる。[[TDD]]とは別に、通常の開発も (遠回りにならない程度の) 小刻みなステップは大事だと思う https://github.com/tadashi-aikawa/rust-tdd/tree/0728036dafb2cd06f97e8606add46b3ab49f59a0 ## 第2章 明白な実装 | 用語 | 意味 | | ---------- | -------------------------------------------- | | 仮実装 | 定数ベタ書きからはじめて変数に置き換えていく | | 明白な実装 | 頭の中の実装をすぐコードに落とす | > [!thinking] 自信があるときは明白な実装モード、自信がなくなったら仮実装モードにシフトというのは分かりやすい戦略の1つ。自分は仮実装モードからスタートすることが多いけど、無意識のうちに2つのモード切替を実はしているのかもしれない...🤔 [[Rust]]の[[バイナリクレート]]として作っていたが[[ライブラリクレート]]としても作り直した。理由は以下。 - 未使用警告が全体に出るのが気持ち悪い - テスト実行が主目的なのでこっちの方が適切なはず https://github.com/tadashi-aikawa/rust-tdd/tree/7763b33e7cbf2f37a2a9352d77ada4fd925f6f41 ## 第3章 三角測量 - [[Value Object パターン]] - [[別名参照問題]] > [!positive] 普通にequalsの実装方法しか頭になかった😇 ```rust #[test] fn test_equality() { assert_eq!(Dollar::new(5).equals(Dollar::new(5)), true); } ``` だと不十分で... [[三角測量]]を行うには2つ目の実例がいる。 ```rust #[test] fn test_equality() { assert_eq!(Dollar::new(5).equals(Dollar::new(5)), true); assert_eq!(Dollar::new(5).equals(Dollar::new(6)), true); } ``` > [!thinking] [[Rust]]だとnullや他Objectとの比較は不要な気がするんだけど、どうなんだろう...? その辺は静的型チェックで弾けるし、弾くべきところかと思うのだが... https://github.com/tadashi-aikawa/rust-tdd/tree/8e79925b28eb1c40c757595f38ffad3e608d85c5 ## 第4章 意図を語るテスト > [!positive] 『テストは意図を語る』という表現好き。複雑な処理を隠蔽するための関数化も大事だけど、テストコードのインターフェースは読めば伝わる方が遥かに大事だと思っている。 > [!positive] [[Java]]の実装に引きずられていたら、[[Rust]]の実装を忘れていた...。[[Rustのassert_eqマクロで比較する対象はPartialEqトレイトとDebugトレイトの実装が必須]]なことや[[derive属性]]などを思い出した。 https://github.com/tadashi-aikawa/rust-tdd/tree/e09f22e29b58b2ce6108131d1701e323bc3b3478 ## 第5章 原則をあえて破るとき > [!positive] 自分はよく『正義のコピペ』という名前で呼んでる https://github.com/tadashi-aikawa/rust-tdd/tree/de782c2354e0f6728c99a5f585db89ca84a0129c ## 第6章 テスト不足に気づいたら > [!thinking] [[Rust]]だと継承は使えないから[[トレイト]]の実装になるのかな... [[derive属性]]でいくつかは実装できてる気はする [[トレイト]]だと共通の[[フィールド (Rust)|フィールド]]を定義できないので、 [[Rustのニュータイプパターンを利用しつつ、self.0を使わない方法]]を応用して切り抜ける。 https://github.com/tadashi-aikawa/rust-tdd/tree/acdfc55ad15fc7b360fa1e14994ad8c0417cf7aa > [!thinking] [[Derefトレイト]]実装を共通化したいけど、やり方が分からん。。 https://github.com/tadashi-aikawa/rust-tdd/tree/b0e1d2c6e12614f70374f47f75c00eb0a921262a ## 第7章 疑念をテストに翻訳する ```rust #[test] fn test_equality() { assert!(Dollar::new(5).eq(&Dollar::new(5))); assert!(!Dollar::new(5).eq(&Dollar::new(6))); assert!(Franc::new(5).eq(&Franc::new(5))); assert!(!Franc::new(5).eq(&Franc::new(6))); assert!(!Franc::new(5).eq(&Dollar::new(5))); } ``` `eq`の型は自分自身しか認めていなかったのでエラーになる。(これを許容したかったからObjectにしてたのか。。) ```error mismatched types expected reference `&rust_tdd::franc::Franc` found reference `&rust_tdd::dollar::Dollar` (rustc E0308) ``` https://github.com/tadashi-aikawa/rust-tdd/tree/4e063e4c9b96a178352388439a43837dfb166b1c ## 第8章 実装を隠す ==ここで一旦休止し [[📰テスト駆動開発 読書メモ ~TypeScript編~]] を進めることにした==