none
Inversion de Dependencias IoC RRS feed

  • Pregunta

  • Hola 

    Estoy trabajando con Visual Studio 2013, app Window Form, DDD y NHibernate.

    Tengo una clase CrudRepository

    using NHibernate;
    using NHibernate.Linq;
    using SoftVill.RepositorioContratos;
    
    namespace SoftVill.Repositorios
    {
        public class CrudRepository<T> : ICrud<T> where T : Entity
        {
            public void Guardar(T entidad)
            {
                using (ISession session = FluentSesionFactory.AbrirSession())
                {
                    session.Save(entidad);
                }
            }
    
            public void Actualizar(T entidad)
            {
                using (ISession session = FluentSesionFactory.AbrirSession())
                {
                    session.Update(entidad);
                }
            }
    
            public void Eliminar(T entidad)
            {
                using (ISession session = FluentSesionFactory.AbrirSession())
                {
                    session.Delete(entidad);
                }
            }
    
            public T Buscar(int id)
            {
                using (ISession session = FluentSesionFactory.AbrirSession())
                {
                    return session.Get<T>(id);
                }
            }
    
            public List<T> GetEntidad()
            {
                using (ISession session = FluentSesionFactory.AbrirSession())
                {
                    return (from e in session.Query<T>() select e).ToList();
                }
            }
    
            public bool Existe(string id)
            {
                using (ISession session = FluentSesionFactory.AbrirSession())
                {
                    bool existe = session.Query<T>().Any(c => c.Id == id);
                    return existe;
                }
            } 
        }
    }

    La cual la implemento de ICrud

    namespace SoftVill.RepositorioContratos
    {
         public class Entity
        {
            public virtual string Id { get; set; } 
        }
        public interface ICrud<T> where T:Entity
        {
            void Guardar(T entidad);
            void Actualizar(T entidad);
            void Eliminar(T entidad);
            T Buscar(int id);
            List<T> GetEntidad();
            //bool Existe(string id);
            
        }
    }

    Siguiendo los principios SOLID que un método o clase solo pueden tener una sola responsabilidad, en mi clase CrudRepository los métodos tienes 2 responsabilidades abir la conexión y la acción de Insert, Update, Delete, etc.

    Se puede hacer IoC manualmente pero como aplico IoC para manejar el tema de la conexión. Si una interface implemeta un método, entonces donde tengo mi clase FluentSesionFactory la debo convertir en una interface

    using FluentNHibernate.Cfg;
    using FluentNHibernate.Cfg.Db;
    using NHibernate;
    
    namespace SoftVill.Repositorios
    {
        public class FluentSesionFactory
        {
            private static string ConnectionString = "Server=127.0.0.1;Port=5432;User Id=postgres;Password=123;Database=prueba;";
            private static ISessionFactory session;
    
            public static ISessionFactory CrearSession()
            {
                if (session != null)
                    return session;
    
                IPersistenceConfigurer configDB = PostgreSQLConfiguration.PostgreSQL82.ConnectionString(ConnectionString);
                var configMap =
                    Fluently.Configure().Database(configDB).Mappings(
                        c => c.FluentMappings.AddFromAssemblyOf<Mapping.UsuarioMap>());
    
                session = configMap.BuildSessionFactory();
    
                return session;
            }
    
            public static ISession AbrirSession()
            {
                return CrearSession().OpenSession();
            }
        }
    }
    Para enviarle parámetros a los métodos que tengo implementado en CrudRepository, como usar IoC. 


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú


    • Editado Pedro Ávila martes, 26 de agosto de 2014 12:46 xxxxxxxx
    martes, 26 de agosto de 2014 12:44

