design - tutorial - ¿Cuál es la diferencia entre los datos y el código?
views django example (12)
Para tomar un ejemplo, considere un conjunto de descuentos disponibles para un comprador de supermercado.
Podríamos definir estas reglas como datos de alguna manera estándar (listas de elementos elegibles, fechas aplicables, códigos de cupones) y escribir un código genérico para manejarlos. O bien, podríamos escribir cada uno como una porción de código, que verifica las cosas adecuadas según la lista de compras del cliente y devuelve los descuentos correspondientes.
Podría almacenar razonablemente las reglas como objetos, serializarlas en Blobs o almacenarlas en archivos de código, para que cada regla pueda elegir su propia división entre datos y código, para permitir reglas futuras que no se ajusten al tipo de procesador genérico considerado anteriormente.
A menudo es fácil criticar código que mezcla datos, a través de declaraciones que verifican 6 cosas diferentes que deberían estar en un archivo o base de datos, pero ¿hay alguna regla que ayude en los casos límite?
¿O es este el objetivo del diseño orientado a objetos, para evitar que nos preocupemos por la línea entre los datos y el código?
Para aclarar, la pregunta subyacente es esta: ¿cómo codificaría el ejemplo anterior? ¿Existe una regla de oro que te hizo decidir qué son los datos y qué es el código?
(Nota: lo sé, se puede compilar el código, pero en un mundo de lenguajes dinámicos y compilación JIT, incluso ese es un concepto borroso).
En Lisp, tu código es datos, y tus datos son código
En Prolog, las cláusulas son términos y los términos son cláusulas.
Código es cualquier dato que se puede ejecutar. Ahora, dado que todos los datos se utilizan como entrada para algún programa en algún punto del tiempo, se puede decir que estos datos los ejecuta un programa. Por lo tanto, su programa actúa como una máquina virtual para sus datos. ¡Por lo tanto, en teoría, no hay diferencia entre los datos y el código!
Al final, lo que importa es la ingeniería del software / consideraciones de desarrollo como el rendimiento, la eficiencia, etc. Por ejemplo, los programas impulsados por datos pueden no ser tan eficientes como los programas que tienen sentencias condicionales codificadas (y por lo tanto frágiles). Por lo tanto, elijo definir código como cualquier dato que se pueda ejecutar de manera eficiente y todo lo demás sea información simple.
Es una compensación entre flexibilidad y eficiencia. Los datos ejecutables (como las reglas XML) ofrecen más flexibilidad (a veces) mientras que los mismos datos / reglas codificados como parte de la aplicación se ejecutarán de manera más eficiente, pero cambiarlos con frecuencia se vuelve engorroso. En otras palabras, los datos ejecutables son fáciles de implementar, pero son ineficientes y viceversa. Entonces, en última instancia, la decisión depende de usted: el diseñador de software.
Por favor corrígeme si me equivoco.
Diría que la distinción entre datos, código y configuración es algo que debe hacerse dentro del contexto de un componente particular. A veces es obvio, a veces no tanto.
Por ejemplo, para un compilador, el código fuente que consume y el código objeto que crea son ambos datos, y deben separarse del propio código del compilador.
En su caso, parece que describe la opción de un archivo de configuración particularmente potente, que puede contener código. Tanto como, por ejemplo, el GIMP le permite ''configurar'' los complementos usando Scheme. Como desarrollador del componente que lee esta configuración, lo consideraría como datos. Cuando trabaje en un nivel diferente, escriba la configuración, podría pensar que es un código.
Esta es una forma muy poderosa de diseñar.
Aplicando esto a la pregunta subyacente ("¿Cómo codificarías el ejemplo anterior?"), Una opción podría ser adoptar o diseñar un lenguaje de dominio específico (DSL) de alto nivel para especificar reglas. En el inicio, o cuando se requiera por primera vez, el servidor lee la regla y la ejecuta.
Proporcionar una interfaz de administrador que permita al administrador
- probar un nuevo archivo de reglas
- reemplace la configuración actual con la de un nuevo archivo de reglas
... todo lo cual sucedería en tiempo de ejecución.
Un DSL puede ser algo tan simple como un analizador de tablas o un analizador XML, o podría ser algo tan sofisticado como un lenguaje de scripting. Desde C, es fácil incrustar Python o Lua. Desde Java, es fácil incorporar Groovy o Clojure.
Podrías cambiar el código compilado en tiempo de ejecución, con enlaces ingeniosos o trucos para el cargador de clases. Esto parece más difícil y menos valioso que la opción DSL integrada, en mi opinión.
Fundamentalmente, por supuesto no hay diferencia entre los datos y el código, pero para las infraestructuras de software reales, puede haber una gran diferencia. Además de cosas obvias como, como mencionaste, compilación, el mayor problema es este:
La mayoría de los proyectos suficientemente grandes están diseñados para producir "lanzamientos" que son un gran paquete, producidos en ciclos de 3 meses (o más), probados exhaustivamente y no pueden ser cambiados posteriormente, excepto en formas estrictamente controladas. Definitivamente, el "código" no se puede modificar, por lo que todo lo que se necesita cambiar se tiene que factorizar e incluir "datos de configuración" para que cambiarlos sea aceptable para aquellos cuyo trabajo es garantizar que funcione una versión.
Por supuesto, en la mayoría de los casos, los datos de configuración erróneos pueden romper una versión tan minuciosamente como un código incorrecto, por lo que todo es en gran medida una ilusión; en realidad, no importa si cambia el código o los "datos de configuración", lo que importa es que la interfaz entre el sistema principal y las partes que cambian es lo suficientemente estrecha y bien definida como para darle una buena oportunidad de que la persona que hace el cambio comprenda todas las consecuencias de lo que está haciendo.
Esto ya es más difícil de lo que piensa la mayoría de la gente cuando se configuran solo unas cuantas cadenas y números (personalmente presencié un bloqueo del sistema mainframe de producción porque tenía un valor booleano diferente a otro sistema con el que estaba hablando). Cuando sus "datos de configuración" contienen lógica compleja, es casi imposible de lograr. Pero la situación no va a ser mejor porque usas un lenguaje ad hoc de "configuración de reglas" mal diseñado en lugar de un código "real".
La línea entre datos y código (programa) es borrosa. En última instancia, solo se trata de terminología ; por ejemplo, podría decir que los datos son todo lo que no es código. Pero, como usted escribió, pueden ser felizmente mezclados (aunque generalmente es mejor mantenerlos separados).
La relación entre código y datos es la siguiente:
código después de compilado en un programa procesa los datos durante la ejecución
programa puede extraer datos, transformar datos, cargar datos, generar datos ...
También el programa puede extraer código, transformar código, cargar código, generar código tooooooo ...
Por lo tanto, el código sin compilar o interperator es inútil, los datos siempre valen la pena ..., pero el código después de compilado puede hacer todas las actividades anteriores ...
Por ejemplo)
Sourcecontrolsystem process Códigos fuente
aquí el código fuente en sí es un código
Los archivos de respaldo procesan archivos
aquí los archivos son datos y demás ...
Los datos son información que se procesa mediante instrucciones llamadas Código. No estoy seguro de sentir que hay una borrosidad en OOD, todavía hay propiedades (Datos) y métodos (Código). La teoría de OO encapsula a ambos en una entidad de gestalt llamada clase pero aún son discretos dentro de la clase.
Qué tan flexible quiere hacer su código en cuestión de elección. La inclusión de valores constantes (lo que está haciendo mediante el uso de sentencias if tal como se describió anteriormente) es inflexible sin volver a procesar su fuente, mientras que el uso de datos dinámicos es más flexible. ¿Está mal el enfoque? Yo diría que realmente depende de las circunstancias. Como dijo Leppie, hay ciertos puntos de ''datos'' que son invariables, como los días de la semana que pueden ser codificados, pero incluso allí puede ser ventajoso hacerlo dinámicamente en ciertas circunstancias.
Los datos son información. No se trata de dónde decide colocarlo, ya sea un archivo db, config, config a través de código o dentro de las clases.
Lo mismo ocurre con los comportamientos / código. No se trata de dónde decide colocarlo o cómo elige representarlo.
Todo depende del requisito. Si los datos son similares a los datos de búsqueda y cambian con frecuencia, realmente no quiere hacerlo en el código, pero cosas como el Día de la semana, no deberían alterarse durante los próximos 200 años más o menos, así que codifique eso.
Puede considerar cambiar su tema, ya que lo primero que pensé cuando lo vi fue la antigua discusión de LISP sobre el código y los datos. Afortunado en el código y los datos del esquema se ve igual, pero eso es todo, nunca se puede mezclar accidentalmente el código con los datos, como es muy posible en LISP con macros antihigiénicos.
La mejor respuesta práctica a esta pregunta que encontré es esta: cualquier clase que necesita ser serializada, ahora o en un futuro previsible, son datos. Todo lo demás es código. Es por eso que, por ejemplo, los HashMap de Java son datos, aunque tienen mucho código, métodos de API e implementación específica (es decir, podría parecer un código a primera vista).
Esta es una pregunta más bien filosófica (que me gusta) así que la responderé de una manera filosófica: sin mucho para respaldarla. ;)
Los datos son parte de un sistema que puede cambiar. El código define el comportamiento; la forma en que los datos pueden cambiar a nuevos datos.
Para decirlo con más precisión: los datos pueden describirse por dos componentes: una descripción de lo que se supone que representa el dato (por ejemplo, una variable con un nombre y un tipo) y un valor . El valor de la variable puede cambiar de acuerdo con las reglas definidas en el código. La descripción no cambia, por supuesto, porque si lo hace, tenemos una información completamente nueva. El código en sí no cambia, a menos que los requisitos (lo que esperamos del sistema) cambien.
Para un compilador (o una VM), el código es realmente la información sobre la cual realiza sus operaciones. Sin embargo, el código que se compila no especifica el comportamiento para el compilador, el propio código del compilador lo hace.
La nota importante es que desea separar la parte de su código que ejecutará la misma cada vez, (es decir, aplicando un descuento) de la parte de su código que podría cambiar (es decir, los productos a descontar, o el% de el descuento, etc.)
Esto es simplemente por seguridad. Si cambia un descuento, no tendrá que volver a escribir su código de descuento, solo tendrá que acceder al repositorio de descuentos (DB, archivo de aplicación o xml, o como quiera que lo implemente) y hacer un pequeño cambio en un número.
Además, si el código de descuento se divide en un archivo XML, puede entregar la aplicación completa a un administrador y, con las instrucciones suficientes, no tendrá que molestarlo cuando quiera cambiar las tasas de descuento.
Cuando mezcla datos y código, aumenta exponencialmente las probabilidades de romperse cuando algo cambia. Entonces, como dijo Leppie , necesitas extraer las partes que cambian constantemente, y ponerlas en un lugar separado.