¿Qué significa "escribir código para patrones en problemas" y no "para instancias"?

7

Estaba leyendo este post sobre lo que se necesita para convertirse en un desarrollador de élite: enlace

Dice: "Escribir código para patrones, no instancias específicas". Qué significa eso? ¿Escribe siempre su programa utilizando un patrón de diseño predefinido en lugar de su solución personalizada al problema?

    
pregunta johnsimer 02.07.2016 - 04:21

5 respuestas

18

Esto es claramente un malentendido, el autor no significa "patrón" en el sentido de "patrón de diseño GOF". Ni siquiera habla de "patrones en tu código", sino de en los problemas que vas a resolver con tu código.

Entonces, para expresar su recomendación en otras palabras: uno debe tratar de escribir un código que resuelva toda una categoría de problemas en lugar de escribir un código que resuelva solo un caso muy específico de un problema.

Este es un ejemplo trivial: no escriba código para completar una matriz de tamaño 10 con los números del 1 al 10, incluso si ese es el requisito que tiene actualmente. Es mejor escribir una función que llene una matriz arbitraria con números desde 1 hasta sizeof (matriz). Esa pieza de código tendría el mismo tamaño y no es más complicada, pero se puede reutilizar mucho más fácilmente, se puede probar más fácilmente y resuelve la "categoría más amplia de problemas".

Por supuesto, en situaciones reales, para encontrar la categoría correcta (o "patrón") se necesita algo de experiencia y un poco de talento, de eso es de lo que habla el artículo. Se debe agregar a ese párrafo que existe un cierto riesgo de sobregeneralización, y es importante que uno se esfuerce por generalizar solo cuando no hace el código innecesariamente complicado (las mejores generalizaciones hacen que el código sea más simple).

    
respondido por el Doc Brown 02.07.2016 - 10:02
6

Esto es bastante vago, y el autor no da ninguna orientación específica. Estoy bastante seguro de que no significa que la codificación implemente un patrón de diseño tras otro. Creo que quiere decir que a menudo es más fácil escribir el caso general que el caso específico.

Aquí hay un ejemplo reciente de mi propio trabajo. Estamos procesando datos de una fuente externa. Hay múltiples pasos de procesamiento y en cada paso algunos de los datos de entrada pueden ser rechazados. Necesitamos recopilar todos los registros erróneos.

El código heredado contiene varias implementaciones de este parche, y no es fácil resolver correctamente un caso. Entonces, uno de los miembros de mi equipo extrajo este patrón en un método general que ejecuta funciones en secuencia y recopila todas las excepciones para informes posteriores. El caso general fue fácil de escribir y probar, y luego todos los casos específicos se simplificaron enormemente. A menudo es más fácil escribir y probar un código más general, porque al ser general, no tiene dependencias.

Los desarrolladores con experiencia solo en OO / lenguajes de procedimiento a menudo pierden estas oportunidades para generalizar patrones de control comunes. Ven la duplicación en los cálculos, pero pierden la duplicación del control.

    
respondido por el kevin cline 02.07.2016 - 05:32
2

La mayoría de los programas tienen patrones de código que serán necesarios varias veces, posiblemente con variaciones. Si puede escribir código para manejar el patrón, simplifica enormemente el desarrollo, ya que no tiene que volver a escribir código similar. Considere estos ejemplos:

Una aplicación lee y escribe archivos de texto en varios puntos de la ejecución. Tienes un par de opciones:

  1. Agregue el código para abrir y leer el archivo relevante en cualquier lugar donde necesite el código.
  2. Escriba funciones que lean o escriban un archivo con el nombre de archivo y el texto del parámetro (en cualquier formato que use la aplicación). Úsalos cuando necesites leer o escribir un archivo.

El segundo caso es más sencillo de codificar (después del primer archivo). También es mucho más fácil de probar.

La aplicación debe presentar muchas formas en un terminal de texto (podría generalizarse). Los formularios deben proporcionar la capacidad de navegar desde cualquier campo.

  1. Codifique cada formulario y cada validación de campo según sea necesario.
  2. Cree una función que presente el formulario basándose en una estructura de datos que contenga datos relevantes (solicitud, tipo de campo (carácter, número), tamaño del campo, etc.) y devuelva una estructura que contenga los campos. La función contiene la lógica de navegación adecuada (campo anterior, número de campo, superior, etc.). Cree la estructura de datos para cada formulario y utilícela cuando se requieran datos de formularios.

