¿Cómo se convirtió en práctica la separación de código y datos?

29

Lea la pregunta detenidamente: pregunta cómo , no por qué .

Recientemente me encontré con esta respuesta , que sugiere usar una base de datos para almacenar datos inmutables:

Parece que muchos de los números mágicos que usted describe, especialmente si dependen en parte, son realmente datos, no códigos. [...] Puede significar una base de datos de tipo SQL, o simplemente puede significar un archivo de texto formateado.

Me parece que si tiene datos que son parte de lo que hace su programa, lo que debe hacer es incluirlos en el programa . Por ejemplo, si la función de su programa es contar vocales, ¿qué tiene de malo tenerla vowels = "aeiou"? Después de todo, la mayoría de los idiomas tienen estructuras de datos diseñadas específicamente para este uso. ¿Por qué molestarse en separar los datos colocándolos en un "archivo de texto formateado", como se sugirió anteriormente? ¿Por qué no hacer que ese archivo de texto esté formateado en el lenguaje de programación que elija? ¿Ahora es una base de datos? ¿O es código?

Estoy seguro de que algunos pensarán que esta es una pregunta tonta, pero la hago con toda seriedad. Siento que "el código y los datos separados" están surgiendo culturalmente como una especie de verdad evidente, junto con otras cosas obvias como "no le dé a sus variables nombres engañosos" y "no evite usar espacios en blanco solo porque su idioma lo considere es insignificante ".

Tomemos, por ejemplo, este artículo: El problema con la separación de datos del código de Puppet . El problema ? ¿Qué problema? Si Puppet es un lenguaje para describir mi infraestructura, ¿por qué no puede describir también que el servidor de nombres es 8.8.8.8? Me parece que el problema no es que el código y los datos estén mezclados, 1 sino que Puppet carece de estructuras de datos suficientemente ricas y formas de interactuar con otras cosas.

Encuentro este cambio inquietante. La programación orientada a objetos dijo "queremos estructuras de datos arbitrariamente ricas", y así dotó a las estructuras de datos con poderes de código. Obtiene encapsulación y abstracción como resultado. Incluso las bases de datos SQL tienen procedimientos almacenados. Cuando secuestra datos en YAML o archivos de texto o bases de datos tontas como si estuviera eliminando un tumor del código, pierde todo eso.

¿Alguien puede explicar cómo surgió esta práctica de separar datos del código y hacia dónde va? ¿Alguien puede citar publicaciones de luminarias o proporcionar algunos datos relevantes que demuestren "código separado de datos" como un mandamiento emergente e ilustran su origen?

1: si uno puede incluso hacer tales distinciones. Los estoy mirando, programadores de Lisp.

Phil Frost
fuente
55
Siéntase libre de enterrar todos los html y css en el idioma que elija.
JeffO
3
Creo que lo que quiso decir el autor de la cita es que los números mágicos no son realmente inmutables.
Pieter B
44
No hay nada de malo en codificar las vocales. Si su aplicación solo se usará para contar las vocales en inglés.
Michael Paulukonis
3
Una razón técnica importante para separar el código y los datos es no tener que volver a compilar el código cuando los datos cambian. Por lo tanto, me preguntaría si se aplica en la misma medida a los lenguajes de secuencias de comandos.
user16764
1
@MichaelPaulukonis: Y ponerlo en una base de datos es una solución falsa. ¿Se necesitan cambios para holandés? Cero (ni siquiera un cambio de DB). ¿Se necesitan cambios para francés / alemán? Al menos soporte ISO-8859-1. (Más que DB). ¿Se necesitan cambios para griego / ruso? Soporte Unicode (más que DB). De hecho, no se me ocurre ningún lenguaje en el que esa base de datos sea de alguna ayuda.
MSalters

Respuestas:

22

Hay muchas buenas razones para separar los datos del código, y algunas razones para no hacerlo. Lo siguiente viene a mi mente.

Oportunidad. ¿Cuándo se conoce el valor de los datos? Es en el momento en que se escribe el código, cuando se compila, vincula, libera, licencia, configura, inicia la ejecución o mientras se ejecuta. Por ejemplo, el número de días en una semana (7) se conoce temprano, pero el tipo de cambio USD / AUD se conocerá bastante tarde.

