Pregunta

¿Qué principios de la programación orientada a objetos, si los hubiere, no se aplican o se aplican de manera diferente en un dinámicamente tipado medio ambiente frente a un estáticamente tipado medio ambiente (por ejemplo Ruby vs C#)?Esto no es una llamada para un vs Estática Dinámica de debate, sino más bien me gustaría ver si hay principios aceptados en cualquiera de los lados de la brecha que se aplican a uno y no al otro, o se aplican de manera diferente.Frases como "prefiero que la composición de la herencia" son bien conocidos en la estáticamente tipado la programación orientada a objetos la literatura.Son sólo aplicables en el lado dinámico?

Por ejemplo, en un dinámicamente tipado de medio ambiente, parecería que la granularidad de acoplamiento no va más allá que el nivel del método.En otras palabras, cualquier llamada de función no sólo de las parejas de la llamada a ese interfaz en particular, que cualquier la clase podría satisfacer -- o para decirlo de otra manera, cualquier cosa que grazna como particular pato.

En Java, por otro lado, la granularidad de acoplamiento puede ir tan alto como el paquete.No sólo un método en particular, llame a establecer un contrato con otra clase/interfaz, pero también a las parejas en que las clases de interfaz/paquete/jar/asamblea.

Hacer diferencias, como este dan lugar a diferentes principios y patrones?Si es así tienen estas diferencias han sido articuladas?Hay una sección en la Ruby Pico libro que va en esta dirección un poco (Pato escritura/Clases no Son Tipos), pero me pregunto si hay algo más.Soy consciente de Patrones de diseño en Rubí pero no lo he leído.

EDITAR -- Se ha argumentado que Liskov no se aplica la misma en un entorno dinámico como lo hace en un entorno estático, pero no puedo dejar de pensar en que lo hace.Por un lado no es de alto nivel de un contrato con una clase entera.Pero no todas las llamadas a cualquier clase constituyen una implícito contrato que debe ser satisfecho por el niño de las clases de la forma de Liskov prescribe?Considere el siguiente.Las llamadas en "hacer algo de la barra cosas" crear un contrato que debe ser atendido por el niño de las clases.No es este un caso de "tratamiento especializado de objetos como si se tratara de una clase 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
¿Fue útil?

Solución

La diferencia esencial se está tocando en la que creo que son:

  • idiomas grupo 1. los métodos actuales que se invocan cuando, por ejemplo object.method1, object.method2, object.method3 son llamados puede cambiar durante la vida del objeto.

  • idiomas grupo 2. Los métodos reales que se invocan cuando, por ejemplo object.method1, object.method2, object.method3 se llaman no pueden cambiar durante la vida del objeto.

Las lenguas en el grupo 1 tienden a tener tipado dinámico y no apoyar en tiempo de compilación comprueba interfaces y lenguajes en el grupo 2 tienden a tener tipos estáticos y para dar soporte a interfaces chcked de tiempo de compilación.

Yo diría que todos los principios OO se aplican a ambos, pero

  • un poco de sobrepeso (explícita) que codifica para poner en práctica (en tiempo de ejecución en lugar de tiempo de compilación) cheques pueden ser requeridos en el grupo 1 de afirmar que los nuevos objetos son creados con todos los métodos apropiados sondeado para cumplir con un contrato de interfaz como se no existe en tiempo de compilación interfaz de acuerdo, (si quieres hacer que el código del grupo 1 más como grupo 2)

  • algo de código adicional puede ser necesaria en el grupo 2 para modelar los cambios del método actual invocado para una llamada al método mediante el uso de indicadores del estado de extras para llamar submétodos, o para concluir el método o un conjunto de métodos en una referencia a uno de los varios objetos adheridos al objeto principal, donde cada uno de los varios objetos tiene diferentes implementaciones de métodos, (si quieres hacer que el código del grupo 2 más como código de grupo 1)

  • las mismas restricciones sobre el diseño en el grupo 2 idiomas a tomar mejores para proyectos más grandes donde la facilidad de la comunicación (en contraposición a la comprensión) se vuelve más importante

  • la falta de restricciones en el diseño del grupo 1 Los idiomas hace entonces es mejor para los proyectos más pequeños, donde el programador puede comprobar más fácilmente si se cumplen las diversas limitaciones de diseño de plomería de un vistazo, simplemente porque el código es más pequeña

  • hacer el código de un grupo de lenguas como el otro es interesante y bien vale la pena estudiar, pero el punto de las diferencias de idioma es realmente que ver con lo bien que ayudan a diferentes tamaños de equipos (- Creo :))

  • hay varias otras diferencias

  • más o menos la pierna-trabajo puede ser necesaria para implementar un diseño orientado a objetos en un idioma u otro en función de los principios exactos involucrados.


editar

Así que para responder a su pregunta original, examiné

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

y

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

En la práctica los principios OO no se siguen por diversas razones (y, por supuesto, otras malas) en un sistema. Buenas razones incluidas en donde los problemas de rendimiento superan a las preocupaciones puros de calidad de diseño, siempre que los beneficios culturales de alternativa estructura / nombres superan los problemas de calidad de diseño puro y donde el costo del trabajo extra de la aplicación de una función no de la manera estándar para un idioma en particular es mayor que los beneficios de la un diseño puro.

patrones de grano más grueso como Abstract Factory, Builder, Factory Method, Prototype, adaptador, Estrategia, cadena de mando, Puente, Proxy, Observador, Visitante e incluso MVC / MMVM tienden a acostumbrarse menos en los sistemas pequeños debido a que la cantidad de la comunicación sobre el código es menor, por lo que el beneficio de la creación de este tipo de estructuras no es tan grande.

