2016-01-21 6 views
5

現在、私はClojureのにリファクタリングしていたとき、私は、パターンを使用する傾向がある:リファクタリング時に戻り値の型を調べる良い方法はありますか?

(defn my-func [arg1 arg2] 
    (assert (= demo.core.Record1 (class arg1) "Incorrect class for arg1: " (class arg1)) 
    (assert (= demo.core.Record1 (class arg2) "Incorrect class for arg2: " (class arg2)) 
    ... 

私は自分自身が手動でシステムの下流部分は、私が「ドン何かにそれらを変更する場合の戻り値の型をチェック見つける、あります期待しています。 (私がリファクタリングして、私が期待していないスタックトレースを取得した場合、不変条件として私の仮定を表現し、そこから前進する)。

これはちょうどBertrand Meyerが予期している不変のチェックのようなものです。 (Object Oriented Software Constructionの著者、および考えの提案者Design by Contract)。

実行時までこれらを見つけられないという難点があります。私はコンパイル時にこれを見つけることができればうれしいです - 関数が何を期待しているかを単に伝えるだけです。

今すぐ私は知っている Clojureは本質的に動的言語です。 (Clojureにはコンパイラの種類がありますが、実行時に関数の値をアプリケーションに渡すことが期待されます)

リファクタリングを簡単にするためのパターンが必要です。 (つまり、引数を関数に変更して最初の呼び出しでブレークしなくても、次のブレークに移動してから次のブレークに移動するすべてのフローオンの効果を参照してください)

私の質問はですリファクタリング時に戻り値の型をチェックする良い方法はありますか?

答えて

2

あなたはオプションのカップルを持っているが、一方のみの時間「コンパイル」さ:Clojureのは動的言語であるため

テスト

を、テストが必要不可欠です。リファクタリングの際のセーフティネットです。静的型付き言語でさえ、テストはまだ使用されています。

前と事後条件

彼らはあなたがMichael Fogus' blogから、このような本例のように、あなたの関数にメタデータを追加することで、あなたの不変量を確認することができます:

(defn constrained-fn [f x] 
    {:pre [(pos? x)] 
    :post [(= % (* 2 x))]} 
    (f x)) 

(constrained-fn #(* 2 %) 2) 
;=> 4 
(constrained-fn #(float (* 2 %)) 2) 
;=> 4.0 
(constrained-fn #(* 3 %) 2) 
;=> java.lang.Exception: Assert failed: (= % (* 2 x) 

をcore.typed

core.typedは、このリストの唯一のオプションで、コンパイル時間のチェックを行います。あなたの例では、そのようにように表現されます:

(ann my-func (Fn [Record1 Record1 -> ResultType])) 
(defn my-func [arg1 arg2] 
...) 

これはおそらく、あなたのテストスイートの一部として、別々のアクションとして実行されているcore.typedを犠牲にして。

さらに、ランタイム検証/検査の分野では、bouncerschemaのようなさらに多くのオプションがあります。

3

あなたのことを正しく理解していれば、プリズム/スキーマを選択する必要があります。 https://github.com/plumatic/schema

(s/defn ^:always-validate my-func :- SomeResultClass 
    [arg1 :- demo.core.Record1 
    arg2 :- demo.core.Record1] 
    ...) 

それがパフォーマンスに影響を与えませんので、あなただけの、リリース前にすべての検証をオフにする必要があります。

core.typedは素晴らしいですが、覚えている限り、すべてのコードにアノテーションを付けるようにしていますが、スキーマではクリティカルな部分のみをアノテーションできます。

関連する問題