Estructura. ¿Es este un conjunto de tiempo de datos único de acuerdo con una sola consideración, o podría ser heredado o parte de una colección más grande de elementos? Los lenguajes como YAML y JSON permiten combinar valores de múltiples fuentes. Quizás algunas cosas que inicialmente parecen inmutables estén mejor accesibles como propiedades en un administrador de configuración.

Localidad. Si todos los elementos de datos se almacenan en un número limitado de lugares, es mucho más fácil administrarlos, particularmente si algunos necesitan ser cambiados a valores nuevos (inmutables). La edición del código fuente solo para cambiar los valores de los datos introduce el riesgo de cambios y errores involuntarios.

Separación de intereses. Lograr que los algoritmos funcionen correctamente se separa mejor de la consideración de qué valores de datos usar. Se necesitan datos para probar algoritmos, no para ser parte de ellos. Ver también http://c2.com/cgi/wiki?ZeroOneInfinityRule .

En respuesta a su pregunta, esto no es algo nuevo. Los principios básicos no han cambiado en más de 30 años, y se ha escrito sobre ellos repetidamente durante ese tiempo. No recuerdo ninguna publicación importante sobre el tema, ya que generalmente no se considera controvertido, solo algo que explicar a los recién llegados. Hay un poco más aquí: http://c2.com/cgi/wiki?SeparationOfDataAndCode .

Mi experiencia personal es que la importancia de esta separación en una pieza de software particular aumenta con el tiempo, no menos. Los valores codificados se mueven a archivos de encabezado, los valores compilados se mueven a archivos de configuración, los valores simples se convierten en parte de estructuras jerárquicas y administradas.

En cuanto a las tendencias, no he visto ningún cambio importante en la actitud entre los programadores profesionales (más de 10 años), pero la industria está cada vez más llena de jóvenes y muchas cosas que pensé que se sabían y decidieron seguir desafiándose y reinventando, a veces fuera de los nuevos ideas, pero a veces por ignorancia.

david.pfx
fuente
2
¿Podría ampliar la historia y la tendencia de esta práctica? Si todos dieran estas consideraciones, no habría hecho la pregunta. La premisa de la pregunta es que las personas no están considerando cuidadosamente a dónde deben ir sus datos (constantes compiladas, bases de datos externas, YAML ...) sino que solo piensan "¡CÓDIGO Y DATOS MIXTOS MALOS! ¡HULK SMASH!" ¿Por qué o cuándo se convirtió esto en algo?
Phil Frost
No es parte de mi experiencia, así que no puedo decírtelo. He añadido un par de paras a mi respuesta.
david.pfx
Creo que la "afluencia de jóvenes" es una explicación válida, pero estoy retrasando la aceptación porque me gustaría saber de algunos de estos jóvenes para ver de dónde sacaron la idea. Claramente obtuvieron la parte de "código y datos separados", pero no creo que obtuvieran el resto. ¿Lo leyeron en una publicación de blog? ¿Un libro? ¿Donde y cuando?
Phil Frost
Siempre obtendrá "_____ ¡MALO! ¡HULK SMASH!" Eso no significa que sea verdad. A menudo, este tipo de cosas (por ejemplo, "'GOTO' BAD! HULK SMASH!") Se enseña a los principiantes, sin enseñarles por qué o cuáles son las excepciones.
AMADANON Inc.
Localitytambién funciona a la inversa: terminamos con una especie de sistema de tipo plugin debido a requisitos personalizados para diferentes clientes, y a través de varios años de prueba y error aprendimos a mantener sus constantes (incluso tablas, por medio de listas de dictados) de la base de datos y en el código. Tanto porque usarlo en otro lugar que no sea ese "complemento" es incorrecto, y porque los cambios se versionan automáticamente cuando ocurren los cambios.
Izkata
8

Los datos se escalan mucho mejor y pueden consultarse y modificarse con mucha más facilidad cuando se separan del código. Incluso si sus datos son de naturaleza codish, por ejemplo, sus datos representan reglas o comandos, si puede almacenar representar ese código como datos estructurados, puede disfrutar de los beneficios de almacenarlos por separado:

