문제

정적으로 유형 된 환경 (예 : Ruby vs C#)과 달리 동적으로 입력 된 환경에서 다르게 적용하거나 적용하지 않는 OOP 원칙은 무엇입니까? 이것은 정적 대 역동적 인 토론을 요구하는 것이 아니라 오히려 다른 분열의 양쪽에 다른 사람에게 적용되는 것이 아니라 다르게 적용되는 원칙이 있는지 여부를보고 싶습니다. "상속을 선호하는 구성"과 같은 문구는 정적으로 유형 된 OOP 문헌에서 잘 알려져 있습니다. 동적 측면에서 적용 할 수 있습니까?

예를 들어, 동적으로 입력 된 환경에서는 커플 링의 세분성이 방법의 수준보다 더 이상 진행되지 않는 것 같습니다. 다시 말해, 주어진 함수는 호출자 만 해당 특정 인터페이스에 연결합니다. 어느 클래스는 아마도 그 특정 오리와 같은 퀴즈가있는 다른 방법으로 만족하거나 다른 방법으로 말할 수 있습니다.

반면에 Java에서는 커플 링의 세분성이 패키지만큼 높을 수 있습니다. 특정 메소드 호출은 다른 클래스/인터페이스와 계약을 체결 할뿐만 아니라 해당 클래스/인터페이스의 패키지/JAR/어셈블리에도 연결합니다.

이와 같은 차이로 인해 다른 원리와 패턴이 발생합니까? 그렇다면 이러한 차이점이 표현 되었습니까? 섹션이 있습니다 루비 찰음 이 방향으로 들어가는 책 (오리 타이핑/클래스는 유형이 아닙니다)이지만 다른 것이 있는지 궁금합니다. 알고 있습니다 루비의 디자인 패턴 그러나 읽지 않았습니다.

편집 - 그것은 주장되었다 리스 코프 정적 환경에서와 마찬가지로 동적 환경에서는 동일하게 적용되지 않지만 그렇게 생각하는 데 도움이되지 않습니다. 한편으로는 전체 클래스와 높은 수준의 계약이 없습니다. 그러나 주어진 클래스에 대한 모든 전화는 절대적인 Liskov가 처방하는 방식으로 아동 계급에 의해 만족 해야하는 계약? 다음을 고려하세요. "일부 바 물건"의 전화는 아동 수업이 참석 해야하는 계약을 만듭니다. 이것은 "특수한 물체를 기본 클래스 인 것처럼 취급하는 경우가 아닌가?"

class Bartender
    def initialize(bar)
       @bar = bar
    end

    def do_some_bar_stuff
        @bar.open
        @bar.tend
        @bar.close
    end
end

class Bar
    def open
        # open the doors, turn on the lights
    end
    def tend
        # tend the bar
    end
    def close
        #clean the bathrooms
    end
end

class BoringSportsBar < Bar
    def open
        # turn on Golden Tee, fire up the plasma screen
    end

    def tend
        # serve lots of Bud Light
    end
end

class NotQuiteAsBoringSportsBar < BoringSportsBar
    def open
        # turn on vintage arcade games
    end
end

class SnootyBeerSnobBar < Bar
    def open
        # replace empty kegs of expensive Belgians
    end

    def tend
        # serve lots of obscure ales, porters and IPAs from 124 different taps
    end
end

# monday night
bartender = Bartender.new(BoringSportsBar.new)
bartender.do_some_bar_stuff

# wednesday night
bartender = Bartender.new(SnootyBeerSnobBar.new)
bartender.do_some_bar_stuff

# friday night
bartender = Bartender.new(NotQuiteAsBoringSportsBar.new)
bartender.do_some_bar_stuff
도움이 되었습니까?

해결책

당신이 말하고있는 필수 차이는 다음과 같습니다.

  • 언어 그룹 2. eg object.method1, object.method2, object.method3는 객체의 수명 동안 변경 될 수 없을 때 ing object.method1, 객체.

그룹 1의 언어는 동적 타이핑을 갖는 경향이 있으며 그룹 2의 컴파일 시간 점검 인터페이스 및 언어는 정적 타이핑을 갖고 컴파일 타임 CHCKED 인터페이스를 지원하는 경향이 있습니다.

나는 모든 OO 원칙이 둘 다에 적용된다고 말하지만

  • 구현하기위한 (명시 적) 코딩 (컴파일 타임 대신 런타임) 검사는 컴파일 타임이 없기 때문에 인터페이스 계약을 충족하기 위해 모든 적절한 방법으로 새로운 객체가 생성되었다고 주장하기 위해 그룹 1에서 검사가 필요할 수 있습니다. 인터페이스 이용 확인 (그룹 1 그룹 2와 비슷한 그룹 1 코드를 만들려면)

  • 그룹 2에서 일부 추가 코딩은 추가 상태 플래그를 사용하여 서브 메트로 드를 호출하거나 첨부 된 여러 개체 중 하나를 참조하여 메소드 또는 메소드 세트를 마무리하여 메소드 호출을 위해 호출 된 실제 메소드의 변경 사항을 모델링하기 위해 필요할 수 있습니다. 여러 객체가 다른 메소드 구현을 갖는 주 객체에 (그룹 2 코드를 그룹 1 코드와 비슷하게 만들려면)

  • 그룹 2 언어의 디자인에 대한 제한은 (이해와 반대로) 의사 소통의 용이성이 더 중요 해지는 더 큰 프로젝트에 더 나은 것입니다.

  • 그룹 1 언어의 디자인에 대한 제한이 부족하면 소규모 프로젝트의 경우 프로그래머가 다양한 디자인 배관 제약 조건이 단순히 코드가 더 작아서 한눈에 충족되는지 더 쉽게 확인할 수 있습니다.

  • 다른 한 그룹과 같은 한 그룹의 언어로 코드를 만드는 것은 흥미롭고 공부할 가치가 있지만 언어 차이의 요점은 실제로 다른 크기의 팀을 잘 돕는 것과 관련이 있습니다 ( - 나는 믿습니다! :))

  • 다른 차이점이 있습니다

  • 관련된 정확한 원칙에 따라 한 언어로 OO 디자인을 구현하려면 다소 레그 작업이 필요할 수 있습니다.