Estas son dos de un conjunto de funciones que reducen el tiempo de desarrollo en un proyecto al 25% del tiempo estimado. Ninguna de las funcionalidades estaba disponible en ese momento.

    
respondido por el BillThor 04.07.2016 - 14:54
1

La redacción de ese artículo es bastante desafortunada, ya que podría interpretarse que significa "encontrar patrones de software conocidos y unirlos para crear una aplicación que funcione". Este es un enfoque comúnmente utilizado por los desarrolladores sin experiencia, y funciona, siempre y cuando comprenda los patrones, cómo aplicarlos correctamente y cuál es su caso de uso adecuado. Los desarrolladores sin experiencia a menudo llegan a este enfoque demasiado pronto, antes de que entiendan completamente las implicaciones.

Los desarrolladores experimentados son capaces de crear sus propios patrones de código.

A modo de explicación, daré un ejemplo. Digamos que tienes el siguiente código:

string text;
switch (number)
{
    case 1: 
        text = "alpha";
        break;
    case 2:
        text = "bravo";
        break;
    case 3:
        text = "charlie";
        break;
    ...etc.
}

En C #, esto se puede simplificar poniéndolo en una función, porque se eliminan las declaraciones break . Entonces el código ahora se convierte en:

switch (number)
{
    case 1: return "alpha";
    case 2: return "bravo";
    case 3: return "charlie";
    ...etc.
}

Por supuesto, la verdadera ganancia es cuando reconoces que esto no tiene que ser una declaración switch . En su lugar, puede crear un Diccionario:

var words = new Dictionary<int, string>
{
    { 1, "alpha" },
    { 2, "bravo" },
    { 3, "charlie" }
    ...etc 
}

y ahora solo puedes decir

var word = words[2];  // bravo

Esto es más poderoso que una declaración de cambio, por varias razones:

  1. El diccionario no tiene que estar codificado, como lo hace la instrucción switch. Puede elegir cargar el diccionario desde cualquier fuente de datos compatible (incluidos los archivos de configuración XML, una base de datos o incluso una fuente de datos remota), y seguirá produciendo valores de la misma manera.

  2. Puede agregar nuevos pares clave / valor al diccionario, o eliminar valores que ya no son necesarios, en tiempo de ejecución. No tiene que ser una lista fija.

  3. El diccionario se escalará mejor (mantendrá un buen rendimiento incluso si tiene una gran cantidad de entradas).

El Diccionario es un patrón de software poderoso que tiene una amplia gama de usos. Es una estructura de datos generalizada; Puede elegir los tipos en los que opera y se le garantiza un cierto nivel de rendimiento. Incluso puedes tener diccionarios de diccionarios.

Para trabajos más grandes de almacenamiento y recuperación de datos, el desarrollador experimentado sabe que debe buscar una base de datos, porque es una tecnología probada que brinda ciertas garantías sobre la forma en que funciona.

Esto es lo que significa la publicación del blog por "escribir código para patrones, no instancias específicas".

    
respondido por el Robert Harvey 02.07.2016 - 05:18
1

Del artículo citado, un desarrollador de élite

  

Escribe código para patrones, no instancias específicas , en mi opinión, es una habilidad intuitiva que realmente no se puede aprender. O lo tienes o no lo tienes. Los desarrolladores realmente talentosos infieren los patrones en un sistema, incluso antes de que se escriba un módulo o un fragmento de código y codifiquen esos patrones, en lugar de instancias específicas. Esta habilidad limita la deuda técnica y da como resultado un código base más estricto y utilizable.

Eso es bastante vago.


Usaré uno de mis programas de software más favoritos y, al mismo tiempo, menos gustados, como ejemplo, que sería git . Una de las razones principales por las que git ha tenido tanto éxito como sistema de control de versiones distribuido es que los autores de git vieron el patrón. Git solo rastrea cuatro tipos de objetos: compromisos, etiquetas, árboles y blobs. Agregue los conceptos de ramas y controles remotos y eso es git en su núcleo. Los autores de git vieron este patrón, y lo hicieron muy temprano en el desarrollo de git. Reconocer el patrón muy temprano en el desarrollo de git fue clave para el éxito de git.

Una de las razones principales por las que a algunos les disgusta git es que los autores no vieron el patrón en cómo las personas usan los sistemas de control de versiones o en cómo se modela la estructura del comando git. Este fallo ha dado como resultado una estructura de comandos bastante compleja y bastante grande con argumentos no intuitivos, a veces con comandos que son duplicados y / o inconsistentes. Esto hace que el git UX sea bastante desagradable.

    
respondido por el David Hammen 02.07.2016 - 17:49

Lea otras preguntas en las etiquetas