patrones

de grano fino como Estado, Comando, Factory Method, compuesto, decorador, Fachada, peso mosca, Memento, el método de la plantilla son tal vez más común en el código de grupo 1, pero a menudo varios patrones de diseño se aplican a un objeto como tal, sino a diferentes partes de un objeto mientras que en el grupo 2 patrones de código tienden a estar presentes en un un patrón por base objeto.

MIHO tiene mucho sentido en la mayoría de los idiomas del grupo de 1 a pensar en todos los datos globales y funciona como una especie de objeto singleton "Aplicación". Sé que estamos llegando a difuminar las líneas entre la programación de procedimiento y OO, pero este tipo de código definitivamente grazna como un objeto "Aplicación" en muchos casos! :)

Algunos patrones de diseño muy de grano fino como iterador tienden a ser integrado en los grupos 1 idiomas.

Otros consejos

Permítanme comenzar diciendo que, en lo personal, un principio de programación orientada a objetos que no funciona en ambos idiomas de tipo dinámico y estático no es un principio.

Dicho esto, he aquí un ejemplo:

La Interfaz Segregación Principio ( http://objectmentor.com/resources/articles/isp. pdf ) afirma que los clientes deben depender de la interfaz más específico que se adapte a sus necesidades. Si el código de cliente tiene que utilizar dos métodos de la clase C, entonces C debe implementar la interfaz, I, que contiene sólo estos dos métodos y el cliente utilizará I en lugar de C. Este principio es irrelevante en idiomas tipos dinámicos en los que no se necesitan las interfaces (ya que las interfaces Los tipos definidos, y no son necesarios los tipos en un lenguaje donde las variables son de tipo menos)

[editar]

Segundo ejemplo - La dependencia Inversion Principio ( http://objectmentor.com/resources/articles /dip.pdf ). Este principio sostiene es "la estrategia de depender de interfaces o funciones abstractas y clases, en lugar de en las funciones y clases concretas". Una vez más, en tipos dinámicos código de cliente lenguaje no depende de nada - sólo se especifica firmas de método -. Obviando de este modo este principio

Tercer ejemplo - principio de sustitución de liskov ( http://objectmentor.com/resources/articles/ lsp.pdf ). El ejemplo de libro de texto de este principio es que una clase Plaza subclases de una clase Rectángulo. Y luego el código de cliente que invoca un método setWidth () sobre una variable del rectángulo se sorprende cuando la altura también se cambia ya que el objeto real es un cuadrado. Una vez más, en un lenguaje de tipos dinámicos las variables son de tipo menos, la clase Rectangle no se menciona en el código del cliente y por lo tanto no surjan tales sorpresas.

Tengo un "radical" ver en todo esto:en mi opinión, respaldado por las matemáticas, la programación orientada a objetos no funciona en un tipo estático ambiente para cualquier problemas interesantes.Puedo definir muy interesante, en el sentido de las relaciones abstractas están involucrados.Esto puede ser demostrado fácilmente (ver "la covarianza problema").

El núcleo de este problema es que los conceptos de la programación orientada a objetos promesa es una forma de modelo de abstracciones y combinado con el contrato de programación entregada por el tipo estático, las relaciones no pueden ser aplicadas sin romper la encapsulación.Sólo trate de cualquier covariante operador binario para ver:tratar de implementar "menos que" o "agregar" en C++.Puede codificar la base de la abstracción con facilidad, pero no se puede implementar.

En los sistemas dinámicos no hay ningún alto nivel formalizado tipos y no encapsulación de molestar con tan OO realmente funciona, en particular, prototipo basado en sistemas como el original de Smalltalk realmente proporcionan modelos de trabajo que no puede ser codificado a todos con tipos estáticos restricciones.

Para responder a la pregunta de otra manera:el supuesto fundamental de la cuestión es instrinsically defectuoso.OO no tiene ningún coherente de principios, ya que no se trata de una coherente teoría, porque no existen modelos con potencia suficiente para manejar cualquier cosa, pero simple de las tareas de programación.Lo que varía es lo que usted da para arriba:en la dinámica de los sistemas de renunciar a la encapsulación, en sistemas estáticos que acaba de cambiar a los modelos que hacer el trabajo (programación funcional, plantillas, etc) ya que todos los de tipo estático de los sistemas de apoyo a estas cosas.

Las interfaces pueden añadir un cierto nivel de sobrecarga, especialmente si depende directamente de la API de otra persona. Una solución simple -. no dependen de la API de otra persona

Haga que cada charla objeto a las interfaces que deseaba existiría en un mundo ideal. Si usted hace esto, usted va a terminar con pequeñas interfaces que tienen pequeño alcance. Al hacerlo, obtendrá los fallos en tiempo de compilación cuando se cambian las interfaces.

Los más pequeños y específicos de sus interfaces son, la 'contabilidad' menos que tendrá que hacer cuando una interfaz cambia.

Uno de los beneficios reales de la tipificación estático no es estática Saber qué métodos se pueden llamar, pero garantizando que los objetos de valor ya están validados ... Si necesitas un nombre y un nombre tiene que ser <10 caracteres, cree una nombre de la clase que encapsula la certificación. (aunque no necesariamente todos los aspectos de I / O - que sea un tipo de valor puro), y el compilador puede ayudar a detectar errores en tiempo de compilación, en lugar de tener que verificar en tiempo de ejecución

Si va a utilizar un lenguaje estático, lo utilizan a su ventaja.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top