Programación orientada a objetos: cuando comienzo un proyecto, nunca sé cómo comenzar. ¿Cómo puedo arreglar eso?

Trabaje desde afuera hacia adentro. Necesita un programa que muestre una ventana con tres cuadros de texto y un botón, y cuando ingresa texto en los tres y hace clic en el botón, hace algo interesante con el texto para producir un resultado que se muestra en una ventana emergente diálogo. Todo eso es muy desalentador cuando nos fijamos en el trabajo a realizar en su conjunto.

Pero, ¿cómo te comes un elefante? Un bocado a la vez. En primer lugar, necesitas un programa. Por lo tanto, escriba el código básico requerido para un programa válido que se inicia y se detiene sin hacer nada. Ahora, el código debe mostrar una ventana. Por lo tanto, cree una ventana básica, sin nada, y escriba el código para mostrar esa ventana al usuario. Ahora, cuando ejecuta el código, obtiene una ventana en blanco; oye, estás en camino, el programa está haciendo algo. Ahora, agregue tres cuadros de texto y un botón. Ahora el formulario se ve como algo, y puede ingresar texto. Por último, escriba el código que hace las cosas interesantes al texto en los cuadros de texto. Finalmente, escriba el código que muestra una ventana emergente al usuario con los resultados de este interesante cálculo.

Haz un poco de trabajo de diseño por adelantado. Si bien el desarrollo de afuera hacia adentro es una buena mentalidad para tener en todo momento, a veces es necesario tener un mapa más definido de cómo proceder. Esto puede ser para que no te codifiques en una esquina, o para que puedas dividir el trabajo entre múltiples desarrolladores mientras aseguras que lo que las otras personas están codificando funcionará con tu código. Entonces, haga el mismo proceso de afuera hacia adentro, excepto que en lugar de hacer el trabajo, describa el trabajo, comenzando desde el resumen “necesitamos un programa” hasta el “QuickSort esta lista por una expresión particular” (o incluso más específico) dependiendo de tu idioma y de lo que estés haciendo).

Considere la “narrativa del caso de uso”. Mire el programa desde la perspectiva de la persona que lo usará. ¿Qué esperan que tengan que hacer y qué esperarían como resultado cuando lo hicieran? Codifique el programa para cumplir con esas expectativas, y nada más. Luego, considere otra narrativa de un caso de uso superpuesto. Agregue más código para cumplir con esas nuevas expectativas. Continúe agregando código para cumplir con cada nueva narrativa de casos de uso, hasta que el código haga todo lo que el usuario necesita que haga.

No te atasques en detalles. Puede perderse fácilmente en los bits y bytes de un sub-algoritmo particular de su programa. Debes ser lo suficientemente inteligente como para darte cuenta de cuándo sucede esto, dar un paso atrás y mirar la imagen más grande. ¿El código que está escribiendo hace su trabajo correctamente y tan rápido como tiene que hacerlo? Entonces sigue adelante . Deja de preocuparte por cómo se ve o cómo está diseñado; Lo más probable es que nunca lo vuelvas a ver.

Haz que funcione, hazlo limpio, hazlo SÓLIDO. Esta es mi regla de “tres golpes” para trabajar con una línea o bloque de código. Cuando se escribe una línea de código por primera vez, no obtiene puntos de estilo para sumar 2 y 2. Haga lo que tiene que hacer y asuma, como en el punto anterior, nunca volverá a ver esa línea de código. Sin embargo, la próxima vez que coloque el cursor en esa línea de código, acaba de refutar esa suposición original. Regresará para corregir o extender el código para que haga lo que hace mejor o haga más. Mientras lo hace, busque formas de “limpiar” el código, refactorizando las declaraciones repetidas en bucles, bloques repetidos en métodos, nombrando variables de forma más intuitiva (pero concisa), etc. Ahora el código debe ser correcto y fácil de entender.

La próxima vez que regrese a este código, probablemente sea un gran problema; o se le pide que haga aún más, o necesita hacerlo en más lugares. Ahora, debe comenzar a prestar atención a los principios de diseño orientado a objetos y las mejores prácticas, como SOLID o GRASP. Prefiero SOLID ya que sus reglas son un poco más definidas; GRASP es un poco más intuitivo y subjetivo, y aunque muy poco es absoluto en el diseño del programa, es mejor IMO definir el ideal y trabajar para lograrlo, en lugar de definir cómo mejorarlo sin definir cuándo ha terminado.

Las reglas SÓLIDAS son:

SRP – Principio de responsabilidad única: un objeto de código (método, clase, interfaz) idealmente debe tener exactamente una razón para cambiar. Este es el ideal del principio general de diseño de “alta cohesión”; todo el código dentro de un objeto debe estar relacionado con un propósito de alcance limitado. Es la base de un buen diseño orientado a objetos, la creación de “código de raviolis”; fragmentos de código del tamaño de un bocado que se pueden examinar individualmente o en combinación con otros.