permisos

Si los datos están codificados, deberá editar el archivo fuente para editar esos datos. Eso significa que:

  • Solo los desarrolladores pueden editar datos. Esto es malo: la entrada de datos no es algo que requiera las habilidades y el conocimiento del desarrollador.

  • Los no desarrolladores pueden editar el archivo fuente. Esto es malo: ¡podrían atornillar el archivo fuente sin siquiera saberlo!

  • Los datos están codificados en archivos de origen separados, y los no desarrolladores solo tienen acceso a esos archivos. Pero esto realmente no cuenta: ahora los datos se separan del código y se almacenan en sus propios archivos ...

edición

Entonces, con respecto a quién puede editar los datos, es mejor almacenarlos por separado. ¿Qué tal cómo van a editar los datos? Si tiene muchos datos, escribirlos a mano es tedioso y puede eliminar errores. ¡Tener algo de interfaz de usuario para esto es mucho mejor! Incluso si todavía tiene que escribir todo, no tendrá que escribir la placa de caldera del formato, por lo que hay menos posibilidades de que estropee el formato y atornille todo el archivo.

Si los datos están codificados, crear esa IU significará que una herramienta automatizada editará sus archivos fuente escritos a mano. Deje que eso se hunda: una herramienta automatizada abrirá sus archivos de origen, intentará encontrar dónde deberían estar los datos y modificará ese código. Brrr ... Microsoft introdujo clases parciales en C # solo para evitar esas cosas ...

Si los datos están separados, su herramienta automatizada solo tendrá que editar archivos de datos. Prefiero creer que los programas de computadora que editan archivos de datos no son tan poco comunes hoy en día ...

escalada

El código y la escala de datos son muy diferentes. A medida que crece su código, desea separarlo en más clases y métodos (o estructuras y funciones de datos), pero sus datos, sin importar cuánto crezcan, desea guardarlos en un solo lugar. Incluso si tiene que separarlo en varios archivos, desea agrupar esos archivos de alguna manera, por lo que será más fácil acceder a esos datos desde el código.

Entonces, imagine que tiene miles de líneas de datos dentro de un archivo fuente. El compilador / intérprete tiene que revisar todos esos datos cada vez que lee el archivo y analizarlo con su costoso lexer & parser, incluso si no va a acceder a esos datos en esta ejecución particular del programa. Además, cuando edita el código real en ese archivo, debe recorrer los datos, lo que complica el proceso completo. Además, los archivos de datos pueden indexarse. Datos codificados? No tanto...

buscando

Tiene toneladas de datos; es natural que desee buscar a través de ellos.

  • Si lo almacena en una base de datos, puede usar el lenguaje de consulta de la base de datos.

  • Si lo almacena en un archivo XML, puede usar XPath.

  • Si lo almacena en JSON / YAML, puede cargarlo en el REPL de su lenguaje de script favorito y buscarlo.

  • Incluso si lo almacena en un archivo de texto antiguo, ya que tiene una estructura que su programa puede reconocer, puede usar grep / sed / awk para buscarlo.

Si bien es cierto que también puede grep / sed / awk a través de datos codificados en un archivo fuente, no funciona tan bien, ya que su consulta puede coincidir con otras líneas no relacionadas o líneas perdidas que se escribieron de manera diferente porque la sintaxis de representación de datos del lenguaje de programación lo permite.

Existen herramientas para buscar a través del código, pero son buenas para encontrar declaraciones, no datos codificados.

Habiendo dicho eso...

Es muy importante distinguir entre datos y código. El hecho de que algo esté escrito como código no significa que no puedan ser datos. Y el hecho de que algo esté escrito con una representación de datos no significa que no sea, de hecho, un código.

Tuve una clase cuando teníamos reglas muy estrictas sobre "números mágicos": no podíamos tener ningún número en nuestro código. Eso significa que tuvimos que hacer cosas como:

#define THE_NUMBER_ZERO 0
//....
for(int i=THE_NUMBER_ZERO;i<cout;++i){
//....

lo cual es completamente ridículo! Sí, 0técnicamente es "datos", ¡pero es tan parte del código como el resto del forciclo! Así que, aunque nos podemos representarla como datos y separarlo del código, eso no significa que deberían . No porque queramos dejar datos dentro del código, sino porque no es realmente un dato, no más que el resto del código, que también se compila en unos y ceros ...

Idan Arye
fuente
7

Creo que hay algo de confusión. Está mezclando dos cosas: "Separar código y datos" y "expresar el comportamiento del programa como datos".

En su caso, en realidad está preocupado por el segundo y mezcla el primero en él. Cuando expresa el comportamiento del programa como datos, facilita su extensión. En su ejemplo con vowels = "aeiou", agregar nueva vocal es tan simple como agregar un carácter. Si tiene estos datos externamente, puede cambiar este comportamiento sin tener que volver a compilar el programa.

Y cuando lo piensas, OOP es una extensión de este pensamiento. La vinculación de datos y comportamiento juntos le permitirá cambiar el comportamiento del programa en función de los datos del programa.

Eufórico
fuente
2
Porque, naturalmente, la lista de vocales va a cambiar.
cHao
13
@cHao Tan pronto como interviene i18n, lo es.
Restablece a Mónica
2
i18n puede romperte la cabeza - mira algunos ejemplos perversos en Java en javaspecialists.eu/archive/Issue209.html
Rory Hunter
2
@Angew: Sin embargo, tan pronto como i18n interviene, estás jodido . Necesitas un código para esto; La solución ingenua es incapaz de manejar todos los casos, incluso en inglés. (No recuerdo el ïde un segundo; Hablemos de yy w!) Traslado de la lista a una base de datos no se va a arreglar eso, y es realmente perjudiciales - es de complejidad que va a ser inútil si mal hecho, pero no lo hará siquiera sabe lo "malo" es menos que usted está diseñando para i18n desde cero. En ese momento ya te estás dando cuenta de que una lista de vocales simplemente no va a ser suficiente.
cHao
1
@BenLee: No me sorprendería un poco, en realidad. Actualmente estoy trabajando en cambiar un código como ese mientras hablamos. Pero externalizar todo a la base de datos es una adivinación de otro tipo. Si aún no sabe si algo tendrá que modificarse, y lo que es más importante, si aún no sabe cómo deberá modificarse, entonces, en mi opinión, es mejor esperar hasta que necesite esa flexibilidad antes de agregarlo. .
cHao
5

Por ejemplo, si la función de su programa es contar vocales, ¿qué tiene de malo tener vocales = "aeiou"?

Almacenar la configuración externamente le permite tener una versión del código que se espera que funcione con muchas configuraciones, la alternativa es mantener muchas versiones del software que difieren solo por la configuración.

Mencionas las vocales = "aeiou", ¿qué pasa si a veces quiero "y", ¿debería tener que reconstruir todo el programa? ¿Puedo actualizar las versiones fácilmente ahora que he modificado el código? Si hay un error, ¿lo causé o el programa no funciona?

Si esto está dentro de su programa, implica que su programa no espera que los usuarios cambien la definición de vocales sin escanear el código para ver los posibles efectos secundarios. Si la definición se almacena externamente, implica que el programa no debe romperse por ningún valor razonable establecido en la configuración.

Cuando secuestra datos en YAML o archivos de texto o bases de datos tontas como si estuviera eliminando un tumor del código

Algunos lo ven como lo contrario, es decir, está eliminando el tumor de código de sus datos preciosos, vea: la cita de Torvalds sobre un buen programador

FMJaguar
fuente
44
La cita de Torvalds se refiere a estructuras de datos, no a datos.
user949300
El OP dice: "La programación orientada a objetos dijo" queremos estructuras de datos ricamente arbitrarias ", y así dotamos a las estructuras de datos con poderes de código".
FMJaguar
1
Si realiza un cambio fundamental en la definición de lo que es una vocal, necesitaría volver a ejecutar todas las pruebas automatizadas. Los sistemas rara vez tienen la capacidad de volver a ejecutar pruebas cuando un archivo de configuración cambia en un sistema implementado. Por lo tanto, tales definiciones deben integrarse en el sistema; quizás como dos conjuntos codificados con una opción de configuración para seleccionar entre ellos.
soru
+1 para la cita de Torvalds. Estoy de acuerdo con este sentimiento: en el ejemplo de Puppet, creo que el problema es que Puppet no tiene una buena estructura de datos para representar la información que la gente quiere poner. En lugar de arreglar las estructuras de datos, los desarrolladores de títeres afirmaron que el problema son los "datos en código" (¿por qué? ¡Esa es la pregunta!) Y desarrollaron hiera , que veo como poco más que trasladar el problema a otro lugar y, además, hacerlo imposible. asociar el comportamiento con los datos.
Phil Frost
2

Estaba en un proyecto donde el líder insistía en poner los datos de referencia en pequeñas tablas, y pensé que era una tontería. Pero como ya teníamos nuestra infraestructura de persistencia y conectividad configuradas, resultó ser un costo bastante bajo además de las otras operaciones de persistencia que estábamos haciendo.

Ahora, sigo pensando que fue una decisión tonta, y si no tuviéramos la infraestructura disponible, simplemente no lo habría hecho.

Pero algunos de los argumentos a favor que veo son:

  • Si tiene una mentalidad de base de datos, poner datos de referencia en la base de datos SQL le permite unirse para generar informes.
  • Si tiene una utilidad de administración o acceso a la base de datos, puede modificar los valores en tiempo de ejecución. (Aunque eso puede ser jugar con fuego).

Además, a veces las políticas interfieren con las prácticas de codificación. Por ejemplo, he trabajado en varias tiendas donde presionar un archivo .xml es A-OK, mientras que tocar una línea en el código requiere un ciclo de regresión completo y tal vez una prueba de carga. Así que había un equipo en el que estaba donde mis archivos .xml para el proyecto eran extremadamente ricos (y tal vez -heh- podría haber contenido algún código).

Siempre me pregunto si voy a disfrutar del beneficio de sacar datos del código a un almacén de datos externo, incluso si es solo un archivo de texto, pero he trabajado con personas que simplemente lo ven así como su primer impulso.

Robar
fuente
3
Buen comentario sobre los procedimientos de la tienda, donde editar XML está "bien" pero editar la misma cosa en código es una gran molestia.
user949300
trabajé en una tienda donde todo estaba en la base de datos que podría estar, hasta los textos de la pantalla. Además del código de la interfaz de usuario, el único que no está en la base de datos fue la ubicación de base de datos y las credenciales ...
jwenting
3
siempre suena tonto hasta que, un día, alguien pregunta "podemos reconfigurar esto para el usuario X que lo exige", y después de todo, no parece tan tonto. Malditos clientes :)
gbjbaanb
2
... y si ese día es "nunca", entonces es mucho tiempo sentirse tonto
Rob
2

