Pergunta

O que OOP princípios, se houver, não aplicam ou aplicam de forma diferente em uma dinamicamente tipada ambiente como oposição a uma estaticamente tipadas ambiente (por exemplo, Ruby vs C#)?Isto não é um apelo por uma Estático vs Dinâmico debate, mas eu gostaria de ver, se existem os princípios aceitos em ambos os lados da divisão que se aplicam a um e não a outro, ou aplicar de forma diferente.Frases como "prefira composição a herança" são bem conhecidos no estaticamente tipada orientada a objetos OOP literatura.Eles são apenas aplicáveis na dinâmica lado?

Por exemplo, em uma dinamicamente tipada ambiente, parece que a granularidade de acoplamento não vai mais do que o nível do método.Em outras palavras, qualquer chamada de função apenas casais chamador para que determinada interface, que qualquer classe poderia satisfazer-ou, para colocar de outra forma, qualquer coisa que grasna como particular pato.

Em Java, por outro lado, a granularidade de acoplamento pode ir tão alto como o pacote.Não só de um determinado método, chamada de estabelecer um contrato com outra classe/interface, mas também os casais em que as classes de interface/pacote/frasco/montagem.

Fazer diferenças como essa dão origem a diferentes princípios e padrões?Se para ter estas diferenças foram articuladas?Há uma seção no Ruby Picareta livro que vai nessa direção um pouco (Duck Typing/Classes não São Tipos), mas eu estou querendo saber se há mais alguma coisa.Eu estou ciente de Padrões de projeto em Ruby mas ainda não leu.

EDIÇÃO -- tem sido argumentado que Liskov não aplicar o mesmo em um ambiente dinâmico, como ele faz em um ambiente estático, mas eu não posso deixar de pensar que ele faz.Por um lado, não há alto nível de contrato com uma classe inteira.Mas não todas as chamadas para qualquer classe constitui um implícito contrato que precisa ser atendida pelo filho classes a forma de Liskov prescreve?Considere o seguinte.As chamadas no "fazer alguma barra de coisas" criar um contrato que precisa ser atendido pela criança classes.Esse não é um caso de "tratamento especializado objeto como se fosse uma classe base?":

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
Foi útil?

Solução

A diferença essencial que você está tocando em que eu acho que são:

  • línguas do grupo 1.os verdadeiros métodos que são invocados quando por exemplo objecto.method1, objeto.method2, objeto.method3 são chamados podem mudar durante o tempo de vida do objeto.

  • línguas do grupo 2.os verdadeiros métodos que são invocados quando por exemplo objecto.method1, objeto.method2, objeto.method3 são chamados não pode mudar durante o tempo de vida do objeto.

Idiomas no grupo 1 tendem a ter dinâmica de digitação e não de suporte de tempo de compilação verificada e interfaces de idiomas no grupo 2, tendem a ter tipagem estática e para suporte de tempo de compilação chcked interfaces.

Eu diria que todos os princípios OO se aplicam a ambos, mas

  • alguns extras (explícita) de codificação de implementação de tempo de execução em vez de em tempo de compilação) verifica poderá ser requerido, no grupo 1 para afirmar que novos objetos são criados com todos os métodos adequados marcada para satisfazer um contrato de interface como não há tempo de compilação interface-acordo de verificação, (se você quer fazer grupo 1 código mais como grupo 2)

  • alguns codificação extra poderá ser requerido, no grupo 2 para mudanças do modelo de real método de chamada para uma chamada de método usando extra de estado de sinalizadores para chamar submethods, ou para embrulhar o método ou um conjunto de métodos em uma referência a um dos vários objetos ligados ao objeto principal, onde cada um dos vários objetos de diferentes implementações do método, (se você quer fazer grupo 2 código mais como grupo 1 código)

  • muito restrições no design, no grupo 2 linguagens de torná-los melhor para projetos maiores, onde a facilidade de comunicação (como oposição a compreensão torna-se mais importante

  • a falta de restrições no design, no grupo 1 línguas faz com que o melhor para projectos de menor dimensão, onde o programador pode mais facilmente verificar se a vários projeto de canalização restrições são atendidas em um relance, simplesmente porque o código é menor

  • tornar o código a partir de um grupo de idiomas como o outro é interessante e vale a pena estudar, mas a ponto de as diferenças de linguagem é realmente a ver com o quão bem eles ajudam a diferentes tamanhos de equipes ( - eu acredito!:) )

  • existem várias outras diferenças

  • mais ou menos perna-de trabalho podem ser necessárias para implementar um design OO em uma língua ou outra, dependendo do exato princípios envolvidos.


EDITAR

Então, para responder sua pergunta original, examinei

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

E

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

Na prática, os princípios OO não são seguidas por várias boas razões (e, claro, algumas más) de um sistema.Boas razões incluídos, onde as preocupações com o desempenho superam puro design preocupações de qualidade, onde quer que benefícios culturais alternativos estrutura e nomenclatura superam puro design preocupações de qualidade, e onde o custo do trabalho adicional de implementação de uma função não de forma padrão para um determinado idioma supera os benefícios de um design puro.

Grau de moagem mais grosso rigorosos padrões como o Abstract Factory, Builder, Método de Fábrica, desenvolvimento de Protótipo, Adaptador, Estratégia, Cadeia de Comando, Ponte, Proxy, Observador, Visitantes e até mesmo MVC/MMVM tendem a ficar menos usado em sistemas de pequeno porte, pois a quantidade de comunicação sobre o código é menor, portanto, o benefício da criação de tais estruturas não é assim tão grande.

