Escolar Documentos
Profissional Documentos
Cultura Documentos
de Sistemas Software
Contenidos
! Guía
práctica 1. Object Constraint
Language (OCL)
! Guía práctica 2. La vista lógica
2
Guía práctica 1. OCL
Object Constraint Language
OCL
! Cuando diseñamos un sistema OO, es necesario especificar un conjunto de
restricciones semánticas:
" utilizar lenguaje natural conduce a ambiguedades
4
OCL
! OCL es un lenguaje declarativo: a partir del cual se
establece que debe ser hecho por el sistema, y no
como debe ser hecho
Usos de OCL
Ejemplos de su utilidad:
! Complementar diagramas UML: diagramas de clase, diagrama de
transición de estados, diagramas de actividades, etc
! Expresar la semántica de UML
! Especificar reglas de negocio
http://www.omg.org/docs/ptc/03-10-14.pdf
6
Conceptos Invariantes
básicos de OCL Pre- y Post-
condiciones
Instancia contextual
navegaciones
Expresiones OCL
En OCL es posible especificar expresiones OCL.
8
invariantes
! Un invariante es una condición que debe ser verdadera para todas las
instancias de un tipo específico en cualquier momento
! El tipo de la instancia contextual de una expresión OCL, el cual es parte de
una invariante, es escrito luego de la palabra reservada context.
! La palabra reservada inv: declara que la expresión OCL es una restricción
invariante
Instancia contextual
! Cada expresión OCL está escrita en el contexto de una instancia de un tipo
específico.
! La palabra reservada self es utilizada para referir a la instancia contextual.
context Habitación
10
Ejemplo de invariante
<<enumeration>>
Genero
mCuentas Masculino
Cuenta femenino
0..*
mTitulares /msaldo: Real
1..*
! Cliente
mCuentaNómina
mNombre: String
0..* Movimiento
mApellidos: String
mImporte: Real
mEdad: Integer mCuentaAsociada
mMovs mConcepto: String
Sexo: Genero
mFecha: Fecha
1 mtitular
0..*
mMovs
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
context Cliente
inv: mEdad>=18
11
12
Pre y post condiciones
context Empleado::aumentarsalario( cantidad: Real ): Real
pre: salario > 0
13
Navegaciones y
colecciones
Navegaciones Simples
context Habitación
inv: self.huespedes->size() <= self.número_de_camas
" el nombre de rol (del extremo opuesto de una relación) que vincula
la clase donde se define la expresión con otra clase del diagrama.
15
Navegaciones Simples
context Habitación
inv: self.Huesped->size() <= self.número_de_camas
Habitación
Huésped
número_piso : Integer
* nombre : String
número_habitación : Integer
edad : Integer
número_de_camas : Integer
sexo : {hombre, mujer}
tipo : {A, B}
16
Colecciones
! El tipo Collection es un tipo abstracto, con tipos de
colección concretos como sus subtipos.
– List / ArrayList
context Habitación
inv: self.Huesped->size() <= self.número_de_camas
17
Navegaciones combinadas
Las navegaciones no se limitan a una única asociación.
context Vuelo
18
Navegaciones y Colecciones
19
context Persona
20
Navegando desde
clases de Asociación
context job
21
Valores Básicos y
Tipos
Tipos Básicos
! En OCL, se definen un número de tipos básicos, los cuales están disponibles
para el modelador en todo momento. Estos tipos son valores predefinidos y son
independientes de cualquier modelo de objetos.
! Tipos Básicos:
" Boolean: true, false
" Real: *, +, -, /, etc.
23
Tipos Básicos
! Todos los classifiers de un modelo UML son tipos que pueden ser
utilizados en las expresiones OCL que estén asociadas a dicho
modelo.
24
Tipos Enumerados
Persona <<enumeration>>
nombre : String Genero
edad : Integer masculino
genero : Genero femenino
25
Conformidad de tipos
1 + ‘motocicleta’
23 * falso
26
Más sobre Conformidad de tipos
27
Ejemplo:
Ejemplo:
28
Profundizando algunos
Propiedades:
conceptos de OCL
• atributos
• operaciones
• extremos finales
de una asociación
Objetos y Propiedades
" Un atributo
<<invariant>>
Cliente
mNombre: String
mApellidos: String self.mEdad >= 17
mEdad: Integer
lim_max_mov:Integer
30
Propiedades: Atributos
31
Propiedades: Operaciones
Context Producto
32
Propiedades: Extremos finales de
asociaciones
objeto.nombredelextremoFinal
inv: self.empleados->notEmpty()
Combinando propiedades
context Cliente
Cliente
Cuenta Movimiento
mNombre: String 0..*
0..*
mTitulares /msaldo: Real mImporte: Real
mApellidos: String
1..* cuentas mMovs mConcepto: String
mEdad: Integer
mFecha: Date
lim_max_mov:Integer
34
Colecciones y
operaciones de Colecciones:
colección Set, orderedset, bag,
sequence, etc.
Operaciones colección:
Select, Reject, Exists,
etc.
Colecciones
36
Operaciones de Colecciones
! OCL define muchas operaciones en tipos de colección. Estas
operaciones permiten contar con una manera flexible y poderosa de
proyectar nuevas colecciones desde colecciones existentes.
colección->operaciónDeColeccion()
! Las operaciones son:
" ForAll
" Exists
" Includes
" etc
37
Operador Select
38
Operador Select (cont.)
context Proyecto
context Proyecto
context Proyecto
39
colección->operación( v | expresión-booleana-utilizando-v )
colección->operación( expresión-booleana)
“ v ” un iterador, es una referencia a los objetos en la colección
40
Operador Reject
context Proyecto
41
Operador collect
self.empleados->collect( fechaNacimiento )
42
Forma resumida de collect
Existe una forma resumida de escribir la operación collect y que hace que las
expresiones OCL sean mas fáciles de leer.
43
Operación ForAll
! Este operador permite especificar una expresión booleana que debe ser verdadera para
todos los elementos de una colección.
context Proyecto
44
Operación ForAll
context Proyecto
45
Operación Exists
context Proyecto
46
Ejemplo de la operación exists
<<enumeration>>
Genero
mCuentas Masculino
Cuenta femenino
0..*
mTitulares /msaldo: Real
1..*
Cliente
mNombre: String mCuentaNómina
0..* Movimiento
mApellidos: String
mImporte: Real
mEdad: Integer mCuentaAsociada
mMovs mConcepto: String
Sexo: Genero
mFecha: Date
1 mtitular
0..*
mMovs
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Date) : Integer
context Cuenta
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
context
! Cuenta
inv: self.mTitulares->exists(mEdad>=18)
48
Operación Size
context Cliente
mCuentas
Cuenta
0..*
mTitulares /msaldo: Real
1..*
Cliente
mNombre: String
mApellidos: String
mEdad: Integer
Sexo: Genero
49
50
Otras operaciones
! notEmpty()
" En el caso de una asociación con multiplicidad 0..1 es útil verificar si existe un objeto
o no cuando navegamos la asociación,
context Persona
<<enumeration>>
! Union( colección_de_objetos )
! Including( Objeto)
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
El saldo de toda cuenta debe ser siempre mayor o igual a cero (el
saldo se calcula como la suma del importe de sus movimientos).
52 self.mMovs->collect(mImporte)->sum() > 0
Ejemplo de la op. collect
<<enumeration>>
Genero
mCuentas Masculino
Cuenta femenino
0..*
mTitulares /msaldo: Real
1..*
! Cliente
mCuentaNómina
mNombre: String
0..* Movimiento
mApellidos: String
mImporte: Real
mEdad: Integer mCuentaAsociada
mMovs mConcepto: String
Sexo: Genero
mFecha: Fecha
1 mtitular
0..*
mMovs
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
El saldo de toda cuenta debe ser siempre mayor o igual a cero (el
saldo se calcula como la suma del importe de sus movimientos).
self.mMovs.mImporte->sum()
53 >0
Let y expresiones
<<definition>>
Expresiones let
If esDesocupado then
55
Expresiones def
<<enumeration>>
Genero
mCuentas Masculino
Cuenta femenino
! mTitulares
0..*
/msaldo: Real
1..*
! Cliente
mCuentaNómina
mNombre: String
0..* Movimiento
mApellidos: String
mImporte: Real
mEdad: Integer mCuentaAsociada
mMovs mConcepto: String
Sexo: Genero
mFecha: Fecha
1 mtitular
0..*
mMovs
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
context Cuenta
context Cuenta
56
inv: saldo > 0
Reglas de
Derivación
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
58
Ej. de reglas de derivación (cont.)
<<enumeration>>
Genero
mCuentas Masculino
Cuenta femenino
0..*
mTitulares /msaldo: Real
1..*
! Cliente
mCuentaNómina
mNombre: String
0..* Movimiento
mApellidos: String
mImporte: Real
mEdad: Integer mCuentaAsociada
mMovs mConcepto: String
Sexo: Genero
mFecha: Fecha
1 mtitular
0..*
mMovs
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
/MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
context Tarjeta
derive: self.mNombreTitular=
59
mTitular.mNombre.concat(“ “).concat(mTitular.mApellidos)
includes
<<enumeration>>
Genero
mCuentas Masculino
Cuenta femenino
0..*
mTitulares /msaldo: Real
1..* 1
! Cliente
mCuentaNómina
mNombre: String
0..* Movimiento
mApellidos: String
mImporte: Real
mEdad: Integer mCuentaAsociada
mMovs mConcepto: String
Sexo: Genero
mFecha: Fecha
1 mtitular
0..*
mMovs
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
self.mCuentas->includes(self.mCuentaNómina)
60
includesAll
<<enumeration>>
Genero
mCuentas Masculino
Cuenta femenino
0..*
mTitulares /msaldo: Real
1..* *
! Cliente
mCuentaNómina
mNombre: String
0..* Movimiento
mApellidos: String
mImporte: Real
mEdad: Integer mCuentaAsociada
mMovs mConcepto: String
Sexo: Genero
mFecha: Fecha
1 mtitular
0..*
mMovs
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
self.mCuentas->includesAll(self.mCuentaNómina)
61
Diagramas de Estados
<<enumeration>>
Genero
mCuentas Masculino
Cuenta femenino
0..*
mTitulares /msaldo: Real
1..* *
Cliente
! mNombre: String mCuentaNómina
Movimiento
mApellidos: String 0..*
mImporte: Real
mEdad: Integer mCuentaAsociada
mMovs mConcepto: String
Sexo: Genero
mFecha: Fecha
1 mtitular
0..*
mMovs
Fecha
mtarjetas 0..* <<datatype>>
mDia: Integer
Tarjeta mMes: Integer
MNombreTitular: String mAño: Integer
ObtenerMes(d: Fecha) : Integer
context Cuenta
62
inv: self.oclInState(SaldoPositivo) implies (msaldo > 0)
Ejercicio ¿?
63
Ejercicio ¿?
64
Expresiones OCL init
Movimiento
mImporte: Real
context Tarjeta::mMovs mConcepto: String
mFecha: Fecha
!
init: Set{} 0..*
mMovs
Cliente
mNombre: String
mApellidos: String
mEdad: Integer
Sexo: Genero
1 mtitular
0..*
mtarjetas
Tarjeta
/mNombreTitular: String
mValidoDesde: Fecha
mValidoHasta: Fecha
65
pre:
if habitación->notEmpty() then
habitacion.huespedes->includes(h)
else
h.habitacion.numero_piso =
self.piso_numero
endif
66
Práctica
sobre OCL
indice
68
A tener en cuenta...
69
A tener en cuenta...
Es importante tener en cuenta...
70
Ejemplo de ejercicio
Indique el horario en el cual inicia el ejercicio: Hora:..........Min:.........Seg:..........
context Auto inv:
self.mantenimientos->select(m|m.repuestos->notEmpty() )
71
Se requiere rescribir la expresión OCL de tal forma que sea válido el siguiente
requerimento:
self.mantenimientos->select(m|m.repuestos->Empty() )
73
75
Implementando OCL
El
! orden de los pasos durante el proceso de implementación es el
siguiente:
(p1) clases
78
(p1) atributos
p.1.2. Cada atributos (privado, protegido, publico) de una
clase se transforma en un miembro de clase, privado, con
operaciones get y set en la clase Java. La visibilidad de las
! operaciones es equivalente a la visibilidad del atributo.
Si el atributo es read-only, la operación set se omite.
AttributeType getAttributeName()
79
(p1) asociaciones
p.1.3. Cada Extremo de asociacion en el modelo se Movimiento
mImporte: Real
transforma en un miembro de clase, privado, con mConcepto: String
mFecha: Fecha
operaciones get y set en la clase Java. La visibilidad
! de las operaciones es equivalente a la visibilidad 0..*
mMovs
del extremo en el modelo.
1 mtitular
public class Tarjeta {
init: Set{}
80
(p1) asociaciones cont.
public class Tarjeta { Movimiento
mImporte: Real
mConcepto: String
Cliente titular; mFecha: Fecha
!
HashSet mMovs; 0..*
mMovs
titular = t; } Cliente
mNombre: String
mApellidos: String
public Titular getTitular(Titular t) { mEdad: Integer
Sexo: Genero
return titular; }
1 mtitular
mMovs.add(m); } Tarjeta
/mNombreTitular: String
mValidoDesde: Fecha
Public HashSet getmMovs() { mValidoHasta: Fecha
return mMovs}
81
82
(p2) la
implementacion de una
libreria estandard de
OCL
Integer int
Real real
String String
Boolean boolean
84
(p2) Implem. una librería standard
OCL
! collection Type Java Type
Set HashSet
Existen dos tipos de operación de colección aquellas que iteran sobre cada
elemento de la colección para realizar una operación (exists, select, collect) y otras
que son mas simples como union, size.
A las primeras se las denomina iteradores de colección. No existen operaciones
equivalentes en Java para todas las operaciones de colección de OCL !
85
Iterator it = mMovs.iterator();
While (it.hasNext()) {
result.add(elem) ;
86
}} return result;
(p3) la
implementación de las
expresiones OCL
self.attribute
es transformado a
this.getAttribute();
self.associationEnd # navegacion
es transformado a
this.getAssociationEnd(); # operationCall
88
(p3) orden de evaluacion!
!
(this.getTitular().getTipo() >= 0 )
||
Cliente
mNombre: String
(this.getTitular() == null) mApellidos: String
mEdad: Integer
tipo: Integer
0...1 mtitular
Error de java.lang.nullPointerException
0..*
Tarjeta
/mNombreTitular: String
mValidoDesde: Fecha
mValidoHasta: Fecha
89
Tarjeta
return getTitular().getNombre() /mNombreTitular: String
mValidoDesde: Fecha
mValidoHasta: Fecha
+ “ “ + getTitular.getApellidos(); }
self.mValidoDesde.estaAntes(mValidoHasta)
92
(p4) expr. invariantes
2. Expresiones Invariantes.
! context Tarjeta
inv: titular.mEdad > = 18
boolean chequearTodosLosInv () {
mtarjetas 0..*
Tarjeta
MNombreTitular: String
return invfechasValidas() & mValidoDesde: Fecha
mValidoHasta: Fecha
agregarTarjeta(t: Tarjeta)
assert( ! mtarjetas.contains(t) ) ; 1 mtitular
Tarjeta
// <cuerpo de la operacion> MNombreTitular: String
mValidoDesde: Fecha
mValidoHasta: Fecha
//
94
assert (mtarjetas = tarjetas_old.add(t) ); }
Otras transparencias no
utilizadas en el curso
Propiedades: Operaciones
! Por ejemplo:
aDocente.ingreso(aFecha)
96
Propiedades: Operaciones
param. de
entrada param. de
salida
97
Propiedades: Operaciones
98
Propiedades: Operaciones
param. de
entrada param. de
salida
aDocente.ingreso(aFecha).result = 500
99
Operación
iterate
Collection->iterate(
element: Type 1 ;
! acum : Type2 = <expresion>
| <expression-con-element-y-acum> )
->Iterate(
p: Titular ;
1..*
mTitulares
Cliente
mNombre: String
mayores: Integer = 0 | mApellidos: String
mEdad: Integer
Sexo: Genero
if p.mEdad >= 18 then
mayores +1
else mayores
endif )
in
10r > 0
1
Guía práctica 2. La
vista lógica
Introducción
! En la Vista Lógica se definen los modelos
que representan el diseño detallado
! Se definen las capas de la aplicación y los
componentes principales dentro de cada
capa
! Se crean mecanismos comunes para
establecer las funcionalidades a las
diferentes áreas de la aplicación
Arquitectura de Capas
! Patrón de arquitectura [Buschmann] que
establece la distribución de una aplicación en
divisiones lógicas desarrolladas y mantenidas
como módulos independientes, incluso en
plataformas distintas
! La arquitectura de 3 capas esta divida en:
" Interfaz de usuario, componentes que interactúan
con el usuario final
" Lógica de negocio, contienen las reglas de negocio
de nuestra aplicación
" Persistencia, contiene el acceso y almacenamiento
de los datos.
Refinamiento del Modelo de Capas
Modelo Cliente/Servidor Modelo 3 Capas Modelo 6 Capas (Refinado )
Control de Usuario
Control de
Procesos deprocesos
Negocio
Lógica de Negocio
Objetos dede
Entidades Negocio
Negocio
Servidor
Acceso a Datos
Persistencia
F Datos
ísica de
Físicos
Datos
Interfaz de Usuario
3 Capas Lógicas
Persistencia
Entidades de Componentes de
Negocio Acceso a Datos
Datos de la
Aplicación
Entidades de Componentes de
Negocio Acceso a Datos
Datos de la
Aplicación
<<extend>>
Si el cliente no
Validar Cliente está registrado Registrar Cliente
<<include>>
<<include>>
<<extend>>
<<extend>>
1
Producto
Categoria productoId : String
categoriaId : String nombre : String
1 0..n
nombre : String descripcion : String
descripcion : String urlFoto : String
precio : Single
verProductos()
BuscarProducto()
Interfaz de Usuario del Modelo de Diseño
! A partir de los casos de Uso debemos determinar que
componentes de interfaz de usuario se han de
representar
! Definimos una clase pantalla genérica que contendrá
toda la funcionalidad y controles necesarios para
representar un formulario en una pantalla
! Cada una de las pantallas extenderá de dicha clase y le
incorporará la/s operacion/es que pueden invocarse
desde ella
! La relaciones que existen entre las pantallas es de uso
puesto que unas se invocan a otras
Sesion
<<uses>>
insertarObjeto()
obtenerObjeto()
duracionSesion() Si estamos en Web la sesion es mantenida por el propio motor.
Si estamos en Windows, la sesión estaría referenciada por una pantalla
principal que estaría en ejecución en todo momento
Entidad de Negocio (EN)
! Un modelo de dominio contiene múltiples clases
con relaciones y debemos decidir como mapear
las clases en diferentes componentes EN
Entidad de Negocio
! Tómate tu tiempo para analizar y modelar las
EN de tu aplicación, en lugar de definir una EN
por cada clase
<<uses>>
EN_Pedido Pantalla Producto Pantalla Categoria
<<uses>> pedidoId : String (from Interfaz Usuario) (from Interfaz Usuario)
fecha : Date
EN_Cliente direccion : String BuscarProducto() verProductos()
clienteId : String localidad : String
nombre : String provincia : String
Sesion NIF : String codigoPostal : Integer <<uses>>
(from Interfaz Usuario) email : String tipoTargeta : String <<uses>>
0..n 1 1 0..n
login : String tipoPago : String
insertarObjeto() password : String numeroTargeta : Long
obtenerObjeto() fechaCaducidad : Date EN_Producto
duracionSesion() validarCliente() estado : String productoId : String EN_Categoria
registrarCliente() nombre : String categoriaId : String
setAtributos() getAtributos() descripcion : String nombre : String
0..n 1
getAtributos() setAtributos() urlFoto : String descripcion : String
realizarPedido() precio : Single
La sesión referencia a un pagarPedido() getAtributos()
cliente que podrá realizar anyadirProducto() BuscarProducto() setAtributos()
más de un pedido. setAtributos() verProductos()
1
getAtributos()
0..n
EN_LineaPedido
lineaPedidoId : String
unidades : Integer
setAtributos()
getAtributos()
Componente de Acceso a Datos
! Para cada EN, definimos un CAD que será definido
como sigue:
" CAD_Cliente: Esta clase provee los servicios para recuperar y
modificar los datos de las tablas Cliente
" CAD_Pedido: Esta clase provee los servicios para recuperar y
modificar los datos de las tablas Pedido y LineaPedido
" CAD_Producto: Esta clase provee los servicios para recuperar y
modificar los datos de la tabla Producto
" CAD_Categoria:Esta clase provee los servicios para recuperar y
modificar los datos de la tabla Categoria
getAtributos()
1 setAtributos()
realizarPedido()
pagarPedido()
anyadirProducto() 1
1 1
1
1
CAD_Cliente CAD_Pedido CAD_Producto CAD_Categoria
Implementando el Componente
de Interfaz de Usuario en .NET
$ Para implementar el interfaz de usuario en .NET
se puede realizar en Windows Forms o Web Forms
Seguridad
Seguridad basada en Seguridad basada en
código y basada en roles roles
Curso 08-09
Propiedades del formulario Windows Forms
Botón Eventos
Nombre Formulario
Botón Ordenación
Botón Alfabético
Panel Descripción
Curso 08-09
$ Codebehind
$ El atributo de página Codebehind identifica la página
de código subyacente que tiene la lógica que soporta el
formulario Web Form. Cuando Visual Studio .NET crea
un formulario Web Form, como WebForm1.aspx,
también crea una página de código subyacente,
WebForm1.aspx.vb o WebForm1.aspx.cs
Atributos de cuerpo
$ Los atributos de la etiqueta <Body> definen el
aspecto de los objetos que se muestran en el
navegador del cliente
<body ms_positioning="GridLayout">
Implementación de Sesión en
ASP.NET
! Las sesiones son tablas Hash en memoria con un
timeout especificado.
Session[ username ] = Jose Martínez ;
Session[ color ] = Blue ;
Operaciones de un CAD
! Un CAD debería proveer los métodos para
realizar las siguientes tareas sobre la BD:
" Crear registros en la BD
" Leer registros en la BD y devolver las entidades de
negocio al componente invocante
" Actualizar registros en la BD, usando entidades de
negocio proporcionadas por el componente invocante
" Borrar registros de la BD
" Las EN son construidas desde los datos que proviene de una o
más tablas de la BD
Composición en un CEN
Ejemplo de Pedido y sus Líneas de Pedido en .NET
public class ENPedido public string IdCliente
{ {
// Atributos de Pedido get { return idCliente; }
private int idPedido; set { idCliente = value; }
private string idCliente; }
private DateTime fechaPedido; public DateTime FechaPedido
private DateTime fechaEnvio; {
// Atributo que contiene las Lineas de Pedido get { return fechaPedido; }
private DataSet lineasPedido; set { fechaPedido = value;}
// Propiedades públicas }
public int IdPedido public DateTime FechaEnvio
{ {
get { return idPedido; } get { return fechaEnvio; }
set { idPedido = value; } set { fechaEnvio = value; }
} }
Composición en un CEN
// Propiedad para exponer públicamente las Líneas de Pedido
public DataSet LineasPedido
{
get { return lineasPedido; }
set { lineasPedido = value; }
}
// Métodos adicionales para simplificar el acceso a las Lineas
public bool estaProductoEnPedido (int idProducto)
{
// La clave primaria debe estar definida en la DataTable
DataRow fila = lineasPedido.Tables[0].Rows.Find(idProducto);
if (row != null) return true;
else return false;
}
public int NumeroDeLineas
{
get
{
return lineasPedido.Tables[0].Rows.Count;
}}}
public ActualizarProducto () {
cadProducto.ActualizarProducto (idProducto, nombre, cantidad, precioUnitario)
}
public BorrarProducto() {
cadProducto.BorrarProducto (idProducto);
}
Ventajas de un CEN con CRUD
! Ventajas:
" Encapsulación. El CEN encapsula las operaciones definidas por
un CAD
" Interfaz para el Cliente. El cliente debe tratar solo con un interfaz
para hacer persistente los CEN. No hay necesidad de acceder
directamente al CAD
" Campos privados. Permite ocultar información que no quieres
exponer al cliente
! Desventajas:
" Tratar con colecciones de EN. Los métodos de un CEN
pertenecen a una única instancia. Para soportar colecciones,
debes definir métodos estáticos que devuelven un array o
colección de entidades
" Se incrementa el tiempo de desarrollo. La aproximación
tradicional orientada a objetos requiere de más diseño y
esfuerzo de desarrollo que cuando se trabaja con estructuras
existentes como DataSets