편집하다

원래 질문에 답하기 위해 검토했습니다

http://c2.com/cgi/wiki?principlesofobjectorientedDesign

그리고

http://www.dofactory.com/patterns/patterns.aspx

실제로 OO 원칙은 시스템에서 다양한 좋은 이유 (물론 나쁜)에 따라 따르지 않습니다. 성능 문제가 순수한 설계 품질 문제를 능가하는 경우, 대체 구조의 문화적 이점/이름 지정의 순수한 설계 품질 문제를 능가하는 곳과 특정 언어에 대한 표준 방식이 아닌 기능을 구현하는 추가 작업의 비용이 이점을 능가하는 경우 순수한 디자인.

State, Command, Factory Method, Composite, Decorator, Facade, Flyweight, Memento, Template Method와 같은 미세한 패턴은 그룹 1 코드에서 더 일반적이지만 종종 여러 디자인 패턴은 물체가 아니라 다른 부분에 적용됩니다. 그룹 2 코드 패턴은 객체 당 하나의 패턴으로 존재하는 객체입니다.

IMHO 대부분의 그룹 1 언어에서 모든 글로벌 데이터와 기능을 일종의 싱글 톤 "응용 프로그램"객체로 생각하는 것이 의미가 있습니다. 나는 우리가 절차 적 프로그래밍과 OO 프로그래밍 사이의 선을 흐리게하고 있다는 것을 알고 있지만, 이런 종류의 코드는 많은 경우에 "응용 프로그램"객체와 같이 quack을 분명히 알고 있습니다! :)

반복자와 같은 매우 세밀한 디자인 패턴은 그룹 1 언어에 내장되는 경향이 있습니다.

다른 팁

개인적으로 동적 및 정적으로 입력 한 언어 모두에서 작동하지 않는 OOP 원칙은 원칙이 아니라고 말하면서 시작하겠습니다.

즉, 여기에 예가 있습니다.

