none
Referencia circular entre capas .evitar. RRS feed

  • Pregunta

  • hola grupo

     les consulto again sobre una problematica , (perdon se me hizo largo)

    estoy revisando una aplicacion  con asp.net que tiene una sola capa y esta muy acoplado empece a desglozar y arme un arquitectura asi:


    UI  -> servicios ->Dominio (clases del dominio ).  

    y tengo una proyecto Seguridad vertical(usan las tres) que tiene una clase llamada UserContext singlenton (tiene datos de usarios y permisos sobre la aplicacion),
    -que se usa desde ui donde esta se se setea valores desde el login los permisos y luego  cada pagina usa el Usercontext para  verificar que control habilitar
     
     - esta capa seguridad se la usa en dominio para auditoria.

    -desde servicio se lo usa tambien para setear valores por ejemplo : desde el login haria    userContext.Instance.usuario = GestionSeguridad.UsuarioLogin(txtUsuario.Text, txtContraseña.Text);


    el tema es que seguridad usa servicos y ahi tengo ref circular :  tengo una propiedad que es as :

     public XmlDocument XmlmMenu
            {
                get
                {
                    //if (_xmlMenu == null)
                        _xmlMenu = GenerarMenu(this.Menu);// esto ahora es Servicos.GenerarXmlMenu..
                    return _xmlMenu;
                }
                set
                {
                    _xmlMenu = value;
                }
            }

    esto pensaba solucionar con reflexion para llamar el metodo en servicios no se si es optimo.o es la mejor alternativa.
     
    pero  ademas la clase UserContext tiene otras propiedades que son  clases del dominio por ejemplo public List<PermisosRol> Permisos siendo permisosRol una clase domino y otro , pense en armar un clase dto vertical  al resto tambien
    pero no quiero romper lo que esta hecho en la ui por ahora.esto no se como podria hacer para no romper la ui y seguir devolviendo objetos de dominio para que todo siga
    funcionando. (dominio tambien se pondria como vertical mientras tanto hasta que en algun momento reemplace por dtos).

    2)Otra inquietud que tenia es que mi aplicacion es uow o sea se agregan varios datos en memoria y despeus se manda a guardar todo junto.En general se maneja con
    datatables y pensaba en la capa de servicios recibir y devolve datatables y list <T>(pero preferene en la capa de servicios voy a recibir datables yab devolver datatables  para poder verificar el estado o la version de la row para ver si se agrego algo nuevo o se modifico. esto como se podria manejar con List<T> deberia implementar un mecanismo para saber si se agrego o modifico. No tengo un ORM, es ado net para traer datos y para  persistencia tengo devexpress Espero se entienda

    gracias



    martes, 22 de enero de 2013 0:00

Respuestas

  • para resolver la ref de seguridad con el dominio , vos comentas que  podria ussar interfaces y ademas crear la instancia como reflection

    aqui explico algo sobre el tema

    Archivos de Configuración - Crear secciones propia (3/3)

    analiza el titulo "Implementación con interfaz Común", alli planteo este tema

    podrias configurar y desacoplar mediente intefaces

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    • Marcado como respuesta sebastian viga jueves, 24 de enero de 2013 18:25
    miércoles, 23 de enero de 2013 12:20
  • Hola Sebastián.

    Permíteme darte algunas ideas generales que puedes aplicar o no en tu proyecto:

    1) La capa de UI puede comunicarse perfectamente con la capa de lógica de negocios sin necesitar ninguna otra capa. Te recomiendo modelar tu capa de negocio como un conjunto de INTERFACES (que puedes tener en un proyecto de VS.Net) y un conjunto de clases que implementan interfaces. Pongamos un ejemplo: por un lado defines la interfaz ICliente y por otra parte la clase Cliente que implementa ICliente. La interfaz de usuario podría depender exclusivamente de las Interfaces.

    2) El patrón FACTORIA es muy útil para establecer la interacción entre la capa de Lógica o Modelo y la Capa de Persistencia o Datos. Lo que yo hago es definir una Interface que expone los métodos necesarios para crear objetos de la lógica de negocio. También conviene crear interfaces para los almacenamientos, por ejemplo: IAlmacenamientoCliente. 

    Tu modelo UML debería entonces parecerse a esto:




    logo osoft
    Si he contestado tu pregunta, por favor marca mi post como respuesta.
    ...Y si mi post te ha servido, márcalo como útil smile

    • Marcado como respuesta sebastian viga jueves, 24 de enero de 2013 18:25
    miércoles, 23 de enero de 2013 14:13
  • El tema que la ui por ahora me tiene que seguir devolviendo objetos del dominio para que no rompa . aca pienso hacer una interfaz entre los dtos  y los objeto de dominio, esta interfaz implemento en los dos lados.

    y porque no usas algun conversor ? o sea podrias mapear un dto a un objeto de dominio cuando este ingresa o es devuelto de la cap a de servicio

    podrias usar

    http://automapper.org/

    para hacer esta conversion mas simple

    B) Para resolver la referencia seguridad  -> Servicos  estoy por haciendo lo siguiente: 1)  copiar la dll de servicos a seguridad en la prop del proyecto evento postbuild....

    es uan buena tecnica asi no tienes que mentener la referencia al proyecto y puedes continuar acediendo directo a la funcionalidad de la dll que tiene el servicio

    c)tanto hinche con seguridad le voy a agregar sus propios dtos y que exponga sus dtos como propiedades...

    tambien es una buena alternativa, que seguridad defina sus entidades no estaria mal, de ultima si alguien quiere usar seguridad referencia funcionalidad y entidades para poder invocarlo

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    • Marcado como respuesta sebastian viga jueves, 24 de enero de 2013 18:25
    jueves, 24 de enero de 2013 13:33
  • Estimados
    (que largo se hizo el post e interesante tema)

    Solo recuerdo la premisa: "Bajo acoplamiento, alta cohesion" y que en POO "Cada objeto tenga las responsabilidades adecuadas (algo que cuesta siempre)"

    Me uno a lo ultimo que comenta Leandro

    • LA tecnica de copiar el asembly post-build. Recomendada para este tipo de casos
    • Seguridad con sus propios DTO/Entidades.
      POr supuesto, o sino estaria muy acoplada
      O seria una seguridad para "un tipo especial de app"

    Existos


    Jose. A Fernandez | blog: http://geeks.ms/blogs/fernandezja

    • Marcado como respuesta sebastian viga jueves, 24 de enero de 2013 18:25
    jueves, 24 de enero de 2013 14:53

