9

私はerlang、mnesia、およびwebmachineを使用してWebサイトを構築しています。私が読んだドキュメントのほとんどは、参照透過性の機能を持つことの長所を賞賛しています。

問題は、すべてのデータベースアクセスが外部状態であるということです。これは、データベースにヒットするメソッドが参照透過性ではなくなったことを意味します。

データベースにユーザーオブジェクトがあり、認証を処理するいくつかの関数があるとします。

参照的に不透明な関数は次のようになります。

handle_web_request(http_info) ->
  is_authorized_user(http_info.userid),
  ...
%referentially opaque
is_authorized_user(userid) ->
  User = get_user_from_db(userid),
  User.is_authorized.

%referentially opaque
lots_of_other_functions(that_are_similar) ->
  db_access(),
  foo.

参照の透明性では、参照の不透明なコードの量を最小限に抑える必要があるため、呼び出し元はデータベースからオブジェクトを取得し、それを引数として関数に渡す必要があります。

handle_web_request(http_info) ->
  User = get_user(http_info.userid),
  is_authorized_user(User),
  ...

%referentially opaque
get_user(userid) ->
  get_user_from_db(userid).

%referentially transparent      
is_authorized(userobj) ->
  userobj.is_authorized.

%referentially transparent    
lots_of_other_functions(that_are_similar) ->
  foo.

上記のコードは明らかに実動コードではありません-それは純粋に説明の目的で構成されています。

私は教義に夢中になりたくありません。参照透過性のあるコード(証明可能な単体テストなど)の利点は、使い勝手の悪いインターフェースを正当化するのでしょうか?参照の透明性を追求するには、どこまで行けばよいのでしょうか。

4

2 に答える 2

9

参照透過性をずっと取り入れてみませんか?

の定義を考えてみましょうget_user_from_db。データベースと通信する方法をどのように知っていますか?明らかに、それはいくつかの(グローバルな)データベースコンテキストを前提としています。この関数を変更して、データベースコンテキストを引数として取る関数を返すようにすることができます。あなたが持っているのは...

get_user_from_db :: userid -> User

これは嘘です。ユーザーIDからユーザーに移動することはできません。他に何かが必要です:データベース。

get_user_from_db :: userid -> Database -> User

ここで、ユーザーIDを使用してそれをカレーし、後でデータベースを指定すると、関数はユーザーを提供します。もちろん、現実の世界でDatabaseは、ハンドルやデータベース接続オブジェクトなどになります。テストのために、モックデータベースを提供します。

于 2009-11-21T00:54:54.567 に答える
3

あなたはすでにユニットテストについて言及しました、それらの用語で考え続けてください。テストで価値があると思うものはすべて、テストできるように、参照透過性にする必要があります。

うまくいかない可能性のある複雑なロジックがなく、単一の機能/統合テストでそれが正しいことがわかる場合、なぜわざわざ余分な距離を移動するのでしょうか。

YAGNIだと思います。しかし、ユニットの妥当性が本当に必要な場合。

于 2009-11-20T22:36:47.263 に答える