¿Qué es el diseño orientado a datos? [cerrado]
Estaba leyendo este artículo y este tipo continúa hablando sobre cómo todos pueden beneficiarse enormemente al combinar el diseño orientado a datos con la programación orientada a objetos. Sin embargo, no muestra ningún ejemplo de código.
Busqué esto en Google y no pude encontrar ninguna información real sobre qué es esto, y mucho menos ningún ejemplo de código. ¿Alguien está familiarizado con este término y puede dar un ejemplo? ¿Es quizás esta una palabra diferente para otra cosa?
En primer lugar, no confunda esto con el diseño basado en datos.
Según tengo entendido, el diseño orientado a datos (DOD) se trata de organizar los datos para un procesamiento eficiente. Especialmente con respecto a errores de caché, etc. El diseño basado en datos, por otro lado, consiste en permitir que los datos controlen gran parte del comportamiento de su programa (descrito muy bien en la respuesta de Andrew Keith ).
Supongamos que tiene objetos de bola en su aplicación con propiedades como color, radio, rebote, posición, etc.
Enfoque orientado a objetos
En POO describirías bolas como esta:
class Ball {
Point position;
Color color;
double radius;
void draw();
};
Y luego crearías una colección de bolas como esta:
vector<Ball> balls;
Enfoque orientado a datos
Sin embargo, en el diseño orientado a datos, es más probable que escriba el código de esta manera:
class Balls {
vector<Point> position;
vector<Color> color;
vector<double> radius;
void draw();
};
Como puedes ver, ya no existe una sola unidad que represente una Bola. Los objetos bola sólo existen implícitamente.
Esto puede tener muchas ventajas en cuanto a rendimiento. Normalmente queremos realizar operaciones con muchas bolas al mismo tiempo. El hardware normalmente necesita grandes porciones de memoria contiguas para funcionar de manera eficiente.
En segundo lugar, podrías realizar operaciones que afecten sólo a una parte de las propiedades de una pelota. Por ejemplo, si combina los colores de todas las bolas de varias maneras, entonces querrá que su caché solo contenga información de color (lo que permite el Departamento de Defensa). Sin embargo, cuando todas las propiedades de la bola se almacenan en una unidad (como OOP), también obtendrás todas las demás propiedades de una bola. Aunque no los necesites.
Ejemplo de uso de caché
Digamos que cada bola ocupa 64 bytes y un punto ocupa 4 bytes. Una ranura de caché también ocupa, digamos, 64 bytes. Si quiero actualizar la posición de 10 bolas, entonces:
- En programación orientada a objetos, tengo que introducir 10 x 64 = 640 bytes de memoria en el caché y obtener 10 errores de caché.
- Sin embargo, en DOD, puedo extraer las posiciones de las bolas por separado (sin extraer las otras propiedades de la unidad), eso solo tomará 10 x 4 = 40 bytes. Eso cabe en una búsqueda de caché. Por lo tanto, solo obtenemos 1 error de caché para actualizar las 10 bolas.
Estos números son arbitrarios; supongo que un bloque de caché es más grande.
Pero ilustra cómo el diseño de la memoria puede tener un efecto grave en los accesos a la caché y, por tanto, en el rendimiento. Esto sólo aumentará en importancia a medida que se amplíe la diferencia entre la velocidad de la CPU y la RAM.
Cómo diseñar la memoria.
En mi ejemplo de bola, simplifiqué mucho el problema, porque normalmente, para cualquier aplicación normal, es probable que accedas a varias variables juntas. Por ejemplo, la posición y el radio probablemente se utilizarán juntos con frecuencia. Entonces su estructura DOD debería ser:
class Body {
Point position;
double radius;
};
class Balls {
vector<Body> bodies;
vector<Color> color;
void draw();
};
La razón por la que debería hacer esto es que si los datos utilizados juntos se colocan en matrices separadas, existe el riesgo de que compitan por las mismas ranuras en la memoria caché. Por lo tanto, cargar uno arrojará el otro.
Entonces, en comparación con la programación orientada a objetos, las clases que terminas creando no están relacionadas con las entidades en tu modelo mental del problema. Dado que los datos se agrupan según el uso de datos, no siempre tendrá nombres sensatos para darles a sus clases en Diseño Orientado a Datos.
Relación con bases de datos relacionales
El pensamiento detrás del diseño orientado a datos es muy similar a cómo se piensa acerca de las bases de datos relacionales. La optimización de una base de datos relacional también puede implicar un uso más eficiente del caché, aunque en este caso el caché no es el caché de la CPU sino páginas en la memoria.
- Un buen diseñador de bases de datos probablemente también dividirá los datos a los que se accede con poca frecuencia en una tabla separada en lugar de crear una tabla con una gran cantidad de columnas donde solo se utilizan algunas de ellas.
- O también podría optar por desnormalizar algunas de las tablas (tal vez en una sola tabla), para que no sea necesario acceder a los datos desde múltiples ubicaciones en el disco.
Al igual que con el diseño orientado a datos, estas decisiones se toman observando cuáles son los patrones de acceso a los datos y dónde está el cuello de botella en el rendimiento.
Mike Acton dio recientemente una charla pública sobre diseño orientado a datos :
Mi resumen básico sería: si desea rendimiento, piense en el flujo de datos, encuentre la capa de almacenamiento que tenga más probabilidades de arruinarlo y optimícela al máximo. Mike se está centrando en los errores de caché L2, porque lo hace en tiempo real, pero imagino que lo mismo se aplica a las bases de datos (lecturas de disco) e incluso a la Web (solicitudes HTTP). Creo que es una forma útil de programar sistemas.
Tenga en cuenta que esto no lo absuelve de pensar en algoritmos y complejidad del tiempo, solo enfoca su atención en descubrir el tipo de operación más costosa al que luego debe apuntar con sus locas habilidades de CS.