Todas las respuestas

  • 1-

    algo no entiendo si esta libreria de seguridad usa servicio y es suada desde la UI cual seria el proble de referencia circular, porque se supone que als entidades podrias ponerlas en un proyecto separado asi puede referencialro tanto de la ui como del servicio y la seguridad

    o sea

    UI -> Seguridad -> Servicio

    UI -> Servicio

    todo referencian al proyecto de entidades

    Nota: la -> indica la direccion de referencia

    2-

    esto como se podria manejar con List<T> deberia implementar un mecanismo para saber si se agrego o modifico.

    en principio con list eso no se puede hacer, lo que si harias si implementas uow es ir acumulando acciones en alguna session pero cada accion se lanza individualmente

    o sea si eliminas un articulo envias el comando de eliminar de forma unitaria solo que no lo ejecutas lo dejas pendiente en la ouw, si agregas un iem tambien lo envias, pero no lo ejecutas y asi con el resto, cuando este todo, eejcutas y pones en firme la ouw

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    martes, 22 de enero de 2013 0:15
  • gracias groso como siempre

    El tema es que seguridad (la clase UserContext  en seguridad) se usan en los tres proyectos UI, Servicios y Dominio . Es vertical ,

    UI ->Seguridad( aca porque despues del logueo busca en un metodo de servicios   y guarda en UserContext lo que devuelve los metodos de servicios UI->Servicios)

    Servicios ->Seguridad ()

    Dominio ->seguridad (aca poruqe hay auditoria de lo que hace el Usercontext en la aplicacion) 

    hasta aca todo bien:

    pero Seguridad->Servicos (tiene una propiedad que llama a un metodo del servico para obtener menues esto va a hacerse asi _xmlMenu =Servicio.GenerarMenu(this.Menu)  aca creo que con reflection puede func)

    y Seguridad ->Dominio (esto porque Usercontext tiene propiedades del dominio que quiero mantener

    para no romper la UI como list<Permisos> siendo Permisos objeto del dominio).

    Todavia no implemento DTO vertical o entidades por el tema de tiempo y de romper lo que esta.

    2) con respecto a este punto de donde podria leer para implementar algo asi, lo que se usa en esta aplicacion  en algunos casos es datatables con session no remondado y se agregar  y se modifica en el datatable, como podria hacer algo asi con asp net,supongo, no tengo idea ,se  tendria que hacer algo en el medio que controle lo que se modifica ,borra y agrego.

    Gracias genio

    martes, 22 de enero de 2013 1:26
  • el tema es que Seguridad no deberia hacer uso de funcionaliad de Servicio, porque es logico que causara referencia circular

    quizas seguridad deberia implementar su propia definicion de entidades y acceso a la informacion para no depender de servicio o dominio, al ser un componente independiente podria hacerlo

    como este componente lo referencias en todas las capas podrias usar directo la entidad que el mismo define

    en realidad hay tecnicas que podrias aplicar para separar la relacion con servicio, para esto usarias interfaces ademas de crear la instancia mediante reflection

    el tema es la relacion con dominio, ya que esta al definir una entidad tipada alli no puede aplciar la misma tecnica, por eso decia que seguridad podria definir su propio "dominio" de entidades, asi desde otros sitio lo usas directo lo que el mismo define

    de ultima si lo necesitas podrias convertir una entidad de Seguridad en otra de Dominio

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    martes, 22 de enero de 2013 7:02
  • gracias por contestar , perdon el delay, en el laburo tengo bloqueado .

     para resolver la ref de seguridad con el dominio , vos comentas que  podria ussar interfaces y ademas crear la instancia como reflection
    como podria hacer esto? en mi caso tengo desde seguridad una propiedad que llama a un metodo del servico _xmlMenu =Servicio.GenerarMenu(this.Menu) .                                                                                               

     Me gusto el tema de la  vinculacion de seguridad y dominio , pero voy a organizar para mas adelante, que tenga sus entidades propias y su propio acceso a datos independiente como comentas,  asi puedo reusar en varias apliacaciones .  

    despues  si lo necesitas podrias convertir una entidad de Seguridad en otra de Dominio. Esto lo podria hacer ahora crear unas clases de seguridad y hago un wrapper de clases de  seguridad a dominio qu puedo seguir usando desde ui  que   manipula clases del dominio. este item lo podria dejar para despues. espero haber entendido bien este item :)

    gracias





    martes, 22 de enero de 2013 22:58
  •   Estoy probando desde seguridad llamar  el metodo de servicos generarmenu :

       private short _menu;
            public short Menu
            {
                get { return _menu; }
                set { _menu = value; }
            }

     _xmlMenu = Servicio.GenerarMenu(t.Menu); menu es una propidad del tipo short

      la llamada a servicio con reflection asi

     Assembly objAssembly = Assembly.LoadFrom(@"C:\Users\Documents\Visual Studio 2010\Projects\WebApplicationTest\Servicios\bin\Debug");

                     
               Type classType = objAssembly.GetType("Servicios.GestorMenu");

                //create the instance of class using System.Activator class
                object  obj  =  Activator.CreateInstance(classType);

                //get the method information
                MethodInfo mi = classType.GetMethod("GenerarMenu");
                object[] parameters = new object[1];
                parameters[0] = menu;

                var result = mi.Invoke(obj, parameters)

    quiro probar a ver si puedo usar el fully qualified assembly name ,porque necesito permisos en la carpeta para acceder con el path absoluto.

    miércoles, 23 de enero de 2013 4:52
  • para resolver la ref de seguridad con el dominio , vos comentas que  podria ussar interfaces y ademas crear la instancia como reflection

    aqui explico algo sobre el tema

    Archivos de Configuración - Crear secciones propia (3/3)

    analiza el titulo "Implementación con interfaz Común", alli planteo este tema

    podrias configurar y desacoplar mediente intefaces

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    • Marcado como respuesta sebastian viga jueves, 24 de enero de 2013 18:25
    miércoles, 23 de enero de 2013 12:20
  • Hola Sebastián.

    Permíteme darte algunas ideas generales que puedes aplicar o no en tu proyecto:

    1) La capa de UI puede comunicarse perfectamente con la capa de lógica de negocios sin necesitar ninguna otra capa. Te recomiendo modelar tu capa de negocio como un conjunto de INTERFACES (que puedes tener en un proyecto de VS.Net) y un conjunto de clases que implementan interfaces. Pongamos un ejemplo: por un lado defines la interfaz ICliente y por otra parte la clase Cliente que implementa ICliente. La interfaz de usuario podría depender exclusivamente de las Interfaces.

    2) El patrón FACTORIA es muy útil para establecer la interacción entre la capa de Lógica o Modelo y la Capa de Persistencia o Datos. Lo que yo hago es definir una Interface que expone los métodos necesarios para crear objetos de la lógica de negocio. También conviene crear interfaces para los almacenamientos, por ejemplo: IAlmacenamientoCliente. 

    Tu modelo UML debería entonces parecerse a esto:




    logo osoft
    Si he contestado tu pregunta, por favor marca mi post como respuesta.
    ...Y si mi post te ha servido, márcalo como útil smile

    • Marcado como respuesta sebastian viga jueves, 24 de enero de 2013 18:25
    miércoles, 23 de enero de 2013 14:13
  • gracias por contestar leandro y gracias  Yván Ecarri  , tengo bloqueado el acceso a foro en el trabajo y eso me demora la contestacion asi que perdon.

     leandro voy a mirar el link tranquilo  Archivos de Configuración - Crear secciones propia (3/3)  recien lo abri y esta bueno voy a verlo tranquilo y  usa interfaces con reflection asi que voy a  analizar tranquilo.(siempre leo tu blog ese articulo se me escapo :))

    recien  veo esto del foro  y estoy contestando al tutun  ,tendria que sentarme a analizar bien pero aca voy:
    Yván Esta interesante usar interfaces e implementar en cada ambiente  , la de factoria esta bueno, se me ocurre, para hacer la conversion de un objeto en otro con su mapeo

    En  la capa seguridad (que se usa por todo el resto , por eso vertical)  ,
    esta capa tiene como propiedades una  public List<PermisosRol> Permisos {get;set;} y
    List<Rol> siendo rol y permisosrol  son objetos del dominio (y no puedo hacer la referencia del domino desde esta capa por ref circular)
    aca pienso hacer lo siguiente (corregirme de ser necesario :)) cambiar esas propiedades por dtos o entidades de seguridad y devolver al cliente entidades de dominio.

    como ? (esto tiro por tirar )con la idea de Yván Ecarri lo que podria hacer es crear una interfaz tanto para estos dtos que voy a crear como para las entidades de dominio (de seguridad por ahora) e implementar en estas entidades  del dominio e implementar en los dtos de seguridad tambien. entonces podria hacer un factory que devuelva por reflection
    un objeto de dominio  u dto y el mapeo de propiedades tambien que lo haga ahi (sigo suponiendo )  entonces la ui por ahora "temporalmente"podria seguir usando los objetos  del dominio, asi no rompe.
     
    lo que no me quedo claro , (tal vez deberia analizar mas )Yván Ecarri  como podria hacer para  exponer una interface con operaciones para crear  objetos de la lógica de negocio como comentas  y en el diagrama me perdi un poco con el almacen cliente y fabrica cliente que no se que capa seria  ( que supongo que es crear clientes dtos). -muchas gracias por la data. 

    Gracias genios . les debo un diagrama tambien;)







    miércoles, 23 de enero de 2013 23:12
  • leandro , estaba leyendo el link 

    Archivos de Configuración - Crear secciones propia (3/3)

    que me pasase esta muy bueno , hace una factoria y crea un medio de pago segun lo que seleccionas en el combo.: (perdon por lo largo de lo de abajo )

    A) leandro decime que te parece esto:  Como movi los metodos de ui a servicios (al estar todo en una capa), cree una capa de entidades o dtos para  servicios (que despues va a ser vertical para todas las capas).El tema que la ui por ahora me tiene que seguir devolviendo objetos del dominio para que no rompa . aca pienso hacer una interfaz entre los dtos  y los objeto de dominio, esta interfaz implemento en los dos lados.

    entonces servicios me podria  exponer una interfaz en cada metodo y no objetos ,asi devuelve objetos de dominio  y hacer una factoria ,entonces mas adelante poder ir devolviendo algunos objetos de dominio a objetos entidades o dtos  , cambiando de a poco

    la factoria   que puede ser otro proyecto, podria hacer asi  como el ejemplo con interfaz comun del link

    metodo Factoria (objeto domino)

    {

    //obtengo el nombre del objeto de dominio e instsancio su igual en dto

    Assembly _assembly = Assembly.LoadFrom(dtosservicios.dll);
    Type classType = _assembly .GetType("dtoservicios.Cliente");

     ICliente instance = (ICliente)_assembly.CreateInstance(classType);

    //uego laca el mapeo de propiedades de objeto domino con dtos para pasar los datos

    }

    B) Para resolver la referencia seguridad  -> Servicos  estoy por haciendo lo siguiente:
    1)  copiar la dll de servicos a seguridad en la prop del proyecto evento postbuild Copy /y "$(TargetPath)" "$(SolutionDir)Seguridad\bin\Debug\$(TargetFileName)" esto calculo uqe va a funcionar

    2) crear un interfaz (peudo hacer sin una creo) en otro proyecto library

    public interface generarmenu
    {
        XMLDocument GenerarMenu
    }

    3) implemnto la interfaz en servicios

    4)en seguridad hago lo siguiente:

              
                Assembly _assembly = Assembly.LoadFrom(Servicios.dll);
                 Type classType = _assembly .GetType("Servicios.GestorMenu");

                IGenerarMenu instance = (IGenerarMenu)_assembly.CreateInstance(classType);

                //
                // invoco al metodo
                //
                xmldocumnt result = instance.Generarmenu(menu);    

    c)tanto hinche con seguridad le voy a agregar sus propios dtos y que exponga sus dtos como propiedades y cambiar en la  capa de UI para que use dtos de seguridad y no objeto dominio (parecido al caso A)

    Gracias



    jueves, 24 de enero de 2013 12:07
  • El tema que la ui por ahora me tiene que seguir devolviendo objetos del dominio para que no rompa . aca pienso hacer una interfaz entre los dtos  y los objeto de dominio, esta interfaz implemento en los dos lados.

    y porque no usas algun conversor ? o sea podrias mapear un dto a un objeto de dominio cuando este ingresa o es devuelto de la cap a de servicio

    podrias usar

    http://automapper.org/

    para hacer esta conversion mas simple

    B) Para resolver la referencia seguridad  -> Servicos  estoy por haciendo lo siguiente: 1)  copiar la dll de servicos a seguridad en la prop del proyecto evento postbuild....

    es uan buena tecnica asi no tienes que mentener la referencia al proyecto y puedes continuar acediendo directo a la funcionalidad de la dll que tiene el servicio

    c)tanto hinche con seguridad le voy a agregar sus propios dtos y que exponga sus dtos como propiedades...

    tambien es una buena alternativa, que seguridad defina sus entidades no estaria mal, de ultima si alguien quiere usar seguridad referencia funcionalidad y entidades para poder invocarlo

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    • Marcado como respuesta sebastian viga jueves, 24 de enero de 2013 18:25
    jueves, 24 de enero de 2013 13:33
  • Estimados
    (que largo se hizo el post e interesante tema)

    Solo recuerdo la premisa: "Bajo acoplamiento, alta cohesion" y que en POO "Cada objeto tenga las responsabilidades adecuadas (algo que cuesta siempre)"

    Me uno a lo ultimo que comenta Leandro

    • LA tecnica de copiar el asembly post-build. Recomendada para este tipo de casos
    • Seguridad con sus propios DTO/Entidades.
      POr supuesto, o sino estaria muy acoplada
      O seria una seguridad para "un tipo especial de app"

    Existos


    Jose. A Fernandez | blog: http://geeks.ms/blogs/fernandezja

    • Marcado como respuesta sebastian viga jueves, 24 de enero de 2013 18:25
    jueves, 24 de enero de 2013 14:53
  • Gracias leandro y jose  , voy a seguir sus consejos.  estoy en la cons ahora asi que puedo entrar y contestar ya. :)

    agrupo por temática poniendo en negrita, como hizo leandro y jose. 
    El tema que la ui por ahora me tiene que seguir devolviendo objetos del dominio para que no rompa . aca pienso hacer una interfaz entre los dtos  y los objeto de dominio, esta interfaz implemento en los dos lados.

    muy  buena idea del automapper  , lo use en otro laburo pero no lo configure  ,encima  algunos tenemos métodos del servicio que van a recibir  datatables y devuelven datatables  asi que voy a  probar mappear datatables a  list objeto de dominio .  (datable es porque matiene el estado de las row y se agrega datos en memoria tipo uow). en otros casos list<dtos> .

    B) Para resolver la referencia seguridad  -> Servicos  estoy por haciendo lo siguiente: 1)  copiar la dll de servicos a seguridad en la prop del proyecto evento postbuild....
    ok , buenisimo  copiar el asembly post-build y usar reflection.
    c)tanto hinche con seguridad le voy a agregar sus propios dtos y que exponga sus dtos como propiedades...

    voy a tener mis entidades dto de seguridad , y por lo que comentas , al referirte a funcionalidad también mis servicios de acceso a datos a parte solo para seguridad.(esto para no usar reflection del punto B )

    Gracias grosos por ayudar


    jueves, 24 de enero de 2013 17:16