Déjame hacerte una contrapregunta completamente seria: ¿Cuál es, en tu opinión, la diferencia entre "datos" y "código"?

Cuando escucho la palabra "datos", pienso "estado". Los datos son, por definición, lo que la aplicación en sí está diseñada para administrar y, por lo tanto, es lo que la aplicación nunca puede saber en tiempo de compilación. No es posible codificar los datos, porque tan pronto como los codifica, se convierte en comportamiento, no en datos.

El tipo de datos varía según la aplicación; un sistema de facturación comercial puede almacenar información de clientes y pedidos en una base de datos SQL, y un programa de gráficos vectoriales puede almacenar datos de geometría y metadatos en un archivo binario. En ambos casos y todo lo demás, hay una separación clara e irrompible entre el código y los datos. Los datos pertenecen al usuario , no al programador, por lo que nunca se pueden codificar.

De lo que parece estar hablando es de usar la descripción más precisa técnicamente disponible para mi vocabulario actual: información que rige el comportamiento del programa que no está escrito en el lenguaje de programación principal utilizado para desarrollar la mayoría de la aplicación.

Incluso esta definición, que es considerablemente menos ambigua que solo la palabra "datos", tiene algunos problemas. Por ejemplo, ¿qué pasa si partes significativas del programa están escritas en diferentes idiomas? Personalmente, he trabajado en varios proyectos que tienen aproximadamente 50% C # y 50% JavaScript. ¿Es el código JavaScript "datos"? La mayoría de la gente diría que no. ¿Qué pasa con el HTML, son esos "datos"? La mayoría de la gente aún diría que no.