OCP: principio abierto / cerrado: idealmente, un objeto debe estar abierto a cualquier extensión, pero cerrado a cualquier cambio. Al agregar código para admitir algún comportamiento nuevo, idealmente no debería existir un código correcto existente. Esto se debe a que cualquier código que cambie tiene el potencial de error y, por lo tanto, debe volver a probar todos los casos de uso originales del código modificado. Además, al agregar este nuevo código al código existente, le da al código dos razones para cambiar; un cambio en el comportamiento existente o nuevo En cambio, es mejor “extender” el código original, ya sea derivando una nueva clase de la existente para implementar un nuevo comportamiento, o dando a la clase existente una referencia al nuevo código que puede usar en cierto modo ya está familiarizado (como una nueva devolución de llamada o un controlador de eventos).

Este es un poco falso porque un programa nunca puede cerrarse a todo tipo de cambio. En cambio, el objetivo es identificar cómo es probable que tenga que cambiar un fragmento de código y diseñarlo para que el cambio identificado pueda ocurrir mediante la extensión del objeto en lugar de agregar más código dentro de él.

LSP – Principio de sustitución de Liskhov: Un objeto A, que depende de un objeto B, debe poder usar cualquier C que se derive de B sin saber la diferencia. Esto básicamente significa que el uso de cualquier objeto que exponga una “interfaz” particular a sus consumidores debe ser idéntico a cualquier otro objeto que exponga la misma interfaz; no se necesita conocimiento especializado del objeto exacto que se utiliza. Esto se relaciona con el OCP y SRP; un nuevo objeto que viola el LSP, por ejemplo, al requerir que se llame a un método nuevo para inicializarlo, requiere que cada uso de la interfaz cambie para incorporar el cambio en el uso, y también requiere que cada clase existente en la familia cambie para exponer el nuevo método incluso si no lo necesitan.

ISP – Principio de segregación de interfaz: muchas interfaces con pocos métodos son mejores que pocas interfaces con muchos métodos. Este es básicamente el SRP para interfaces. Si tiene una interfaz con tres métodos, y agrega un parámetro a uno de ellos, cada implementación de la interfaz debe cambiar para acomodar el nuevo parámetro, cada uso del método debe cambiar para pasarlo, y cada uso de la interfaz misma al menos debe volver a compilarse, incluso si no utiliza ese método en absoluto . Por lo tanto, evitar esta situación es una ventaja definitiva; Si el uso de una interfaz no utiliza un método particular, tal vez ese método no pertenezca a esa interfaz específica.

Todavía se debe tener cuidado para adherirse al SRP. El código con un solo propósito, la mayoría de las veces, implementa una única interfaz que le permite cumplir el propósito.

DIP – Principio de inversión de dependencia: los objetos de código nunca deberían depender de objetos concretos, sino de abstracciones. Un objeto A que tiene que saber sobre B tendrá que cambiar si alguna vez desea utilizar C en su lugar. Por el contrario, si A dependiera de una interfaz I, que tanto B como C implementaron, A no tendría que cambiar cuando cambiara B por C. Esta es la esencia del “acoplamiento flojo”, y va junto con el LSP y el OCP ; poder intercambiar una dependencia por otra sin ningún cambio en el uso significa varias cosas que son buenas para el codificador. Es más fácil reorganizar los objetos para hacer algo diferente sin necesidad de volver a codificar las piezas. Es más fácil probar cada objeto de código de forma aislada conectando dependencias “ficticias” como simulacros y trozos. Es más fácil entender el propósito básico de un objeto de código (y, por lo tanto, su “razón para cambiar”).

Si este es un proyecto personal, recomendaría comenzar con algo pequeño. Digamos que estás haciendo un juego de Mario. Comience por hacer la plataforma inferior y una gota que represente a Mario. ¿Puedes programar algo para que salte? Moverse a izquierda y derecha? Luego intente agregar algunas plataformas más sobre las que pueda saltar. ¿Se pueden generar las ubicaciones sobre la marcha en lugar de codificadas? ¿Qué tal hacer algunos monstruos para que él salte?

Ningún proyecto comienza perfecto, y hacer diagramas UML, para mí, es tan aburrido como el infierno. Claro, tendrá que reescribir / refactorizar mucho código de esta manera, pero es de esperar que el progreso lo mantenga motivado más que algunos diagramas abstractos, sin mencionar que la funcionalidad de refactorización / extensión es una habilidad clave para un programador. ¡Que te diviertas!