인터페이스 분리 원리 (http://objectmentor.com/resources/articles/isp.pdf) 고객은 자신의 요구를 충족시키는 가장 구체적인 인터페이스에 의존해야한다고 말합니다. 클라이언트 코드가 클래스 C의 두 가지 메소드를 사용해야하는 경우 C는 인터페이스를 구현해야하며,이 두 가지 메소드 만 포함하고 클라이언트는 C보다는 i를 사용합니다.이 원리는 인터페이스가 필요하지 않은 동적으로 입력 된 언어와 관련이 없습니다 (인터페이스 이후. 정의 된 유형 및 유형은 변수가 유형이없는 언어에서 필요하지 않습니다)

편집하다

두 번째 예 - 의존성 반전 원리 (http://objectmentor.com/resources/articles/dip.pdf). 이 원칙은 "구체적인 기능과 클래스보다는 인터페이스 또는 추상 기능 및 클래스에 의존하는 전략"이라고 주장합니다. 다시 말하지만, 동적으로 입력 한 언어 클라이언트 코드는 아무것도 의존하지 않습니다. 단지 메소드 서명을 지정 하여이 원칙을 명시하지 않습니다.

세 번째 예 -Liskov 대체 원리 (http://objectmentor.com/resources/articles/lsp.pdf). 이 원칙의 교과서 예제는 사각형 클래스를 서브 클래스하는 제곱 클래스입니다. 그런 다음 실제 객체가 정사각형이기 때문에 높이가 변경되면 사각형 변수에서 setwidth () 메소드를 호출하는 클라이언트 코드가 놀랍습니다. 다시 말하지만, 동적으로 입력 된 언어로 변수는 유형이없고, 직사각형 클래스는 클라이언트 코드에 언급되지 않으므로 그러한 놀라움은 발생하지 않습니다.

나는이 모든 것에 대한 "급진적 인"견해를 가지고 있습니다. 제 생각에는 수학에 의해 뒷받침되는 OOP는 흥미로운 문제에 대해 정적으로 입력 한 환경에서 작동하지 않습니다. 나는 초록 관계가 관련된 의미로 흥미를 정의합니다. 이것은 쉽게 입증 될 수 있습니다 ( "공분산 문제"참조).

이 문제의 핵심은 OOP의 개념이 추상화를 모델링하는 방법이며 정적 타이핑에 의해 전달되는 계약 프로그래밍과 결합하는 것이 캡슐화를 중단시키지 않으면 서 관계를 구현할 수 없다는 것입니다. C ++에서 "Less"또는 "Add"를 구현하십시오. 기본 추상화를 쉽게 코딩 할 수 있지만 구현할 수는 없습니다.

동적 시스템에는 높은 수준의 공식화 된 유형이 없으며 OO로 귀찮게 할 캡슐화는 없으며, 특히 원래 SmallTalk와 같은 원래 SmallTalk와 같은 프로토 타입 기반 시스템은 실제로 정적 타이핑 제약 조건으로 전혀 인코딩 할 수없는 작업 모델을 제공합니다.

또 다른 방법으로 질문에 대답하기 위해 : 바로 질문의 기본 가정은 도구 적으로 결함입니다. OO는 일관된 이론이 아니기 때문에 일관된 원칙이 없습니다. 간단한 프로그래밍 작업을 수행 할 수있는 충분한 힘을 가진 모델이 없기 때문입니다. 다이나믹 시스템에서는 캡슐화를 포기하고 정적 시스템에서는 정적으로 입력 한 모든 시스템이 이러한 것들을 지원하기 때문에 작동하는 모델 (기능적 프로그래밍, 템플릿 등)으로 전환합니다.

인터페이스는 특히 다른 사람의 API에 직접 의존하는 경우 어느 정도의 오버 헤드를 추가 할 수 있습니다. 간단한 해결책 - 다른 사람의 API에 의존하지 마십시오.

각 객체가 이상적인 세상에 존재하기를 원했던 인터페이스와 대화하도록하십시오. 이렇게하면 스코프가 작은 작은 인터페이스로 끝납니다. 그렇게하면 인터페이스가 변경 될 때 컴파일 시간 장애가 발생합니다.

인터페이스가 작을수록 인터페이스가 변경 될 때해야 할 '부기'가 적습니다.

정적 타이핑의 실제 이점 중 하나는 어떤 메소드를 호출 할 수 있는지 정적으로 알지 못하지만 값 객체가 이미 검증되었다고 보장합니다 ... 이름이 필요하고 이름이 10 자 <인 경우 이름 클래스를 작성해야합니다. 그 유효성 검사를 캡슐화합니다 (반드시 I/O 측면은 아니지만 순수한 값 유형을 유지). 컴파일러는 런타임에 확인하지 않고 컴파일 시간에 오류를 잡을 수 있도록 도와줍니다.

정적 언어를 사용하려면 유리하게 사용하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top