빈혈 도메인 모델이 C # / OOP에서는 좋지 않은 것으로 간주되지만 F # / FP에서는 매우 중요한 이유는 무엇입니까?


46

재미와 이익을위한 F # 의 블로그 게시물 에서 다음과 같이 말합니다.

기능적 디자인에서는 데이터와 동작을 분리하는 것이 매우 중요합니다. 데이터 유형은 단순하고 "멍청하다". 그리고 따로 따로, 이러한 데이터 유형에 작용하는 많은 기능이 있습니다.

이것은 동작과 데이터가 결합되는 객체 지향 디자인과 정반대입니다. 결국, 그것이 바로 클래스입니다. 실제로 객체 지향 디자인에서는 동작 외에는 아무것도 없어야합니다. 데이터는 개인 정보이며 메서드를 통해서만 액세스 할 수 있습니다.

실제로 OOD에서 데이터 유형 주위에 충분한 동작이없는 것은 나쁜 것으로 간주되며 이름은 " 빈혈 도메인 모델 "입니다.

C #에서는 F #에서 계속 차용하고 더 기능적인 스타일의 코드를 작성하려고합니다. 어떻게 데이터 / 동작을 분리한다는 아이디어를 빌리지 않고 나쁜 것으로 생각합니까? 단순히 정의가 OOP와 함께 있지 않다는 것입니까, 아니면 C #에서 어떤 이유로 F #에 적용되지 않는 것이 확실한 이유가 있습니까 (실제로 반대로되어 있습니까)?