¿Qué hay de CSS? ¿Son esos datos o código? Si pensamos que el código es algo que controla el comportamiento del programa, entonces CSS no es realmente código, porque solo (bueno, principalmente) afecta la apariencia, no el comportamiento. Pero tampoco son realmente datos; el usuario no lo posee, la aplicación ni siquiera lo posee. Es el equivalente de código para un diseñador de interfaz de usuario. Es como un código, pero no del todo código.

Podría llamar a CSS un tipo de configuración, pero una definición más práctica es que es simplemente código en un lenguaje específico de dominio . Eso es lo que a menudo representan su XML, YAML y otros "archivos formateados". Y la razón por la que usamos un lenguaje específico de dominio es que, en términos generales, es simultáneamente más conciso y más expresivo en su dominio particular que codificar la misma información en un lenguaje de programación de propósito general como C o C # o Java.

¿Reconoces el siguiente formato?

{
    name: 'Jane Doe',
    age: 27,
    interests: ['cats', 'shoes']
}

Estoy seguro de que la mayoría de la gente lo hace; es JSON . Y aquí está lo interesante de JSON: en JavaScript, es claramente código, y en cualquier otro idioma, son datos claramente formateados. Casi todos los lenguajes de programación convencionales tienen al menos una biblioteca para "analizar" JSON.

Si usamos exactamente la misma sintaxis dentro de una función en un archivo JavaScript, no puede ser otra cosa que código. Y, sin embargo, si tomamos ese JSON, lo guardamos en un .jsonarchivo y lo analizamos en una aplicación Java, de repente son "datos". ¿Eso realmente tiene sentido?

Sostengo que la "data-ness" o "configuration-ness" o "code-ness" es inherente a lo que se describe, no a cómo se describe.

Si su programa necesita un diccionario de 1 millón de palabras para, por ejemplo, generar una frase de contraseña aleatoria, ¿desea codificarlo así:

var words = new List<string>();
words.Add("aa");
words.Add("aah");
words.Add("ahhed");
// snip 172836 more lines
words.Add("zyzzyva");
words.Add("zyzzyvas");

¿O simplemente insertaría todas esas palabras en un archivo de texto delimitado por líneas y le diría a su programa que lea? Realmente no importa si la lista de palabras nunca cambia, no se trata de si está codificando o codificando (que muchos consideran correctamente un antipatrón cuando se aplica de manera inapropiada), es simplemente una cuestión de qué formato es más eficiente y hace que sea más fácil describir el "material", sea cual sea el "material". Es bastante irrelevante si lo llamas código o datos; es la información que requiere su programa para ejecutarse, y un formato de archivo plano es la forma más conveniente de administrarlo y mantenerlo.

Suponiendo que siga las prácticas adecuadas, todas estas cosas pasarán al control de la fuente de todos modos, por lo que también podría llamarlo código, solo código en un formato diferente y quizás muy minimalista. O puede llamarlo configuración, pero lo único que realmente distingue el código de la configuración es si lo documenta o no y le dice a los usuarios finales cómo cambiarlo. Tal vez podría inventar algún argumento falso sobre la configuración que se interpreta en el momento del inicio o el tiempo de ejecución y no en el momento de la compilación, pero luego comenzaría a describir varios lenguajes dinámicamente escritos y casi cualquier cosa con un motor de secuencias de comandos incrustado dentro de él (p. Ej. la mayoría de los juegos). El código y la configuración son lo que decida etiquetarlos, nada más y nada menos.

Ahora bien, no es un peligro para la externalización de la información que no es realmente seguro modificar (véase el enlace "suave codificación" más arriba). Si externaliza su conjunto de vocales en un archivo de configuración y lo documenta como un archivo de configuración para sus usuarios finales, les está dando una forma casi infalible de romper instantáneamente su aplicación, por ejemplo, poniendo "q" como vocal. Pero ese no es un problema fundamental con la "separación de código y datos", es simplemente un mal sentido del diseño.