Me gusta la idea de un esqueleto ambulante : “una pequeña implementación del sistema que realiza una pequeña función de extremo a extremo. No necesita usar la arquitectura final, pero debe unir los componentes arquitectónicos principales. La arquitectura y la funcionalidad entonces puede evolucionar en paralelo “. Básicamente, una aplicación HelloWorld glorificada que se conecta a la base de datos y sirve una página web de una línea, por ejemplo. También configuré la infraestructura básica del proyecto, como el control de versiones y el marco de prueba.

Desde allí, puede proceder de la manera que prefiera: diseño inicial frente a emergente, de abajo hacia arriba frente a arriba hacia abajo, prueba primero versus prueba después, etc.


Intente escribir una historia que describa lo que su programa tiene para los datos y lo que hace con los datos. Lea su historia, identifique sustantivos (probablemente serán objetos), verbos (probablemente serán métodos o pistas sobre atributos importantes de los objetos) y, de lo contrario, transforme su narrativa en un primer borrador de la estructura de la clase,

Entonces comience a programar.

Encuentra errores, reestructura las clases, repite. Cuando encuentre patrones repetitivos, la reestructuración incluirá hacer clases base y heredar de ellas para tratar con detalles.

No soy un experto en OO, pero así es como haría las cosas:
Diseñe primero la interfaz, la interfaz de todo el sistema.
por ejemplo: si quiero construir un televisor, primero comenzaría por diseñar el control remoto y construir el televisor como un dispositivo que responda al control remoto.

lo que pones en la interfaz depende exactamente de cuál es el servicio que tu sistema está proporcionando al usuario.

Una vez que haya terminado de decidir la interfaz del sistema, cree interfaces de los componentes independientes dentro del sistema.

ahora extienda esas interfaces con código concreto.

siempre funcionó para mí, cuando no lo hizo, principalmente porque no tenía suficiente conocimiento de dominio.

ahora cierra los ojos, respira hondo, exhala lentamente y mientras exhalas repite después de mí “todo es un objeto”.

Te recomiendo que aprendas algo de UML, porque proporciona una gran variedad de formas de pensar sobre tu proyecto. Algunos ejemplos de los tipos de diagramas UML que a menudo encuentro útiles:

  • Los diagramas de casos de uso lo ayudan a pensar cómo las personas u otros sistemas interactuarán con su proyecto
  • Si su proyecto será muy complejo, los diagramas de componentes pueden ayudarlo a manejarlo (aunque para un proyecto de una sola persona, esto probablemente no sea necesario)
  • Si habrá una cadena compleja de eventos en algún lugar, los diagramas de secuencia pueden ayudarlo a definir eso
  • Los diagramas de clase deben ser el último paso antes de comenzar a programar y ayudarlo a mapear las clases que necesitará y las relaciones entre ellas. Una vez que hayas hecho esto, ¡apuesto a que un punto de partida te salta a la vista!

Al principio, UML puede parecer complejo y desalentador, pero no se preocupe: puede recoger muchas de las ideas más útiles de él en las primeras horas de aprender sobre él; todo lo demás es solo detalle. No necesita dibujar diagramas UML para todo el proyecto, solo para las áreas en las que desea pensar. Y no necesita usar una sintaxis UML perfectamente correcta, simplemente dibuje lo que tenga sentido para usted. Es una herramienta para ayudarlo a pensar en su proyecto, no una especificación precisa.

Como beneficio adicional, con un poco más de aprendizaje, puede usar UML como una especificación precisa, como documentación posterior al proyecto y / o como una forma de discutir el software con sus colegas, en otras palabras, como una herramienta de comunicación . Por supuesto, en ese caso debe ser preciso sobre cómo obtener la sintaxis UML correcta para que pueda comunicarse con claridad. Pero cuando lo usas solo para ti, esas cosas no importan.

No considere codificar de inmediato. Planifique su proyecto, defina cuántos tipos de usuarios van a usar el proyecto y qué deben poder hacer. Luego dibuje diagramas de casos de uso para aclarar quién hará qué en su programa. Luego, constriñe las estructuras de sus clases en un papel, se llama diagramas de clases . Después de eso, debería ser fácil convertir tu idea en un programa

  1. Encuentra los sustantivos en tu dominio problemático. Estos pueden ser representados por clases.
  2. Identificar las relaciones entre los sustantivos. Una relación “tiene un” implica composición o agregación. “es un” implica herencia. En general, hay mucha más composición que herencia. En caso de duda, favorezca la composición sobre la herencia.
  3. Enumere las operaciones que puede solicitar a sus sustantivos que realicen. Las operaciones son verbos representados por métodos en sus clases.
  4. Algunos sustantivos representan conceptos abstractos, serán clases abstractas. Algunas operaciones sobre conceptos abstractos también pueden ser abstractas. Si no tiene sentido, no lo hagas.
  5. No lo pienses demasiado. Mantenlo simple. Comience de manera simple con algunas clases críticas y pruébelo. Si parece antinatural, algo está mal con el modelo. Revise con los miembros del equipo para asegurarse de que los sustantivos y verbos que elija tengan sentido.

