En general, lo que utilizo para hacer es: capa
datos:
Para el acceso a datos, que crear una interfaz, para cada objeto. Cada interfaz enumera todos los métodos públicos de acceso a datos para el objeto en cuestión. Para contener los datos, creo tipos de contenedores, también para cada objeto, que pueden ser estructuras o clases simples solo con datos. También confío en el conjunto de datos de idiomas, como listas, para almacenar mis datos, por lo que no estoy vinculado a un tipo de base de datos en particular. Después de eso, creo una clase que implementa las interfaces de datos, esta clase tiene todos los SQL y accede a la base de datos, por lo que en caso de cambio en la tecnología de almacenamiento de datos, esta es la única clase que se cambiará.
Capa de negocio:
¿Tiene toda la lógica con los datos, cómo validar, wich métodos de las interfaces de datos debe ser llamado y en qué orden.Esta clase recibe y "envía" datos al almacenamiento de datos o GUI, usando contenedores (listas por ejemplo) donde los tipos de datos son mis contenedores mencionados anteriormente.
GUI:
llama a los métodos de lógica de negocio y presentación de datos mostrar/formato. Aquí no hay lógica más que llamar a los métodos correctos de la lógica comercial.
Pequeño ejemplo de código de un contenedor (C#)
//Interface for Department class data access. DataStorage assembly
namespace DataStorage
{
public interface IDepartmentDS
{
void Open(); //Open data conection
void Close(); //Close data conection
List<Repositories.Department> List(); //Gets all departments (from data base)
}
}
//This class holds all data regarded a department. There's no logic here. Repositories assembly
namespace Repositories
{
public class Department
{
[Browsable(false)]
public Department()
{
}
[Browsable(false)]
public Department(String Symbol, String Name)
{
this.Symbol = Symbol;
this.DeptName = Name;
}
public Department(Department department)
{
this.Symbol = department.Symbol;
this.DeptName = department.DeptName;
}
[Browsable(false)]
public String Symbol { get; set; }
public String DeptName { get; set; }
}
}
//This class implements the data manipulation itself, accessing the real database.
//However the data exchange outside this class is done via repositories classes and
//Generics - Lists mainly
public class DataStorage : IDepartmentDS
{
//Here I use to put generic functions to connect with the database, format stored
//procedure parameters list etc.
//Implementation of the List method declare in the Department Interface
List<Repositories.Department> IDepartmentDS.List()
{
String query = String.Format("SELECT * FROM {0}", DepartmentTable);
int rows = 0;
DataSet ds = ExecSqlCommand(query, out rows); //this method is private to this class
if (ds == null)
return null;
List<Repositories.Department> list = new List<Repositories.Department>();
foreach (DataRow row in ds.Tables[0].Rows)
{
list.Add(new Repositories.Department((String)row[DepFN_Symbol], (String)row[DepFN_DepName]));
//DepFN_Symbol and the others are just const variables representing the column index
}
return list;
}
}
public class DepartmentLogic
{
public DepartmentLogic()
{
.....
}
public List<Repositories.Department> GetAllDepartments()
{
//Here I create an Instance of the DataStorage but using the Department interface
//so I restrict the access to Department data methods only. It could be a good
//idea here to use the factory pattern.
IDepartmentDS department = (IDepartmentDS) new DataStorage();
department.Open();
List<Repositories.Department> departments = department.List();
department.Close();
return departments;
}
}
Este ejemplo de lógica de negocios es, de hecho, muy simple, sólo se muestra cómo recuperar los datos de la capa de almacenamiento, pero siempre y cuando usted tiene acceso a los datos , puedes manipularlo de la manera que quieras. Solo un comentario aquí: tal vez esta solución debería ser repensada si se implementa en un servidor muy ocupado con miles de solicitudes porque puede usar mucha memoria.
Para la lógica de negocios y también el punto de vista de la interfaz de usuario, todos los datos se comunican entre módulos usando contenedores de uso general como listas. El punto de enlace entre todos esos módulos son las clases de contenedores, por lo que todas las clases están menos desacopladas.
UI hace requisiciones para las clases de lógica de negocios, por lo que actúa como un proveedor de servicios. Si lo hace de esa manera, cambiar la UI no afectará las clases que se muestran a continuación.
La lógica de negocios solicita y envía datos a las clases de almacenamiento de datos usando datos de propósito general, por lo que cambiar la base de datos/tecnología de almacenamiento no debería afectarlo.
Esa es la forma que utilizo para hacer y estoy tratando de mejorarlo;)
¿Podría dar un ejemplo en el que la lógica comercial recupera algunos datos de la capa de datos? – CasperT
Entiendo lo que quiere decir con contenedores, etc. Pero aún no estoy seguro de cómo debería recuperar los datos, de qué manera es el mejor. – CasperT
Creo que estoy siendo rechazado por esto: "Cada interfaz enumera todos los métodos públicos de acceso a datos para el objeto en cuestión." Realmente apreciaría algunos pequeños ejemplos – CasperT