Mais refinada padrões como o Estado, Comando, Método de Fábrica, Composite, Decorator, Fachada, Flyweight, Memento, método de Modelo são, talvez, mais comum no grupo 1 do código, mas, muitas vezes, vários padrões de projeto não se aplicam a um objeto como tal, mas para as diferentes partes de um objeto enquanto que no grupo 2 padrões de código tendem a estar presentes em um padrão por objeto base.

IMHO faz muito sentido na maioria grupo 1 idiomas para pensar global de todos os dados e funciona como uma espécie de singleton "Aplicação" do objeto.Eu sei que estamos chegando a borrar as linhas entre Processuais e programação OO, mas este tipo de código, definitivamente, grasna como um "Aplicativo" objeto em muitos casos!:)

Alguns muito refinado e padrões de projeto Iterator tendem a ser construído no grupo 1 línguas.

Outras dicas

Deixe-me começar por dizer que, pessoalmente, uma OOP princípio de que não funciona em ambos dinâmica e estaticamente tipada línguas não é um princípio.

Dito isto, aqui está um exemplo:

A Interface Segregation Principle (http://objectmentor.com/resources/articles/isp.pdf) afirma que os clientes devem depender mais de interface específica que atenda às suas necessidades.Se o código do cliente precisa usar dois métodos da classe C, C deve implementar a interface, I, contendo apenas estes dois métodos e o cliente vai usar, ao invés de C.Este princípio é irrelevante em linguagens de tipo dinâmico, onde as interfaces não são necessários (desde interfaces definidas tipos e tipos não são necessários em um idioma no qual as variáveis são de tipo menos)

[editar]

Segundo exemplo - A Dependência Inversão de Princípio (http://objectmentor.com/resources/articles/dip.pdf).Este princípio defende é "a estratégia da consoante as interfaces ou funções abstratas e classes, ao invés de na de concreto funções e classes".Novamente, em linguagem dinamicamente tipada código do cliente não depende de nada - ele especifica o método de assinaturas - tornando-se óbvia a este princípio.

Terceiro exemplo - Liskov Substitution Principle (http://objectmentor.com/resources/articles/lsp.pdf).O texto do livro de exemplo para este princípio é um Quadrado de classe que subclasses de uma classe Retângulo.E, em seguida, o código de cliente que invoca um setWidth() o método em um Retângulo variável é surpreendido quando a altura é também alterado desde que o objeto real é um Quadrado.Novamente, em uma linguagem dinamicamente tipada as variáveis são de tipo menos, o Retângulo de classe não estará mencionado no código de cliente e, portanto, não há tais surpresas irão surgir.

Eu tenho um "radical" de vista sobre tudo isso:na minha opinião, apoiada pela matemática, OOP não funciona em um tipo estático ambiente para quaisquer problemas interessantes.Eu defino interessante como significado abstrato de relações envolvidas.Isso pode ser comprovado facilmente (consulte "covariância problema").

O núcleo do problema é que os conceitos de OOP prometer é uma maneira de modelo de abstrações e combinado com o contrato de programação entregues por tipagem estática, as relações não podem ser implementados sem quebrar o encapsulamento.Basta tentar qualquer covariante operador binário para ver:tentar implementar "menor que" ou "adicionar" em C++.Você pode codificar a base de abstração facilmente, mas você não pode implementá-lo.

Em sistemas dinâmicos não há alto nível formalizado tipos e não de encapsulamento para se preocupar com isso OO realmente funciona, em particular, o desenvolvimento de sistemas como o original Smalltalk, na verdade, fornecer modelos de trabalho que não pode ser codificado com tipagem estática restrições.

Para responder a pergunta de outra forma:o pressuposto fundamental da questão é intrinsecamente falho.OO não tem qualquer coerente de princípios, porque não é uma teoria consistente porque não existem modelos com poder suficiente para lidar com qualquer coisa, mas simples tarefas de programação.O que difere é que você desista:em sistemas dinâmicos com que você desista de encapsulamento, estáticos, sistemas de você acabou de mudar para modelos que não funcionam (programação funcional, modelos, etc), pois todas as estaticamente tipada sistemas de suporte a essas coisas.

Interfaces pode adicionar algum nível de sobrecarga, especialmente se você diretamente depender de alguém API.Solução simples - não dependem de outra pessoa API.

Cada objeto de falar com as interfaces que o desejasse poderia existir em um mundo ideal.Se você fizer isso, você vai acabar com pequenas interfaces que têm pequeno alcance.Fazendo isso, você vai ganhar o tempo de compilação de falhas quando a mudança de interfaces.

O menor e mais específico de suas interfaces são, a menos 'contabilidade' você vai ter que fazer quando uma interface alterações.

Um dos benefícios reais de tipagem estática não é estaticamente saber quais os métodos que você pode chamar, mas garantindo que os objetos de valor já estão validados...se você precisa de um nome, e um nome tem de ser < 10 caracteres, crie um Nome de classe que encapsula que o processo de avaliação (embora não necessariamente de e/S de aspectos - manter-se puro tipo de valor), e o compilador pode ajudar a detectar erros em tempo de compilação ao invés de você ter que verificar em tempo de execução.

Se você estiver indo para usar uma linguagem estática, use isso em sua vantagem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top