Primero iría con su proyecto general. ¿Cuál es el objetivo del proyecto, cómo funcionará y cuál será el resultado esperado? Alguien más lo mencionó también, no comience el proyecto saltando en la codificación: haga una hoja de ruta, haga diagramas, haga un diagrama de flujo, haga un plano … etc. No empiece a construir una casa saliendo y comprando madera y no construyes una computadora comprando componentes aleatorios con la esperanza de que todos funcionen juntos.

Ahora hay funciones o clases generales que podría usar, pero ya deberían estar en su arsenal. Trabaja primero en la imagen más grande.

Solo tienes que hacer un poco de planificación. Personalmente, me gusta hacer un diagrama de flujo simple que muestre cómo funcionará el programa. Esto ayudará a organizar sus pensamientos e identificar las diferentes partes del sistema y cómo interactúan. Después de eso, haga algunos gráficos de clase usando UML o algo similar. Una vez hecho esto, tendrá una idea clara de dónde comenzar y qué clases crear. Y tenga en cuenta que este proceso de planificación no necesariamente tiene que ser complicado o tomar mucho tiempo.

La forma en que suelo diseñar algo no trivial es usando un grupo de gnomos que guardo en mi bolsillo trasero. Nadie más puede ver esos gnomos, por lo que la gente tiende a llamarlos gnomos imaginarios, pero sé que están allí.

Entonces, trato de ver cómo puedo hacer que los gnomos hagan el trabajo. Estos gnomos son un poco irritables. Si les dices que hagan algo, lo harán. Por ejemplo, si le digo a un gnomo que lea un archivo, no lo analizará. Además, son un poco antisociales. No les gusta hablar con otras personas, mucho menos entre ellos. Hablarán con otro gnomo si es necesario, pero cuantos más gnomos tengan que hablar, más malhumorados se pondrán. Como no les gusta hablar conmigo también, es difícil para mí decirle a 2 gnomos que hagan lo mismo. Es mejor para mí encontrar una manera para que un gnomo haga solo una cosa, y que ningún otro gnomo haga lo mismo. ¿No diría que estaban de mal humor? ¡Aunque los amo!

Entonces, tomo mis malhumorados gnomos antisociales y hago que resuelvan el problema que quiero resolver. Con el tiempo, he descubierto ciertas cosas que funcionan bien con estos gnomos. Por ejemplo, tener un gnomo responsable de hablar con el mundo exterior es mejor que el mundo que habla con cada gnomo. Entonces, tengo un gnomo de Fachada

Una vez que tengo a los gnomos haciendo el trabajo, simplemente creo una clase para cada gnomo. ¡Son los gnomos los que están haciendo el diseño! ¡Desarrollo impulsado por gnomos!

Este es un problema con muchos desarrolladores, primero abren un ide y piensan qué clase escribir y qué métodos agregar.

Para comenzar, no comience a programar. Toma un papel y dibuja. Escribe tus pensamientos, define el problema que necesitas resolver. Analízalo. Hacer preguntas.
Luego estructúrelo, obtendrá su diseño en un instante después de eso.
Escribir el código es la parte más fácil de la programación si comprende el problema que resuelve.

Una función, por definición, es un mapeo múltiple de datos de entrada a datos de salida a través de un proceso bien definido. Entonces, el primer paso en cualquier proyecto sería definir la entrada, la salida y el proceso en ese orden. Para empezar, estas definiciones no necesitan ser elaboradas o precisas, ya que se perfeccionarán a medida que se analicen de forma iterativa.

Generalmente comienzo identificando los componentes individuales de un proyecto, luego trato de segmentar estos componentes en partes más pequeñas hasta que la carga sea manejable. En algún momento, incluso puede hacer una parte de la codificación sin saber completamente cómo encaja en la imagen completa. Solo asegúrese de que lo que está haciendo sea un componente necesario en su aplicación.

Primero quiero saber qué tipo de proyecto desea desarrollar, como una aplicación de escritorio, una aplicación web o una aplicación móvil. Dependiendo de su respuesta, puedo sugerir algunos buenos marcos, al usar esos marcos puede desarrollar y mantener aplicaciones muy fácilmente.

Bueno, puede ser difícil, dependiendo de tu proyecto.

Su problema podría no estar relacionado con la POO. Puede ser que no sabes lo que quieres hacer. De lo contrario, la respuesta sería “lo que quieras”.

Entonces, ¿qué es exactamente lo que quieres hacer?