oop - que - Pensamiento orientado a objetos de aprendizaje
que es un lenguaje orientado a objetos (16)
Hay un bloqueo en mi mente que me incapacita para ver dónde debería usar una clase y dónde no debería.
Cuando se trata de eso, las clases son una forma de separar los sistemas complejos en partes simples que interactúan entre sí. Intenta crear clases donde de lo contrario te estarías repitiendo.
En este momento, el indicador era un entero en la clase Plot.
¿El indicador necesita ser una clase? ¿Cuál sería la ventaja de convertirlo en una clase? Estas son el tipo de cosas que siempre debes hacerte a ti mismo.
- Los Game Engines son difíciles de diseñar. La separación de tales requisitos vagamente definidos es un proceso complejo, lea aquí: artículo sobre motores de juegos
- El diseño es iterativo y usted se refactorizará varias veces, no se sorprenda por esto.
Actualmente estoy trabajando en un pequeño motor de juego en 2D en C ++, pero ahora me enfrento a un daemon: apelo al diseño de un "sistema de clases" que realmente funciona. Hay un bloqueo en mi mente que me incapacita para ver dónde debería usar una clase y dónde no debería. Estaba leyendo un artículo sobre el diseño del motor y me propuse usar una clase ''State'' para administrar el estado de diferentes entradas del juego (estaba usando un int). También sugirió que todos los objetos del juego (no io / video / sonido, etc.) derivan de las clases Renderable o NonRenderable. Eso es inteligente. Ya sé que esa fue una manera inteligente de hacerlo, quiero decir, cada objeto en Java es de clase básica Objeto, ¿verdad? Inteligente, lo sé! ¿Cómo es que no lo hice de esa manera? ¿Qué tengo que leer para realmente entrar en esta forma de pensar?
Otro ejemplo. Estoy tomando este curso de verano en Ruby (realmente simple) y se supone que debemos diseñar un camping. ¡Sencillo! Entonces, un campamento es una colección de ''parcelas'' que cada una tiene un indicador eléctrico para medir cuánta energía ha consumido el invitado. Mi diseño consistía en tres clases, una para un Camping, que a su vez utilizaba matrices de clases de Invitado y Trama. Mi maestra sugirió que use más clases. WTF (!) Fue mi primer pensamiento, ¿dónde, qué clases? En mi opinión, todo era una clase, hasta que me di cuenta de que tal vez el indicador debería ser una clase. En este momento, el indicador era un entero en la clase Plot.
Quiero aprender cómo encontrar soluciones orientadas a objetos para mis problemas, ¡no solo cómo hacer las cosas más obvias en las clases!
Consejos / libros / artículos / blogs?
¡Tengo dos años en un título de collage en CS y he estado programando como un pasatiempo durante muchos años! Estoy "solo" atrapado, ¡y me está impidiendo crear cualquier pieza de software más grande!
En mi opinión, uno de los mejores libros que he leído para aprender conceptos orientados a objetos es:
El proceso de pensamiento orientado a objetos
Para mí, este libro realmente te hace pensar de una manera orientada a objetos (¡bien, la pista está en el título! :) Es bastante independiente del lenguaje, contiene algunos pequeños ejemplos de código en todo el texto en VB.NET, C # y Java y frecuentemente hace referencia a muchos "grandes" en el mundo del análisis y diseño de OO, como Grady Booch , Martin Fowler y otros.
Dado que el libro lo ayuda a pensar de una manera orientada a objetos, a menudo tomará un ejemplo específico y mostrará las diferencias entre la forma en que OO aborda un problema y la forma de proceder. Esto puede ser una gran ayuda si proviene de más o tiene antecedentes de procedimiento. También se refiere a cosas como UML para ayudar a explicar y comprender el diseño detrás de bibliotecas completas de clases (por ejemplo, marcos de trabajo) y la interacción entre clases y también el diseño de jerarquías de clases ricas usando conceptos tales como agregación y composición.
Escribe una gran cantidad de software, y durante todo el proceso, cuanto más grande sea, más extensibilidad necesitarás y más diseño de clase necesitarás, así que la próxima vez pensarás en el futuro y harás que tu diseño de clase sea bueno. al principio...
Hay un ensayo en el libro " ThoughtWorks Anthology " de Jeff Bay: "Object Calisthenics" en el que da un conjunto de reglas para el diseño de software OOP:
- Use solo un nivel de sangría por método
- No use la palabra clave else
- Ajustar todas las primitivas y cadenas
- Use solo un punto por línea
- No abreviar
- Mantenga todas las entidades pequeñas
- No use ninguna clase con más de dos variables de instancia
- Use colecciones de primera clase
- No use ningún getters / setters / properties
A primera vista, puede parecer demasiado estricto para seguir todas estas reglas. Tenga en cuenta que incluso si intenta escribir algún código que los vincule, será mejor diseñador de OOP.
Jaja. Recuerdo ese punto. Todo el "¿cómo diablos funciona esto?". Solo mantenlo, en algún momento solo hace clic. Realmente es como una bombilla pasando. En un momento no tiene sentido y luego, una fracción de segundo después, estás codificando todo en clases.
Intente descargar algunas de las herramientas de código abierto que probablemente terminará usando y lea el código. Te dará algo para hacer referencia a tu estilo de código.
Mi experiencia personal fue aprender Construcción de software orientada a objetos con Construcción de software orientado a objetos, segunda edición de Bertrand Meyer.
El libro fue invaluable para mí en ese momento, y sigue siendo el único libro del que he aprendido más sobre la programación de OO y la construcción de software en general.
Estos son algunos de sus puntos fuertes:
- En la Parte A: los problemas , una muy buena definición de la calidad del software.
- En la Parte B: El camino hacia la orientación a objetos , una búsqueda lógica paso a paso de técnicas OO de una manera que hace pensar al lector que la investigación se está realizando en vivo, es decir, como si aún no se conocieran los resultados. Probablemente adquirirás la mentalidad que estás buscando desde esta parte.
- En la Parte C: Técnicas orientadas a objetos , el núcleo técnico del libro, hará que sus conocimientos sean sólidos y aprenderá técnicas muy útiles sobre Diseño por Contrato, Herencia, Genericidad, etc.
- Parte D: metodología OO: aplicar bien el método es un enfoque más práctico sobre el diseño, que también me parece muy útil. Consulte, por ejemplo, Cómo encontrar las clases (22) , que puede encontrar en online .
Después de estas partes, aparecen temas más avanzados, como Concurrencia (30) o Bases de datos (31) .
Dado que el libro utiliza el lenguaje de Eiffel (diseñado por el autor), esto lo pondrá en la mentalidad correcta y le enseñará a pensar. Será fácil aplicar estas ideas a otros lenguajes de programación, más o menos OO.
Para mí, OO no ''hizo clic'' hasta que leí un libro sobre patrones de diseño. Si ya te sientes cómodo con conceptos como clases abstractas, interfaces, etc. eso es solo la mitad de la batalla.
El siguiente paso es averiguar por qué debería preferir la composición a la herencia, cómo codificar una interfaz y cómo escribir sus clases para que estén desacopladas y bien encapsuladas. Los patrones de diseño le muestran soluciones a problemas comunes de OO y le ayudan a estructurar su código siguiendo las pautas anteriores.
No puedo recomendar ningún libro en particular sobre C ++, pero el libro GOF es el estándar en Design Patterns (Java). Prefiero libros que hablen sobre patrones de diseño en un idioma particular para que pueda obtener ejemplos de códigos concretos. Patrones de diseño En Ruby es bastante bueno, como lo es PHP: Objects, Patterns and Practice .
Tengo la sensación de que tu instructor no sabe particularmente de lo que está hablando. ''Más clases'' es un consejo bastante inútil en sí mismo.
Peter Coad y Ed Yourdon escribieron un libro sobre esto hace dos años. Aunque no está lleno de nuevas metodologías sobrevaloradas, este libro proporciona una buena base para pensar en el estilo de los objetos.
Probablemente aprendí más sobre el desarrollo de software orientado a objetos de Craig Larman Aplicando UML y patrones: una introducción al análisis y diseño orientado a objetos y desarrollo iterativo .
En su enfoque, las clases se derivan de manera sistemática de los casos de uso:
- Los nombres en los casos de uso se asignan a las clases,
- verbos a los métodos y
- adjetivos a las variables miembro
Esto, por supuesto, funciona mejor para las nociones en el dominio del problema que, por ejemplo, widgets GUI. Sin embargo, comenzar con un caso de descripción / uso del programa que se escribirá me ayudó a encontrar mejores abstracciones que cuando omití ese paso.
Solo recuerda que nunca hay 1 solución a un problema. Convertir todo en una clase tampoco es la solución. Las cosas especialmente pequeñas (como el indicador) bien podrían ser un miembro int o float dentro de la clase de trama como lo hizo usted.
Mi sugerencia es que la práctica es un buen maestro. Solo sigue intentándolo y sigue leyendo. Con el tiempo, serás más y más fluido.
Tal vez le resulte útil Pensar en patrones de Bruce Eckel. Puedes descargar este libro de su sitio de forma gratuita (solo puedo publicar un enlace como nuevo miembro, así que simplemente haz clic en los enlaces que hay allí y podrás encontrarlo). Aunque, el libro es de 2003, tal vez las ideas presentadas en este libro lo ayudarán a crecer como programador en general.
Una de las cosas que ayudó a entrar en la mentalidad de OO, junto con las prácticas que han sido las publicaciones anteriores, es reescribir / mejorar el código existente que ha escrito utilizando los principios OO.
Por ejemplo :
a. En situaciones donde hay una gran cantidad de construcciones if / else, entonces probablemente se pueda pensar en tener una jerarquía de clases para distribuir los códigos de las ramas en consecuencia, y para usar el polimorfismo.
segundo. Cualquier uso de operadores como (instanceof en Java) indicaría la programación de tipos concretos y se puede pensar cómo deshacerse de la instancia de verificación.
do. Use "Law of Demeter" como guía y vea si el acoplamiento entre las clases es alto
Hasta cierto punto, la práctica de "Test Driven Development" también me ayudó, ya que te obliga a pensar en términos de interfaces / comportamiento para ser expuesto por una clase en lugar de solo concentrarte en cómo se puede codificar la mejor solución para un problema.
Una forma simple de encontrar un conjunto razonable de cosas que probablemente deberían ser objetos (y por lo tanto, clases): escriba una descripción del problema de su tarea, como:
En un camping hay invitados, y cada huésped tiene acceso a algunos puntos de venta. El software debe ser capaz de administrar la energía consumida por cada huésped, por lo que debe conocer los puntos de venta utilizados por un huésped y la energía consumida a través de cada punto de venta.
Ahora, cree una lista de todos los sustantivos para tener una buena idea de qué clases (= tipo de objetos) están involucradas en su problema:
- Lugar para acampar
- Huésped
- Salida
- Poder
Esta no es necesariamente una lista definitiva, pero es un buen comienzo.
Vale la pena recordar: OO no es un fin en sí mismo. El objetivo de OO es facilitar el desarrollo y, especialmente, el mantenimiento del código a lo largo de la vida útil del producto. Tenga cuidado con la mentalidad de "OO por amor de sí".
Head First: Análisis y diseño orientado a objetos
Me encanta Head First Books porque son divertidos de leer. Tienen ejercicios y acertijos para rascarse la cabeza. He leído este libro y lo encontré muy bien.
El libro cubre:
- Utilice los principios OO (encapsulación y delegación)
- Principio Abierto Cerrado (OCP)
- El Principio de Responsabilidad Individual (SRP)
- Patrones de diseño, UML, casos de uso, etc.
Orientado a objetos
La programación orientada a objetos se trata de pedir objetos para hacer algo: un concepto engañosamente difícil de aplicar correctamente.
Goban
Considere un tablero de juego 2D, como para jugar Go (llamado goban ).
Primero piense en el comportamiento que requiere para cumplir su tarea. Esto significa enumerar el comportamiento de un objeto en lugar de decidir sobre los datos manipulados por los comportamientos. Por ejemplo, una placa base puede tener los siguientes comportamientos:
- Coloca una piedra Go.
- Retire una piedra Go.
- Retire todas las piedras.
Para una versión de computadora de Go, es conveniente llamar la atención sobre áreas específicas:
- Marque una intersección (p. Ej., Triángulo, número, letra, círculo, cuadrado).
- Eliminar una marca de una intersección marcada.
- Elimina todas las marcas.
Tenga en cuenta que un goban no necesita proporcionar una manera de proporcionar a los clientes una referencia a la piedra en una intersección específica. En cambio, puede responder preguntas sobre su estado. Por ejemplo, un goban podría responder las siguientes preguntas:
- ¿Hay una piedra negra en una intersección dada?
- ¿Hay una piedra blanca en una intersección dada?
- ¿Hay una marca en una intersección dada?
No es responsabilidad del gobán saber el estado del juego: eso pertenece a una instancia de un Juego (que tiene Reglas ). En la vida real, un goban es simplemente un escenario para las piedras.
En este punto, podríamos escribir una interfaz para un goban sin saber cómo funcionará la implementación subyacente.
public interface Goban {
public void place( Stone stone, Point point );
public void removeStone( Point point );
public void removeStones();
public void place( Mark mark, Point point );
public void removeMark( Point point );
public void removeMarks();
public boolean hasWhiteStone( Point point );
public boolean hasBlackStone( Point point );
public boolean hasMark( Point point );
}
Observe cómo la junta está limpiamente separada de las Reglas y los Juegos . Esto hace que el goban sea reutilizable para otros juegos (que incluyen piedras e intersecciones). El goban podría heredar de una interfaz genérica (por ejemplo, una interfaz de la Junta ), pero esto debería ser suficiente para explicar una forma de pensar en términos de objetos.
Encapsulación
Una implementación de la interfaz de Goban no expone sus datos internos. En este punto, podría pedirte que implementes esta interfaz, escribas pruebas unitarias y me envíes la clase compilada cuando termines.
No necesito saber qué estructuras de datos has usado. Puedo usar su implementación para jugar (y representar) un Goban. Este es un punto crucial que muchos proyectos se equivocan. Muchos, muchos proyectos codifican lo siguiente:
public class Person {
private HairColour hairColour = new HairColour( Colour.BROWN );
public Person() {
}
public HairColour getHairColour() {
return hairColour;
}
public void setHairColour( HairColour hairColour ) {
this.hairColour = hairColour;
}
}
Esta es una encapsulación ineficaz. Considere el caso en el que a Bob no le gusta que su cabello tenga un color rosado. Podemos hacer lo siguiente:
public class HairTrickster {
public static void main( String args[] ) {
Person bob = new Person();
HairColour hc = bob.getHairColour();
hc.dye( Colour.PINK );
}
}
Bob ahora tiene el cabello teñido de rosa, y nada podría evitarlo. Hay formas de evitar esta situación, pero la gente no las hace. En cambio, la encapsulación se rompe, lo que da como resultado sistemas rígidos, inflexibles, plagados de errores e inmanejables.
Una posible forma de hacer cumplir la encapsulación es devolver un clon de HairColour
. La clase Person revisada ahora hace que sea difícil cambiar el color del cabello a Pink.
public class Person {
private HairColour hairColour = new HairColour( Colour.BROWN );
public Person() {
}
public HairColour getHairColour() {
return hairColour.clone();
}
public void setHairColour( HairColour hairColour ) {
if( !hairColour.equals( Colour.PINK ) {
this.hairColour = hairColour;
}
}
}
Bob puede dormir profundamente, sabiendo que no se despertará con un tinte rosado.