Respuestas

  • Hay algunas cosas que tienes que mejorar:

    1. Evitar configurar todos los mappings cada vez que crees una sesion. Los mappings debes configurarlos una vez en toda la aplicación, cuando la aplicación arranque. Debes hacer esto por que configurar los mappings es costoso. Al igual que crear la factoría de sesiones.
    2. El método CrearSession debería llamarse CrearFactoriaDeSesiones porque no devuelve una sesión, devuelve una factoría de sesiones. Aunque yo prefiero todo el código en inglés, no me gusta ver en el código mezclados dos idiomas. Así que yo llamaría al método CreateSessionFactory
    3. La factoría de sesiones debería ser un objeto singleton. Solo debería haber una instancia en toda la aplicación. La factoría de sesiones es segura para subprocesos, pudiendo crear sesiones desde distintos subprocesos al mismo tiempo.

    Suponiendo que ahora el método CrearSession se llama CreateSessionFactory, que el repositorio tiene un constructor con el ISession como parámetro, y que tenemos un repositorio para orders como este:

    public interface IOrderRespository: ICrud<Order>
    {
       // metodos especifícos para pedidos
       void DoSomethingUsefull();
    void DoAnotherThing(); } public class OrderRepository : CrudRepository<Order>, IOrderRepostory { public OrderRepository(ISession session): base(session) { } // implementación de los métodos específicos de IOrderRepository    public void DoSomethingUsefull() {}
       public void DoAnotherThing() {} }

    En una aplicación Windows Forms y usando la librería LightInject que es la que más me gusta para inyección de dependencias. Este sería el contenido de Program.cs:

    using LightInject;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        static class Program
        {
    
            public static readonly ServiceContainer ServiceContainer = new ServiceContainer();
    
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                try
                {
                    RegisterServices();
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    var form = ServiceContainer.GetInstance<Form1>();
                    Application.Run(form);
                }
                finally
                {
                    ServiceContainer.Dispose();
                }
            }
    
            static void RegisterServices()
            {
                // registramos la factoría de sesiones como objeto singleton, sólo habrá una factoría de sesiones en toda la aplicación.
                ServiceContainer.Register<ISessionFactory>(x => FluentSesionFactory.CreateSessionFactory(), new PerContainerLifetime());
    
                // registramos el servicio de ISession con ciclo de vida por alcance (scope)
                // ya que necesitamos que se llame a Dispose() para cerrar la conexión
                // de forma determinista.
                ServiceContainer.Register<ISession>(factory => factory.GetInstance<ISessionFactory>().OpenSession(), new PerScopeLifetime());
    
                // registramos el servicio de IRepository asociado a la clase concreta Repository
                ServiceContainer.Register<IOrderRepository, OrderRepository>();
    
    
                // registramos el servicio necesaro para crear alcances (scopes)
                ServiceContainer.Register<IDisposable>(factory => factory.BeginScope());
    
                // registramos el servicio del formulario
                ServiceContainer.Register<Form1>();
            }
        }
    }

    Observa que para crear el fomulario uso esto: var form = ServiceContainer.GetInstance<Form1>(); El contenedor me resuelve todas las dependencias del formulario. y ¿Qué dependencias tiene el formulario? pues el fomulario tiene que poder ser capaz de crear alcances (scopes) y objetos repositorio de pedidos, así  el fomulario, a parte del constructor predeterminado, tiene el siguiente constructor, que tiene una factoría de repositorios y una factoría de alcances como parámetros:

    private readonly Func<IOrderRepository> repositoryFactory;
    private readonly Func<IDisposable> scopeFactory;
    
    public Form1(Func<IOrderRepository> repositoryFactory, Func<IDisposable> scopeFactory): this()
    {
        this.repositoryFactory = repositoryFactory;
        this.scopeFactory = scopeFactory;
    }

    LightInject va a llamar a este constructor cuando llame a ServiceContainer.GetInstance<Form1>();

    Luego para utilizar el repositorio y controlar la vida de la sesión en el formulario podemos hacer algo como lo siguiente:

    private void button1_Click(object sender, EventArgs e)
    {
        using (var scope = scopeFactory())
        {
            var orderRepository = repositoryFactory();
            // utilizar el repositorio
            orderRepository.DoSomethingUsefull();
            orderRepository.DoAnotherThing();
        }
    }

    Probablemente, en una aplicación real, no uses directamente los repositorios sino los servicios de dominio, que dependerán a su vez de los repositorios y de otras cosas.

    Hay que evitar, en la medida de lo posible, llamar directamente al ServiceContainer para no caer el service locator antipattern. En este ejemplo sólo se llama para configurar el contenedor y crear el primer formulario. Luego en el resto de la aplicación no haría falta casi nunca. Si un formulario f1 tiene que crear otro formulario f2, podemos crear un constructor de f1 al que se le pasa una factoría de formularios f2. Así casi todo nuestro código es independiente del contenedor que estemos usando.

    A lo mejor parece que siempre tenemos constuctores con factorías, pero eso no es así, tenemos constructores con factorías cuando el objeto tiene que crear otros objetos, si simplemente tiene que usar un objeto el parametro del constructor no es una factoría sino un interfaz, es por ejemplo el caso del repositorio, al contructor del repositorio no se le pasa una factoría, se le pasa un ISession.


    EntityLite: A Lightweight, Database First, Micro ORM




    miércoles, 27 de agosto de 2014 9:58
  • Por cierto, al no definir un interfaz IUsuarioRepository lo estás estropeando todo. Ya cuando un objeto tenga una dependencia del repositorio del usuario tendrá que ser sobre la clase concreta UsuarioRepository. Y ya, la única razón válida (que expuso Leandro) por la que crear esos repositorios que era la de poder mockear para hacer test unitarios, se ha ido al garete. Ya no tiene ningún sentido todo el tema de repositorios que estás haciendo, sólo añade abstracción innecesaria y complejidad.

    ¡Las abstracciones tienen que tener sentido y proporcionar un valor! no abstraer por abstraer para tener una arquitectura güay.

    Ayende (el creador de RavenDB) tiene una interesante serie de blog posts acerca del tema:

    Limit your abstractions: Analyzing a DDD application

    Limit your abstractions: Application Events–the wrong way

    Limit your abstractions: Application Events–what about change?

    Limit your abstractions: Application Events–Proposed Solution #1

    Limiting your abstractions: Reflections on the Interface Segregation Principle

    Limit your abstractions: Application Events–Proposed Solution #2–Cohesion

    Limit your abstractions: Application Events–event processing and RX

    Limit your abstractions: You only get six to a dozen in the entire appLimit your abstractions: Commands vs. Tasks, did you forget the workflow?

    Limit your abstractions: All cookies looks the same to the cookie cutter

    Limit your abstractions: So what is the whole big deal about?

    Limit your abstractions: Refactoring toward reduced abstractions

    Limit your abstractions: The key is in the infrastructure…

    Limit your abstractions: And how do you handle testing?


    EntityLite: A Lightweight, Database First, Micro ORM


    jueves, 28 de agosto de 2014 11:44
  • >> Ahora sale el error en el dominio en la clase Usuario <<

    UsuarioRepository _usuario = new UsuarioRepository(); ==> donde esta sombreado

    ¡Pues claro que te sale un error! UsuarioRepository necesita una sessión, no puedes crearlo sin pasarle la sesión en el constructor. UsuarioRepository no tiene un constructor sin parámetros. Así es como debe ser.

    Además, la clase Usuario es la entidad de dominio, y una entidad de dominio debe ser agnóstica de la persistencia, es decir la clase Usuario NO DEBE usar el repositorio.

    Por otra parte la clase Usuario ahora mismo está violando el principio de inversión de dependencia al crear el mismo el repositorio. Para no violarlo la clase Usuario debería tener un constructor con la sesión como parámetro.

    ¿De das cuenta de la cantidad de dificultades que estás encontrando? Y sólo estás empezado a entender y aplicar alguno de los principios básicos de la POO, los principios SOLID, con un problema trivial como es la gestión CRUD de una tabla de usuarios. ¿Qué pasará cuando te pongas a aplicar la metodología DDD en una aplicación del mundo real?


    EntityLite: A Lightweight, Database First, Micro ORM


    viernes, 29 de agosto de 2014 7:04