Lo que les digo a los desarrolladores junior es que siempre deben externalizar las configuraciones que esperan cambiar por entorno. Eso incluye cosas como cadenas de conexión, nombres de usuario, claves API, rutas de directorio, etc. Ellos podrían ser el mismo en su caja dev y en la producción, pero probablemente no, y los administradores de sistemas decidirán cómo quieren que se vea en la producción, no a los desarrolladores. Por lo tanto, necesita una forma de aplicar un grupo de configuraciones en algunas máquinas, y otras configuraciones aplicadas en otras máquinas: ergo, archivos de configuración externos (o configuraciones en una base de datos, etc.)

Pero enfatizo que simplemente poner algunos "datos" en un "archivo" no es lo mismo que externalizarlos como configuración. Poner un diccionario de palabras en un archivo de texto no significa que desee que los usuarios (o TI) lo cambien, es solo una forma de facilitar que los desarrolladores entiendan qué demonios está sucediendo y, si es necesario, cambios ocasionales Del mismo modo, poner la misma información en una tabla de base de datos no necesariamente cuenta como externalización del comportamiento, si la tabla es de solo lectura y / o los DBA tienen instrucciones de no atornillarla. La configuración implica que los datos son mutables, pero en realidad eso está determinado por el proceso y las responsabilidades más que por la elección del formato.

Entonces, para resumir:

  • "Código" no es un término rígidamente definido. Si expande su definición para incluir lenguajes específicos de dominio y cualquier otra cosa que afecte el comportamiento, gran parte de esta aparente fricción simplemente desaparecerá y todo tendrá sentido. Puede tener un "código" DSL no compilado en un archivo plano.

  • "Datos" implica información que es propiedad del usuario (s) o al menos alguien que no sea el desarrollador, y que generalmente no está disponible en el momento del diseño. No podría estar codificado incluso si quisieras hacerlo. Con la posible excepción del código auto modificable , la separación entre código y datos es una cuestión de definición, no de preferencia personal.

  • La "codificación suave" puede ser una práctica terrible cuando se aplica en exceso, pero no todas las instancias de externalización necesariamente constituyen una codificación suave, y muchas instancias de almacenamiento de información en "archivos planos" no son necesariamente un intento de buena fe de externalización.

  • La configuración es un tipo especial de codificación suave que es necesaria debido al conocimiento de que la aplicación puede necesitar ejecutarse en diferentes entornos. Implementar un archivo de configuración separado junto con la aplicación es mucho menos trabajo (y mucho menos peligroso) que implementar una versión diferente del código en cada entorno. Entonces, algunos tipos de codificación suave son realmente útiles.

Aaronaught
fuente
1

Sugiero leer este artículo clásico de Oren Eini (también conocido como Ayende Rahien)

http://ayende.com/blog/3545/enabling-change-by-hard-coding-everything-the-smart-way

Mi propia conclusión es centrarme en la simplicidad y la legibilidad. Esto puede significar que las cosas que es poco probable que se reconfiguren son mejor codificadas (legibles). Esto le permite utilizar la sintaxis completa de un lenguaje de programación para expresar los parámetros, así como obtener efectos secundarios beneficiosos como la finalización del código y los errores del compilador en caso de mal uso.

De esta forma, puede evitar las complejidades de analizar / interpretar ("pero alguien más analiza mi YAML / JSON": asignar el texto analizado a las llamadas API específicas puede ser una forma de interpretación) y evitar la complejidad de otro paso entre los "datos "y su uso.

Algunos casos se prestan a expresarse en datos incluso en un escenario como este: por ejemplo, especificar miles de puntos en el espacio 3D puede ser más adecuado para un archivo de texto que un código, aunque en algunos lenguajes, incluido C usando inicializadores de estructura, código puede ser apropiado incluso para eso.

orip
fuente
1

