TDD with RDD Clojure/LispのREPLで変わる開発体験 #NextbeatTechBar 1
のシニアエンジニア スタートアップの起業家と投資家のための業務効 率化/連携プラットフォームを開発している 主要技術スタック: & TypeScript の運営企業 , などの関数型言語と関数型プログ ラミングの実践が好き Java, , Clojure, KotlinとJVM言語での開発実務 に長く取り組んできた lagénorhynque🐬カマイルカ 株式会社スマートラウンド Kotlin Server-Side Kotlin Meetup Clojure Haskell Scala 2
ClojureでRDDとTDDのハイブリッドな開発スタイル を実践しよう 3
1. TDDとRDD 2. TDD with RDD 3. Clojureでの実践例 4
1. TDDとRDD 5
[IMO] プログラミングで体感的に大きな割合を占める 対話的プロセス 言語 対話の相手 (高度な型システムを持つ)静的 型付き言語 コンパイラ (高度なREPL開発環境と動的性質 を持つ) Lisp系言語 REPL その他の多くの言語 ユニットテストor/and (ログ付 きの実行を含む)デバッガー 6
対話の延長上にある3種類の開発スタイル コンパイラとの対話→型駆動開発(type-driven development) REPLとの対話→REPL駆動開発(REPL-driven development, RDD) ユニットテストとの対話→テスト駆動開発(test- driven development, TDD) 7
試行錯誤の探索的なプロセス ツールに助けられたり惑わされたりしながら進む 高速で高頻度なフィードバックループ 反応を見て、書き換えて、反応を見る繰り返し 設計の漸進的改善の機会でもある ユニットテストによるフィードバックと一定の動作 保証は高度なコンパイラやREPLを補完しうる 複数を組み合わせて実践しよう💡 8
2. TDD with RDD 9
テスト駆動開発(TDD) 0. 満たすべき仕様を整理する 1. 🟥Red: 仕様に対応するテストコードを書いて(想定 通り)テストをパスしないことを確かめる 2. 🟩Green: テストをパスする最小限の実装を与えて テストをパスすることを確かめる 3. 🟦Refactor: 内部実装(コード設計)を改善して引き 続きテストをパスすることを確かめる→再び1.へ 10
コードを読み取り、評価し、出力する繰り返し REPL (read-eval-print loop) ;; [Clojure] REPL内で素朴なrepl関数を定義し実行してみる user=> (defn repl [] (loop [] (-> (read) ; 入力の読み取り (eval) ; 評価 (prn)) ; 出力 (recur))) ; 再帰(= ループ) #'user/repl ; 関数定義式の評価結果 user=> (repl) (+ 1 2) ; 入力 3 ; 出力 (map inc [1 2 3]) ; 入力 (2 3 4) ; 出力 11
REPL駆動開発(RDD) 1. ✍️Write: 小さなコード(任意の式)を書く 2. 🔍Eval: 式を評価し結果を確かめる→再び1. へ 12
TDD with RDD 1. ✍🔍️テスト対象の式を書いて評価する 2. ✍🔍テスト用の式を書いて評価し結果を確かめる 🟥意図通りでない→再び1. へ 🟩意図通り→(適宜)テストケースに記録する 3. 🟦内部実装を改善して評価結果が意図通りである (or テストをパスする)ことを確かめる→再び1. へ 13
3. Clojureでの実践例 14
事前準備: テストコード用ファイル (ns clj-tdd-with-rdd.core) ; 名前空間(モジュール)の宣言 (defn fizzbuzz [n]) ; 関数の定義(※ボディはまだ空) 15
事前準備: プロダクトコード用ファイル (ns clj-tdd-with-rdd.core-test (:require [clj-tdd-with-rdd.core :as sut] ; テスト対象 [clojure.test :as t])) ; 標準のテストライブラリ (t/deftest test-fizzbuzz ; テスト関数の定義 (t/testing "3の倍数ならFizz") ; テストケースの説明 (t/testing "5の倍数ならBuzz") (t/testing "3の倍数かつ5の倍数ならFizz Buzz") (t/testing "3の倍数でも5の倍数でもなければ整数の文字列")) 16
エディタでファイルを開き、REPLに接続する 17
関数の定義と適用の式を評価してみる 18
関数定義を書き換えてそれぞれ評価してみる 19
テストケースに書き換えて評価してみる 20
類似のケースを追加してテスト全体を実行してみる 21
さらに続けて…… 22
プロダクトコードとテストコードを書き上げた 23
リファクタしてみた 24
リファクタリング後もテストをパスする😌 25
リッチなREPLは探索的な開発フローを加速する♾️ Lisp系言語のREPLはいいぞ😈 (他言語でも同じような開発体験がしたい) 26
Further Reading cf. Clojure/ClojureScript関連リンク集> REPL駆動開 発 『テスト駆動開発』 Type-Driven Development with Idris Idris: A Language for Type-Driven Development 型駆動開発|プログラング言語Idrisに入門させた い(v0.9) 27

TDD with RDD: Clojure/LispのREPLで変わる開発体験