2009-11-20 4 views
9

나는 erlang, mnesia 및 webmachine을 사용하여 웹 사이트를 구축 중입니다. 필자가 읽은 대부분의 문서는 참조가 투명한 기능을 갖는 덕목을 칭찬합니다.참조 투명성을 얼마나 멀리 가져야합니까?

문제는 모든 데이터베이스 액세스가 외부 상태라는 것입니다. 즉, 데이터베이스에 도달하는 모든 메소드가 더 이상 참조 성을 갖지 않습니다.

데이터베이스에 사용자 개체가 있고 인증을 처리하는 일부 기능이 있다고 가정 해 보겠습니다.

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. 

Referentially 투명성 내가 referentially 불투명 코드의 양을 최소화하는 것이 필요하므로 발신자는 데이터베이스에서 개체를 가져오고 인수로 그에 통과해야합니다 : 같은

Referentially 불투명 기능을 보일 수 있습니다 함수 :

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. 

위의 코드는 분명히 생산 코드가 아니며 설명 목적으로 만 작성되었습니다.

저는 독단에 빠져들고 싶지 않습니다. 명확한 투명 코드 (증명 가능한 단위 테스트와 같은)의 이점은 덜 친숙한 인터페이스를 정당화합니까? 내가 얼마나 멀리 떨어진 곳에서 투명성을 추구해야 하는가?

+0

루프 (MyWholeState) -> 루프 (X-> X 끝, MyWholeState 수신) 및 루프 (RecvHttp, MyWholeState) -> ..., 루프 (MyWholeNewState) 루프 만 있으면 전체 데이터베이스를 제거 할 수 있습니다. 모든 것을 참조하는 것을 투명하게 만듭니다. – Zed

답변

9

참조 투명성을 항상 유지해야하는 이유는 무엇입니까?

get_user_from_db의 정의를 고려하십시오. 데이터베이스와 대화하는 방법을 어떻게 알 수 있습니까? 분명히 일부 (전역) 데이터베이스 컨텍스트를 가정합니다. 이 함수를 변경하여 데이터베이스 컨텍스트를 인수로 취하는 함수를 리턴 할 수 있습니다. 당신이 가진 것은 ...

get_user_from_db :: userid -> User 

이것은 거짓말입니다. 사용자 ID에서 사용자로 이동할 수 없습니다. 데이터베이스가 필요합니다.

get_user_from_db :: userid -> Database -> User 

이제 사용자 ID로 카레를 작성하고 나중에 데이터베이스를 지정하면 함수가 사용자에게 제공됩니다. 물론 현실 세계에서 Database은 핸들이나 데이터베이스 연결 객체 등이 될 것입니다. 테스트를 위해 모의 데이터베이스를 제공하십시오.

+1

답변을 읽었으니 완전히 분명한 것 같습니다. 그러나 나는 결코 그것을 생각하지 않았을 것이다 - 감사합니다!-> 사용자 ID -> 사용자 나는이 버전은 가정 get_user_from_db : 데이터베이스 : 그러나, 데이터베이스 컨텍스트를 가지고 함수를 반환하는 함수를 작성하는 것이 (이 상황에서) 더 나을 나에게 보인다 기본 데이터베이스 컨텍스트가 변경 될 수 있기 때문에 잠재적으로 참조 투명성이 손상됩니다. –

+1

하나를 다른 데이터베이스에서 가져올 수 있습니다. 'a -> b -> c'는'b -> a -> c'와 같습니다. 당신이 필요로하는 것은 상위 함수입니다 :'flip f a b = f b a'. 인수 선택의 순서. 이 특별한 경우에는 Database를 마지막 인자로 사용할 수있는 조합성에 대한 의미가 있습니다. 왜냐하면 Kleisli 구성을 할 수 있기 때문입니다. – Apocalisp

+1

첫 번째 인수로'Database'를 사용하면 함수는 데이터베이스를 반환하는 함수로만 구성 될 수 있습니다. 나는 그 중 많은 것이 없다고 생각합니다. – Apocalisp

3

이미 단위 테스트에 대해 언급 했으므로이 용어로 생각해보십시오. 테스트에서 가치가 있다고 생각되는 모든 것은 실제적으로 투명해야 테스트 할 수 있습니다.

잘못 될 수있는 복잡한 논리가없고 단일 기능/통합 테스트에서 이것이 맞는지 알아 보려면 왜 여분의 거리에가는 것이 좋을까요?

Think YAGNI. 그러나 단위 테스트 가능성이 진정 필요한 것입니다.

관련 문제