sistema programacion orientado orientada objetos modelo gestor ejercicios ejemplos ejemplo datos sql linq database-design oop

sql - orientado - programacion orientada a objetos



¿Cómo puede un programador orientado a objetos hacerse una idea de la programación basada en bases de datos? (11)

¡Los productos ni siquiera deberían saber que existen las categorías, y mucho menos tienen un campo de datos que contenga una identificación de categoría!

No estoy de acuerdo, creo que en lugar de proporcionar una identificación de categoría, deje que su orm lo haga por usted. Luego, en el código tendrías algo así como (tomando prestado de NHib''s y Castle''s ActiveRecord):

class Category [HasMany] IList<Product> Products {get;set;}

...

class Product [BelongsTo] Category ParentCategory {get;set;}

Entonces, si quisieras ver en qué categoría está el producto, simplemente harías algo simple como:

Product.ParentCategory

Creo que puedes configurar el orm de manera diferente, pero de cualquier forma para la cuestión de la herencia, pregunto ... ¿por qué te importa? O hazlo con objetos y olvídate de la base de datos o hazlo de otra manera. Puede parecer una tontería, pero a menos que realmente no pueda tener un montón de tablas, o no quiera una sola mesa por alguna razón, ¿por qué le importa la base de datos? Por ejemplo, tengo la misma configuración con algunos objetos heredables, y me dedico a mi negocio. No he revisado la base de datos actual ya que no me concierne. El SQL subyacente es lo que me concierne y los datos correctos vuelven.

Si tiene que preocuparse por la base de datos, necesitará modificar sus objetos o crear una forma personalizada de hacer las cosas.

He estado programando en C # y Java durante poco más de un año y tengo una comprensión decente de la programación orientada a objetos, pero mi nuevo proyecto lateral requiere un modelo basado en bases de datos. Estoy usando C # y Linq, que parece ser una herramienta muy poderosa, pero estoy teniendo problemas con el diseño de una base de datos en torno a mi enfoque orientado a objetos.

Mis dos preguntas principales son:

¿Cómo trato la herencia en mi base de datos? Digamos que estoy compilando una aplicación de asignación de personal y tengo una clase abstracta, Evento. Del Evento I deriva clases abstractas ShiftEvent y StaffEvent. Luego tengo clases concretas Shift (derivado de ShiftEvent) y StaffTimeOff (derivado de StaffEvent). Hay otras clases derivadas, pero por razones de argumentación, esto es suficiente.

¿Debo tener una tabla separada para ShiftEvents y StaffEvents? ¿Tal vez debería tener tablas separadas para cada clase concreta? Ambos enfoques parecen darme problemas cuando interactúo con la base de datos. Otro enfoque podría ser tener una tabla de eventos, y esta tabla tendría columnas anulables para cada tipo de datos en cualquiera de mis clases concretas. Todos estos enfoques parecen que podrían impedir la extensibilidad en el futuro. Es más que probable que haya un tercer enfoque que no he considerado.

Mi segunda pregunta:

¿Cómo trato las colecciones y las relaciones uno a muchos de una manera orientada a objetos?

Digamos que tengo una clase de productos y una clase de categorías. Cada instancia de Categorías contendría uno o más productos, pero los productos mismos no deberían tener conocimiento de las categorías. Si quiero implementar esto en una base de datos, entonces cada producto necesitaría una identificación de categoría que se asigna a la tabla de categorías. Pero esto introduce más acoplamiento de lo que preferiría desde el punto de vista OO. ¡Los productos ni siquiera deberían saber que existen las categorías, y mucho menos tienen un campo de datos que contenga una identificación de categoría! ¿Hay una mejor manera?


Creo que un poco de pragmatismo sería bueno aquí. Las asignaciones entre objetos y tablas siempre tienen un poco de extrañeza aquí y allá. Esto es lo que hago:

Uso Ibatis para hablar con mi base de datos (de Java a Oracle). Cada vez que tengo una estructura inheretance donde quiero que se almacene una subclase en la base de datos, utilizo un "discriminador". Este es un truco donde tienes una tabla para todas las Clases (Tipos) y tienes todos los campos que posiblemente quieras almacenar. Hay una columna extra en la tabla, que contiene una cadena que es utilizada por Ibatis para ver qué tipo de objeto necesita devolver.

Se ve raro en la base de datos y, a veces, puede provocar problemas con las relaciones con campos que no están en todas las clases, pero el 80% de las veces esta es una buena solución.

Con respecto a su relación entre la categoría y el producto, agregaría una columna categoryId al producto, porque eso haría la vida realmente fácil, tanto en cuanto a SQL como a Mapeo. Si realmente está atascado haciendo la "cosa teóricamente correcta", puede considerar una tabla adicional que tenga solo 2 columnas, conectando las categorías y sus productos. Funcionará, pero generalmente esta construcción solo se usa cuando necesita relaciones de muchos a muchos.