Todas las respuestas

  • Lo primero es que tu repositorio tenga un constructor con ISession como parámetro, en vez de que el repositorio cree la sesión. Ese es el principio. Luego ya viene lo de la inyección de dependencias que es precisamente el mecanismo por el que se creará el objeto repositorio pasándole como parámetro (inyectándole) un objeto ISession.

    Tu clase debería ser así:

    public class CrudRepository<T> : ICrud<T> where T : Entity
    {
       private readonly ISession session;
       
       public CrudRepository(ISession session)
       {
           this.session = session;
       }
    
    // resto de los métodos
    
    }
    


    EntityLite: A Lightweight, Database First, Micro ORM


    martes, 26 de agosto de 2014 13:01
  • Hay algunas cosas que tienes que mejorar:

    1. Evitar configurar todos los mappings cada vez que crees una sesion. Los mappings debes configurarlos una vez en toda la aplicación, cuando la aplicación arranque. Debes hacer esto por que configurar los mappings es costoso. Al igual que crear la factoría de sesiones.
    2. El método CrearSession debería llamarse CrearFactoriaDeSesiones porque no devuelve una sesión, devuelve una factoría de sesiones. Aunque yo prefiero todo el código en inglés, no me gusta ver en el código mezclados dos idiomas. Así que yo llamaría al método CreateSessionFactory
    3. La factoría de sesiones debería ser un objeto singleton. Solo debería haber una instancia en toda la aplicación. La factoría de sesiones es segura para subprocesos, pudiendo crear sesiones desde distintos subprocesos al mismo tiempo.

    Suponiendo que ahora el método CrearSession se llama CreateSessionFactory, que el repositorio tiene un constructor con el ISession como parámetro, y que tenemos un repositorio para orders como este:

    public interface IOrderRespository: ICrud<Order>
    {
       // metodos especifícos para pedidos
       void DoSomethingUsefull();
    void DoAnotherThing(); } public class OrderRepository : CrudRepository<Order>, IOrderRepostory { public OrderRepository(ISession session): base(session) { } // implementación de los métodos específicos de IOrderRepository    public void DoSomethingUsefull() {}
       public void DoAnotherThing() {} }

    En una aplicación Windows Forms y usando la librería LightInject que es la que más me gusta para inyección de dependencias. Este sería el contenido de Program.cs:

    using LightInject;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        static class Program
        {
    
            public static readonly ServiceContainer ServiceContainer = new ServiceContainer();
    
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                try
                {
                    RegisterServices();
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    var form = ServiceContainer.GetInstance<Form1>();
                    Application.Run(form);
                }
                finally
                {
                    ServiceContainer.Dispose();
                }
            }
    
            static void RegisterServices()
            {
                // registramos la factoría de sesiones como objeto singleton, sólo habrá una factoría de sesiones en toda la aplicación.
                ServiceContainer.Register<ISessionFactory>(x => FluentSesionFactory.CreateSessionFactory(), new PerContainerLifetime());
    
                // registramos el servicio de ISession con ciclo de vida por alcance (scope)
                // ya que necesitamos que se llame a Dispose() para cerrar la conexión
                // de forma determinista.
                ServiceContainer.Register<ISession>(factory => factory.GetInstance<ISessionFactory>().OpenSession(), new PerScopeLifetime());
    
                // registramos el servicio de IRepository asociado a la clase concreta Repository
                ServiceContainer.Register<IOrderRepository, OrderRepository>();
    
    
                // registramos el servicio necesaro para crear alcances (scopes)
                ServiceContainer.Register<IDisposable>(factory => factory.BeginScope());
    
                // registramos el servicio del formulario
                ServiceContainer.Register<Form1>();
            }
        }
    }

    Observa que para crear el fomulario uso esto: var form = ServiceContainer.GetInstance<Form1>(); El contenedor me resuelve todas las dependencias del formulario. y ¿Qué dependencias tiene el formulario? pues el fomulario tiene que poder ser capaz de crear alcances (scopes) y objetos repositorio de pedidos, así  el fomulario, a parte del constructor predeterminado, tiene el siguiente constructor, que tiene una factoría de repositorios y una factoría de alcances como parámetros:

    private readonly Func<IOrderRepository> repositoryFactory;
    private readonly Func<IDisposable> scopeFactory;
    
    public Form1(Func<IOrderRepository> repositoryFactory, Func<IDisposable> scopeFactory): this()
    {
        this.repositoryFactory = repositoryFactory;
        this.scopeFactory = scopeFactory;
    }

    LightInject va a llamar a este constructor cuando llame a ServiceContainer.GetInstance<Form1>();

    Luego para utilizar el repositorio y controlar la vida de la sesión en el formulario podemos hacer algo como lo siguiente:

    private void button1_Click(object sender, EventArgs e)
    {
        using (var scope = scopeFactory())
        {
            var orderRepository = repositoryFactory();
            // utilizar el repositorio
            orderRepository.DoSomethingUsefull();
            orderRepository.DoAnotherThing();
        }
    }

    Probablemente, en una aplicación real, no uses directamente los repositorios sino los servicios de dominio, que dependerán a su vez de los repositorios y de otras cosas.

    Hay que evitar, en la medida de lo posible, llamar directamente al ServiceContainer para no caer el service locator antipattern. En este ejemplo sólo se llama para configurar el contenedor y crear el primer formulario. Luego en el resto de la aplicación no haría falta casi nunca. Si un formulario f1 tiene que crear otro formulario f2, podemos crear un constructor de f1 al que se le pasa una factoría de formularios f2. Así casi todo nuestro código es independiente del contenedor que estemos usando.

    A lo mejor parece que siempre tenemos constuctores con factorías, pero eso no es así, tenemos constructores con factorías cuando el objeto tiene que crear otros objetos, si simplemente tiene que usar un objeto el parametro del constructor no es una factoría sino un interfaz, es por ejemplo el caso del repositorio, al contructor del repositorio no se le pasa una factoría, se le pasa un ISession.


    EntityLite: A Lightweight, Database First, Micro ORM




    miércoles, 27 de agosto de 2014 9:58
  • Implementando de esta manera como me indica Jesús 

    using NHibernate;
    using NHibernate.Linq;
    using SoftVill.RepositorioContratos;
    
    namespace SoftVill.Repositorios
    {
        public class CrudRepository<T> : ICrud<T> where T : Entity
        {
            private readonly ISession _session;
    
            public CrudRepository(ISession session)
            {
                _session = session;
            }
            public void Guardar(T entidad)
            {
                try
                {
                    //using (ISession session = FluentSesionFactory.AbrirSession())
                    //{
                        _session.Save(entidad);
                        _session.Flush();
                    //}
                }
                catch (Exception ex)
                {
                    throw new Exception("No se puede guardar el registro", ex);
                }     
            }

    Me sale el siguiente error :

    SoftVill.Repositorios.CrudRepository<SoftVill.DominioEntidades.UsuarioEntity>' no contiene un constructor que tome 0 argumentos.

    Mi Clase UsuarioEntity es la siguiente.

    using SoftVill.RepositorioContratos;
    
    namespace SoftVill.DominioEntidades
    {
        public class UsuarioEntity : Entity
        {
            public virtual string usuarioid { get; set; }
            //public virtual string Id { get; set; }
            public virtual string nombre { get; set; }
            public virtual string direccion { get; set; }
        }
    }


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 28 de agosto de 2014 0:39
  • @Pedro

    Necesitamos saber en qué línea te la excepción, y que pongas el resto del código. ¿Es un error de compilación? o ¿es una excepcion en tiempo de ejecución?

    Si es una excepción, pon por favor la pila de llamadas de la excepción. Necesitamos el contenido de ex.ToString()


    EntityLite: A Lightweight, Database First, Micro ORM

    jueves, 28 de agosto de 2014 6:36
  • @Jesús

    El error sale en tiempo de compilación, en esta línea.

    using NHibernate;
    using NHibernate.Linq;
    using SoftVill.DominioEntidades;

    namespace SoftVill.Repositorios
    {
        public class UsuarioRepository : CrudRepository<UsuarioEntity> ==> Donde esta sombreado
        {
            //private readonly ISession _session;

            //public UsuarioRepository(ISession session)
            //{
            //    _session = session;
            //}

            public string GenerarCodigo()
            {
                using (ISession session = FluentSesionFactory.AbrirSession())
                {
                    ISQLQuery query = 
                        session.CreateSQLQuery("SELECT lpad(CAST(COALESCE(CAST(MAX(usuarioid) AS integer), 0) + 1 as varchar(6)), 6, '0') FROM usuarios");
                    return query.UniqueResult<string>();
                }
            }


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 28 de agosto de 2014 11:12
  • Cambia private por protected en el CrudRepository para que las clases derivadas puedan acceder a la sesión:

    public class CrudRepository<T> : ICrud<T> where T : Entity
    {
       protected readonly ISession session;
       
       public CrudRepository(ISession session)
       {
           this.session = session;
       }
    
    // resto de los métodos
    
    }

    El constructor del repositorio de usuarios debería ser así:

    public UsuarioRepository(ISession session): base(session)
    {
    }

    el repositorio de usuarios no debería volver a declarar un campo ISession, ya lo tiene la clase base.

    -


    EntityLite: A Lightweight, Database First, Micro ORM



    jueves, 28 de agosto de 2014 11:22
  • @Jesús

    Ahora sale el error en el dominio en la clase Usuario

    using SoftVill.DominioEntidades;
    using SoftVill.RepositorioContratos;
    using SoftVill.Repositorios;
    using System.Transactions;
    
    namespace SoftVill.Dominio
    {
        public class Usuario
        {
            public string MensajeLogica;
            public string MensajeError;
    
            UsuarioRepository _usuario = new UsuarioRepository(); ==> donde esta sombreado
            
            public void Guardar(UsuarioEntity entidad)
            {
                BusinessException.Clear();
                if(string.IsNullOrEmpty(entidad.nombre)) BusinessException.Add("Debe ingresar el nombre");
                if(string.IsNullOrEmpty(entidad.direccion)) BusinessException.Add("Debe ingresar la dirección");
                
                if(BusinessException.Count() == 0)
                {
                    if (string.IsNullOrEmpty(entidad.Id))
                    {
                        entidad.Id = _usuario.GenerarCodigo();
                        entidad.usuarioid = entidad.Id;
                    }
                        
                    using(TransactionScope tran = new TransactionScope())
                    {
                        try
                        {
                            if (_usuario.Existe(entidad.Id))
                            {
                                _usuario.Actualizar(entidad);
                                MensajeLogica = "Registro acualizado con éxito";
                            }
                            else
                            {
                                _usuario.Guardar(entidad);
                                MensajeLogica = "Registro guardado con exito";
                            }
                            tran.Complete();
                        }
                        catch (Exception ex)
                        {
                            BusinessException.Add(ex.Message);
                        }
                    }
                    
                    if(MensajeError != string.Empty)
                        BusinessException.Add(MensajeError);
                }
            }
    
        }
    }
    SoftVill.Repositorios.UsuarioRepository' no contiene un constructor que tome 0 argumentos


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 28 de agosto de 2014 11:37
  • Por cierto, al no definir un interfaz IUsuarioRepository lo estás estropeando todo. Ya cuando un objeto tenga una dependencia del repositorio del usuario tendrá que ser sobre la clase concreta UsuarioRepository. Y ya, la única razón válida (que expuso Leandro) por la que crear esos repositorios que era la de poder mockear para hacer test unitarios, se ha ido al garete. Ya no tiene ningún sentido todo el tema de repositorios que estás haciendo, sólo añade abstracción innecesaria y complejidad.

    ¡Las abstracciones tienen que tener sentido y proporcionar un valor! no abstraer por abstraer para tener una arquitectura güay.

    Ayende (el creador de RavenDB) tiene una interesante serie de blog posts acerca del tema:

    Limit your abstractions: Analyzing a DDD application

    Limit your abstractions: Application Events–the wrong way

    Limit your abstractions: Application Events–what about change?

    Limit your abstractions: Application Events–Proposed Solution #1

    Limiting your abstractions: Reflections on the Interface Segregation Principle

    Limit your abstractions: Application Events–Proposed Solution #2–Cohesion

    Limit your abstractions: Application Events–event processing and RX

    Limit your abstractions: You only get six to a dozen in the entire appLimit your abstractions: Commands vs. Tasks, did you forget the workflow?

    Limit your abstractions: All cookies looks the same to the cookie cutter

    Limit your abstractions: So what is the whole big deal about?

    Limit your abstractions: Refactoring toward reduced abstractions

    Limit your abstractions: The key is in the infrastructure…

    Limit your abstractions: And how do you handle testing?


    EntityLite: A Lightweight, Database First, Micro ORM


    jueves, 28 de agosto de 2014 11:44
  • >> Ahora sale el error en el dominio en la clase Usuario <<

    UsuarioRepository _usuario = new UsuarioRepository(); ==> donde esta sombreado

    ¡Pues claro que te sale un error! UsuarioRepository necesita una sessión, no puedes crearlo sin pasarle la sesión en el constructor. UsuarioRepository no tiene un constructor sin parámetros. Así es como debe ser.

    Además, la clase Usuario es la entidad de dominio, y una entidad de dominio debe ser agnóstica de la persistencia, es decir la clase Usuario NO DEBE usar el repositorio.

    Por otra parte la clase Usuario ahora mismo está violando el principio de inversión de dependencia al crear el mismo el repositorio. Para no violarlo la clase Usuario debería tener un constructor con la sesión como parámetro.

    ¿De das cuenta de la cantidad de dificultades que estás encontrando? Y sólo estás empezado a entender y aplicar alguno de los principios básicos de la POO, los principios SOLID, con un problema trivial como es la gestión CRUD de una tabla de usuarios. ¿Qué pasará cuando te pongas a aplicar la metodología DDD en una aplicación del mundo real?


    EntityLite: A Lightweight, Database First, Micro ORM


    viernes, 29 de agosto de 2014 7:04