Ok, supongamos que quieres escribir algún tipo de programa de C ++ para tu tiempo libre. Sabes exactamente lo que tiene que hacer y lo que nunca tendrá que hacer. Ahora tome cualquier libro sobre "diseño de software moderno". Aquí está la regla del juego: para cada clase en su proyecto y cada caso pequeño, debe implementar todos y cada uno de los patrones elegantes que encuentre descritos en ese libro para hacer que su código sea un "diseño limpio". Bueno, supongo que la "inyección de dependencia" será suficiente para muchas personas. (¡Es c ++, no java!) La programación se enseña desde un punto de vista cada vez más teórico. No es suficiente que hagas el trabajo, tienes que escribir código que se pueda mantener, prueba tonta ... todo bien y correcto. El problema comienza cuando ppl. Deje de pensar en la razón real, los patrones de diseño se inventaron y se volvieron dogmáticos.

Permítame dejar de escribir su herramienta de conteo de letras (sobre) usando un único principio de diseño simple: cuando escriba código que haga un cierto trabajo en datos de entrada de cierto tipo, asegúrese de que pueda realizar esa tarea para cualquier entrada dada datos de ese tipo. - Cuando desee escribir una herramienta para contar letras, tiene sentido escribirla de una manera que no solo pueda contar vocales, sino "cualquier letra". - Como es posible que no sepa cuál es realmente el corpus que está analizando, también puede elegir una codificación muy general (UTF-16) y cubrir la mayoría (¿todos?) De los idiomas escritos y sus símbolos.

Hasta ese momento, tenemos una función con dos argumentos (el corpus y las letras a contar). Solo nos preocupa encontrar un "tipo" o "clase" razonablemente general al que pertenezcan las letras: ¡ciertamente podemos hacerlo mejor que los símbolos ASCII!

Introduzca un demonio con la "generalización y reutilización" -dogma: - ¿Por qué no contar ningún símbolo de ninguna clase en una secuencia de entrada de esa clase? (resumen de letras a secuencias de bits de longitud arbitraria pero finita, ya que es lo más general que puede obtener con una computadora ...) - Espere, incluso entonces seguimos contando en números naturales. Sin embargo, el conteo se puede generalizar como un mapeo de un conjunto contable a sí mismo que cumple los axiomas ... [se entiende]

Ahora, ese ejemplo puede ser tonto, pero si considera tareas de diseño más complejas que una herramienta de conteo, podría encontrar todas las oportunidades para introducir una abstracción adicional requerida de acuerdo con algún tipo de patrón de diseño que encontró en su libro.

La separación de "datos" y "código" probablemente sea trivial (argumentos de función) o se encontrará tratando a los invariantes como variables ("datos").

Si alguna vez hay alguna confusión, es probable que las "interfaces" y los "servicios" y todos los detalles de la clase (por ejemplo, los tipos) sean repentinamente "datos", es decir, dependencias que se inyectarán desde el exterior. Siento que los cursos de informática que se imparten en la universidad se parecen mucho a las clases de filosofía y hay menos tiempo para proyectos reales para que los estudiantes puedan adquirir experiencia sobre cómo hacer software que funcione. Si alguna vez se pregunta por qué debe usar un patrón increíblemente complejo en lugar de una solución obvia, este desarrollo es (probablemente) cómo se "creó" ese requisito ...

Para su problema específico: si pudiera 1.) escribir un programa con un máximo de codificación rígida para su caso específico y luego 2.) generalizar a partir de ese código de manera directa, por ejemplo. introduciendo más argumentos de función y utilizando otros "patrones triviales" puede estar seguro de que está separando código y datos, de la manera obvia, como se ha hecho desde que se inventó la programación funcional. (Ofc te saltas 1. y haces 2. instantáneamente ...)

Cualquier cosa que no sea obvia aquí es probable que sea un caso de "bloqueo de teoría": como escribir una interfaz haciendo referencia a una interfaz y otra interfase ... y al final tiene un pequeño y ordenado archivo xml para configurar todas estas interfaces y las dependencias que se inyectarán en su clase-interfaz-desorden.

Solo esperemos que el analizador xml que requiera no necesite una configuración xml para funcionar ...

bhak
fuente