(참고 : 블로그 게시물의 의견에 동의하지 않을 수있는 개인보다는 오히려 좋고 나쁜 것에 대한 의견을 바꿀 수있는 C # / F #의 차이점에 특히 관심이 있습니다.)


1
안녕 댄! 당신의 태도는 감동적입니다. .NET (및 haskell) 플랫폼 외에도 scala를 살펴 보는 것이 좋습니다. Debashish 고쉬는 당신이가는 기능 도구를 사용하여 도메인 모델링에 대한 블로그의 몇 가지, 그것은 여기, 너무 당신을 위해 희망, 나에게 통찰력이었다 작성했습니다 : debasishg.blogspot.com/2012/01/...
AndreasScheinert

2
: 나는 오늘 동료에 의해 흥미로운 블로그 게시물을 보냈습니다 blog.inf.ed.ac.uk/sapm/2014/02/04/... 그 사람들이 빈혈 도메인 모델은 크게 나쁜한다는 생각에 도전하기 시작 보인다; 좋은 것 같아요!
Danny Tuppeny

1
참조하는 블로그 게시물은 잘못된 아이디어를 기반으로합니다. "일반적으로 데이터는 캡슐화되지 않고 노출되는 것이 좋습니다. 데이터는 변경 불가능하므로 오작동으로 인해"손상 "될 수 없습니다." 불변 유형에도 보존이 필요한 불변이 있으며, 데이터를 숨기고 작성 방법을 제어해야합니다. 예를 들어, 변경 불가능한 레드-블랙 트리의 구현을 공개 할 수 없습니다. 누군가가 레드 노드만으로 구성된 트리를 만들 수 있기 때문입니다.
Doval

4
@Doval은 누군가가 디스크를 가득 채울 수 있기 때문에 파일 시스템 기록기를 노출시킬 수 없다고 말하는 것과 같습니다. 빨간색 노드 만있는 트리를 생성하는 사람은 복제 된 레드-블랙 트리 나 시스템 전체의 코드가 제대로 구성된 인스턴스를 사용하는 데 아무런 피해를주지 않습니다. 새로운 가비지 인스턴스를 생성하거나 위험한 일을하는 코드를 작성하면 불변성은 저장되지 않지만 다른 사람은 저장 하지 않습니다 . 구현을 숨겨도 사람들이 0으로 나눈 넌센스 코드를 작성하는 것을 막을 수는 없습니다.
Jimmy Hoffa

2
@JimmyHoffa 동의하지만 그것은 내가 비판 한 것과는 아무 관련이 없습니다. 저자는 데이터가 불변 이기 때문에 노출되는 것이 보통이라고 주장하며 , 불변성이 구현 세부 사항을 숨길 필요가 마술처럼 제거되지 않는다고 말하고 있습니다.
Doval

답변:


37

FP가이를 목표로하고 C # OOP가하지 않는 주된 이유는 FP에서 초점이 참조 투명성에 있기 때문입니다. 즉, 데이터가 기능으로 들어가고 데이터가 나오지만 원래 데이터는 변경되지 않습니다.

C # OOP에는 개체 관리를 개체에 위임하는 책임 위임 개념이 있으므로 자체 내부를 변경하려고합니다.

FP에서는 객체의 값을 변경하고 싶지 않으므로 객체에 함수를 포함시키는 것은 의미가 없습니다.

또한 FP에서는 C # OOP에서 허용하는 것보다 함수를 훨씬 일반화 할 수있는 더 높은 종류의 다형성이 있습니다. 이런 식으로 any에 적합한 함수를 작성할 수 a있으므로 데이터 블록에 포함시키는 것은 의미가 없습니다. 그 방법은 특정 종류 의 에서만 작동하도록 단단히 결합합니다 a. 어쨌든 일반적으로 함수를 추상화하는 기능이 없지만 FP에서는 트레이드 오프이기 때문에 이와 같은 동작은 C # OOP에서 모두 잘 일반적입니다.

C # OOP의 빈혈 도메인 모델에서 본 가장 큰 문제는 DTO x가 있기 때문에 중복 코드로 끝나고 4 명의 다른 사람들이 다른 구현을 보지 못했기 때문에 활동 f를 DTO x에 커밋하는 4 가지 함수가 있다는 것입니다 . 메소드를 DTO x에 직접 넣으면이 4 명 모두 f의 구현을보고 재사용합니다.

C # OOP의 빈혈 데이터 모델은 코드 재사용을 방해하지만 FP에서는 그렇지 않습니다. 하나의 함수가 여러 유형에 걸쳐 일반화되어 있기 때문에 함수보다 더 많은 시나리오에서 해당 함수를 사용할 수 있기 때문에 더 큰 코드 재사용을 얻을 수 있기 때문입니다 C #에서 단일 DTO를 작성합니다.


주석에서 지적한 바와 같이 , 유형 추론은 FP가 이러한 다형성을 허용하기 위해 의존하는 이점 중 하나이며, 특히 알고리즘 W 유형 추론 을 통해 Hindley Milner 유형 시스템으로 이를 추적 할 수 있습니다 . 제약 기반의 추론이 추가 컴파일 시간 때문에 철저한 검색에 매우 긴 필요가 있기 때문에 C #을 OOP 형 시스템에서 같은 형식 유추를 피할했다, 여기 자세한 사항 : https://stackoverflow.com/questions/3968834/generics-why -이 경우에는 컴파일러가 유추 할 수없는 형식 인수


이러한 종류의 재사용 가능한 코드를 작성하기 쉽게 F #의 어떤 기능을 사용합니까? C #의 코드를 재사용 할 수없는 이유는 무엇입니까? (인터페이스를 필요로하지 않고 메소드가 특정 속성을 갖는 인수를 가질 수있는 능력을 보았을 것 같습니다. 이것이 핵심이라고 생각합니까?)
Danny Tuppeny

7
@DannyTuppeny 솔직히 F #은 비교하기에 좋지 않은 예입니다. 단지 약간 차려 입은 C #입니다. C #과 마찬가지로 변경 가능한 명령 언어이며 C #에는없는 FP 기능이 거의 없습니다. 유형 클래스와 일반 ADT로 인해 FP가 실제로 눈에 띄는 곳을 찾아 내고 이와 같은 것들이 훨씬 더 가능한지 알아보십시오.
Jimmy Hoffa

@MattFenwick 나는 포스터가 요구하는 것이기 때문에 C #을 명시 적으로 언급하고 있습니다. 내 대답 전체에서 OOP를 언급 할 때 C # OOP를 의미합니다. 명백하게 편집 할 것입니다.
Jimmy Hoffa 2016 년

2
이러한 유형의 재사용을 허용하는 기능적 언어 중 공통적 인 기능은 동적 또는 유추 된 타이핑입니다. 언어 자체는 잘 정의 된 데이터 유형을 사용할 수 있지만 일반적인 함수는 수행되는 연산 (기타 함수 또는 산술)이 유효한 한 데이터가 무엇인지 상관하지 않습니다. 이것은 OO 패러다임에서도 사용할 수 있습니다 (예를 들어 Go는 객체가 Duck으로 명시 적으로 선언되지 않은 상태에서 Fly, Swim 및 Quack가 가능하기 때문에 객체가 Duck이 될 수 있도록 암시 적 인터페이스 구현이 있지만). 함수형 프로그래밍의 필수 조건입니다.
KeithS

4
@KeithS Haskell의 값 기반 과부하로 패턴 일치를 의미한다고 생각합니다. Haskell은 서로 다른 패턴을 가진 동일한 이름의 여러 최상위 기능을 갖는 능력을 즉시 1 개의 최상위 기능 + 패턴 일치로 제거합니다.
jozefg

6

빈혈 도메인 모델이 C # / OOP에서는 좋지 않은 것으로 간주되지만 F # / FP에서는 매우 중요한 이유는 무엇입니까?

귀하의 질문에는 귀하가 얻는 답변의 유용성을 제한하는 큰 문제가 있습니다. F #과 FP가 유사하다는 것을 암시 / 가정하고 있습니다. FP는 상징적 용어 재 작성, 동적 및 정적을 포함한 거대한 언어 제품군입니다. 정적으로 형식화 된 FP 언어 중에서도 OCaml 및 SML (F #에는 존재하지 않는)의 고차 모듈과 같은 도메인 모델을 표현하기위한 다양한 기술이 있습니다. F #은 이러한 기능적 언어 중 하나이지만 특히 간결한 것으로 유명하며 특히 고차 모듈이나 고급 유형을 제공하지 않습니다.

실제로 도메인 모델이 FP로 표현되는 방식을 알려 드릴 수 없었습니다. 다른 답변은 Haskell에서 어떻게 수행되는지에 대해 매우 구체적으로 말하며 Lisp (모든 FP 언어의 어머니), ML 언어 군 또는 기타 기능적 언어에는 적용되지 않습니다.

어떻게 데이터 / 동작을 분리한다는 아이디어를 빌리지 않고 나쁜 것으로 생각합니까?

제네릭은 데이터와 동작을 분리하는 방법으로 간주 될 수 있습니다. ML 기능 프로그래밍 언어 제품군에서 나온 제네릭은 OOP의 일부가 아닙니다. 물론 C #에는 제네릭이 있습니다. 따라서 C #이 데이터와 동작을 분리한다는 아이디어를 천천히 빌리고 있다고 주장 할 수 있습니다.

단순히 정의가 OOP에 맞지 않는다는 것입니까?

OOP는 근본적으로 다른 전제를 기반으로하므로 결과적으로 데이터와 행동을 분리하는 데 필요한 도구를 제공하지 않습니다. 모든 실제 목적을 위해서는 제품 및 합계 데이터 유형이 필요하며이를 전달해야합니다. ML에서 이는 통합 및 레코드 유형과 패턴 일치를 의미합니다.

내가 준 예를 확인 하십시오 .

아니면 어떤 이유로 F #에 적용되지 않는 사실이 C #에서 나쁜 구체적인 이유가 있습니까 (실제로 반대입니까)?

OOP에서 C #으로 점프하는 것에주의하십시오. C #은 다른 언어처럼 OOP에 대해 순수하게 접근 할 수있는 곳이 없습니다. .NET Framework는 이제 제네릭, 정적 메서드 및 람다로 가득합니다.

(참고 : 블로그 게시물의 의견에 동의하지 않을 수있는 개인보다는 오히려 좋고 나쁜 것에 대한 의견을 바꿀 수있는 C # / F #의 차이점에 특히 관심이 있습니다.)

C #의 공용체 유형과 패턴 일치가 없기 때문에 거의 불가능합니다. 당신이 가진 모든 것이 망치라면 모든 것이 못처럼 보입니다 ...


2
... 당신이 가진 모든 것이 망치라면 OOP 사람들은 망치 공장을 만들 것입니다 .P +1은 실제로 C #에서 누락 된 것의 핵심을 고정하여 데이터와 행동이 서로 완전히 추상화 될 수있게합니다 : 유니온 유형 및 패턴 일치.
Jimmy Hoffa

-4

비즈니스 응용 프로그램에서는 불변의 값에 대한 패턴 일치가 모든 가능한 경우를 다루기 위해 훌륭하기 때문에 데이터를 숨기고 싶지 않다고 생각합니다. 그러나 복잡한 알고리즘 또는 데이터 구조를 구현하는 경우 ADT (대수 데이터 형식)를 ADT (추상 데이터 형식)로 변환하는 구현 세부 정보를 숨기는 것이 좋습니다.


4
이것이 객체 지향 프로그래밍과 기능 프로그래밍에 어떻게 적용되는지에 대해 좀 더 설명해 주시겠습니까?
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.