Intenta mantenerlo lo más simple posible. Tener una "solución académica" es bueno, pero en general significa un exceso de habilidad y es más difícil de refactorizar porque es demasiado abstracto (como ocultar las relaciones entre Categoría y Producto).

Espero que esto ayude.


En mi opinión, estos paradigmas (el Modelo relacional y OOP) se aplican a diferentes dominios, lo que dificulta (e inútil) tratar de crear un mapeo entre ellos.

El modelo relacional se trata de representar hechos (como "A es una persona"), es decir, cosas intangibles que tienen la propiedad de ser "únicas". No tiene sentido hablar de varias "instancias" del mismo hecho: simplemente está el hecho.

La Programación Orientada a Objetos es un paradigma de programación que detalla una forma de construir programas de computadora para cumplir ciertos criterios (reutilización, polimorfismo, ocultamiento de información ...). Un objeto es típicamente una metáfora de algo tangible: un automóvil, un motor, un gerente o una persona, etc. Las cosas tangibles no son hechos. Puede haber dos objetos distintos con un estado idéntico sin que sean el mismo objeto (de ahí la diferencia entre equals y == en Java, por ejemplo).

Spring y herramientas similares proporcionan acceso a datos relacionales mediante programación, de modo que los hechos se pueden representar mediante objetos en el programa. Esto no significa que el POO y el Modelo Relacional sean los mismos o que se confundan entre sí. Use el Modelo Realational para diseñar bases de datos (colecciones de hechos) y OOP para diseñar programas de computadora.

TL; DR version (desajuste de impedancia relacional de objeto destilado):

Hechos = la receta en tu refrigerador. Objetos = el contenido de tu refrigerador.


Hay varias posibilidades para mapear un árbol de herencia a un modelo relacional. NHibernate, por ejemplo, admite la ''tabla por jerarquía de clases'', tabla por subclase y tabla por estrategias de clases concretas: http://www.hibernate.org/hib_docs/nhibernate/html/inheritance.html

Para su segunda pregunta: puede crear una relación 1: n en su base de datos, donde la tabla Productos tiene una clave foránea en la tabla Categorías. Sin embargo, esto no significa que su Clase de Producto necesite tener una referencia a la instancia de Categoría a la que pertenece. Puede crear una clase de Categoría, que contiene un conjunto o una lista de productos, y puede crear una clase de producto, que no tiene ninguna noción de la Categoría a la que pertenece. De nuevo, puede hacer esto fácilmente usando (N) Hibernate; http://www.hibernate.org/hib_docs/reference/en/html/collections.html


La gran pregunta: ¿cómo puedes entenderlo? Solo requiere práctica. Intenta implementar un diseño de base de datos, tiene problemas con su diseño, refactoriza y recuerda para la próxima vez lo que funcionó y lo que no funcionó.

Para responder a sus preguntas específicas ... esto es un poco de opinión, como en "cómo lo haría", sin tomar en cuenta las necesidades de rendimiento y tal. Siempre comienzo completamente normalizado y voy desde allí en base a las pruebas del mundo real:

Table Event EventID Title StartDateTime EndDateTime Table ShiftEvent ShiftEventID EventID ShiftSpecificProperty1 ... Table Product ProductID Name Table Category CategoryID Name Table CategoryProduct CategoryID ProductID

También reiterando lo que dijo Pierre: una herramienta ORM como Hibernate hace que lidiar con la fricción entre las estructuras relacionales y las estructuras OO sea mucho más agradable.


Linq a SQL usando una tabla por solución de clase:

http://blogs.microsoft.co.il/blogs/bursteg/archive/2007/10/01/linq-to-sql-inheritance.aspx

Otras soluciones (como mi favorita, LLBLGen) permiten otros modelos. Personalmente, me gusta la solución de tabla única con una columna discriminatoria, pero probablemente sea porque a menudo consultamos en la jerarquía de herencia y, por lo tanto, la vemos como la consulta normal, mientras que consultar un tipo específico solo requiere un cambio de "dónde".

Todo dicho y hecho, personalmente siento que mapear OO en tablas es colocar el carro antes que el caballo. Ha habido continuas afirmaciones de que el desajuste de impedancia entre OO y las relaciones se ha resuelto ... y ha habido muchas bases de datos específicas de OO. Ninguno de ellos ha destronado la poderosa simplicidad de la relación.

En cambio, tiendo a diseñar la base de datos con la aplicación en mente, mapear esas tablas a entidades y construir desde allí. Algunos encuentran esto como una pérdida de OO en el proceso de diseño, pero en mi opinión la capa de datos no debería estar hablando lo suficientemente alto en su aplicación como para afectar el diseño de los sistemas de orden superior, solo porque usó un modelo relacional para almacenamiento .



Mi conjetura fuera de mi cabeza:

Sobre el tema de la herencia, sugiero tener 3 tablas: Evento, Evento Shift y Evento del personal. El evento tiene los elementos de datos comunes más o menos como se definió originalmente.

El último puede ir para otro lado, creo. Puede tener una tabla con ID de categoría e ID de producto sin otras columnas donde, para una ID de categoría determinada, devuelva los productos, pero es posible que el producto no necesite obtener la categoría como parte de cómo se describe a sí mismo.



También llegué a comprender el diseño de bases de datos, SQL y, en particular, la visión del mundo centrada en datos antes de abordar el enfoque orientado a objetos. El desajuste de impedancia relacional-objeto todavía me desconcierta.

Lo más parecido que he encontrado para manejar esto es esto: mirar objetos no desde una perspectiva de programación orientada a objetos, o incluso desde una perspectiva de diseño orientado a objetos sino desde una perspectiva de análisis orientado a objetos. El mejor libro sobre OOA que obtuve fue escrito a principios de los 90 por Peter Coad.

En el lado de la base de datos, el mejor modelo para comparar con OOA no es el modelo relacional de datos, sino el modelo Entidad-Relación (ER). Un modelo ER no es realmente relacional, y no especifica el diseño lógico. Muchos apologistas relacionales piensan que es la debilidad de ER, pero en realidad es su fortaleza. ER se utiliza mejor no para el diseño de la base de datos sino para el análisis de requisitos de una base de datos, también conocido como análisis de datos.

El análisis de datos ER y OOA son sorprendentemente compatibles entre sí. ER, a su vez, es bastante compatible con el modelado de datos relacionales y, por lo tanto, con el diseño de bases de datos SQL. OOA es, por supuesto, compatible con OOD y por lo tanto con OOP.

Esto puede parecer el camino más largo. Pero si mantiene las cosas lo suficientemente abstractas, no perderá demasiado tiempo en los modelos de análisis, y le resultará sorprendentemente fácil superar el desajuste de la impedancia.

Lo más importante que hay que superar en términos de diseño de base de datos de aprendizaje es este: los enlaces de datos como la clave externa al enlace de clave principal a los que se ha opuesto en su pregunta no son nada horribles. Son la esencia de vincular datos relacionados entre sí.

Hay un fenómeno en la prebase de datos y los sistemas orientados a preobjetos llamado efecto dominó. El efecto dominó es cuando un cambio aparentemente trivial en un sistema grande termina causando los cambios necesarios en todo el sistema.

OOP contiene el efecto dominó principalmente a través de la encapsulación y la ocultación de información.

El modelado de datos relacionales supera el efecto dominó principalmente a través de la independencia de los datos físicos y la independencia de los datos lógicos.

En la superficie, estos dos parecen modos de pensamiento fundamentalmente contradictorios. Eventualmente, aprenderá a usarlos a ambos para una buena ventaja.


Tuve el problema opuesto: cómo entender OO después de años de diseño de la base de datos. En cuanto a eso, una década antes tuve el problema de hacerme cargo de SQL después de años de programación de archivos planos "estructurados". Sin embargo, existen suficientes similitudes entre la clase y la descomposición de la entidad de datos para inducirlo a creer que son equivalentes. Ellos no son

Tiendo a estar de acuerdo con la opinión de que una vez que se compromete con una base de datos relacional para el almacenamiento, entonces debe diseñar un modelo normalizado y comprometer su modelo de objetos donde sea inevitable. Esto se debe a que el DBMS lo limita más de lo que está con su propio código: crear un modelo de datos comprometido es más probable que le cause dolor.

Dicho esto, en los ejemplos dados, tiene opciones: si ShiftEvent y StaffEvent son en su mayoría similares en términos de atributos y se procesan juntos como Eventos, me inclino por implementar una sola tabla de Eventos con una columna de tipo. Las vistas de una sola tabla pueden ser una forma efectiva de separar las subclases y en la mayoría de las plataformas de db son actualizables. Si las clases son más diferentes en términos de atributos, entonces una tabla para cada uno podría ser más apropiada. No creo que me guste la idea de las tres mesas: las relaciones "tiene uno o ninguno" pocas veces son necesarias en el diseño relacional. De todos modos, siempre puede crear una vista de evento como la unión de las dos tablas.

En cuanto a Producto y Categoría, si una Categoría puede tener muchos Productos, pero no al revés, entonces la forma relacional normal para representar esto es que el producto contenga una identificación de categoría. Sí, es un acoplamiento, pero solo es un acoplamiento de datos, y no es un pecado mortal. La columna probablemente debería estar indexada, de modo que sea eficiente recuperar todos los productos para una categoría. Si realmente te horroriza la idea, imagina que es una relación de muchos a muchos y usa una tabla de categorización de productos por separado. No es un gran problema, aunque implica una posible relación que en realidad no existe y podría inducir a error a alguien que vendrá a la aplicación en el futuro.