Manejo de Excepciones en aplicaciones de varias capas

Cuando desarrollamos aplicaciones, es habitual dividir la lógica de nuestra aplicación en varias capas. Normalmente un mínimo de 3 capas (las conocidas como three-tier applications) que separan: Capa de presentación, capa de lógica de negocio y capa de acceso a datos.

Un tema importante en este tipo de implementaciones es, que approach utilizar para el manejo de excepciones, para ello hoy he tenido la oportunidad de leer un artículo muy interesante en c-sharpcorner que quiero compartir con vosotros en el que hablan de cómo tratar el manejo de excepciones en aplicaciones de este tipo y dan una serie “reglas” que hay que tener en cuenta. Este es el artículo en cuestión:

http://www.c-sharpcorner.com/Blogs/46991/standard-way-of-exception-handling-in-3-tier-or-n-tier-appli.aspx

En el artículo destacan los siguientes aspectos a tener en cuenta a la hora de implementar el manejo de excepciones en este tipo de aplicaciones:

  1. Encapsular la excepción que se ha lanzado en una excepción personalizada
  2. Almacenar en un log los detalles de la excepción (o hacerlo en la base de datos)
  3. Si la excepción proviene de una capa anterior, trasladar las excepción hasta la capa superior sin grabar la excepción, ya que esto se ha hecho en la capa de origen
  4. Si estamos en la capa visual mostrar un mensaje amigable al usuario

Además en el artículo comparten una imagen que ayuda a aclarar la implementación de excepciones que también quiero compartir.

Exception

Lo que quiero hacer a continuación es mostraros con un ejemplo de código cómo podríamos hacer la implementación que nos sugieren en el artículo anterior, o al menos tal y como yo lo he entendido. El ejemplo está hecho para .NET, aunque se puede aplicar en cualquier lenguaje de programación.

Ejemplo de implementación del manejo de errores en aplicaciones de varias capas

Para el ejemplo en cuestión, se tratará de una aplicación en tres capas, por lo que contaremos con una clase que representaría a cada una de las capas: Acceso a datos, Lógica de Negocio y Presentación, y otras tantas clases personalizadas de excepciones.

Vamos a empezar definiendo las Clases de Error Personalizadas

public class DataAccessException: Exception
{
    public DataAccessException(){}
    public DataAccessException(string message) : base(message){}
    public DataAccessException(string message, Exception inner) : base(message, inner){}
}

public class BusinessLogicException: Exception
{
    public BusinessLogicException(){}
    public BusinessLogicException(string message) : base(message){}
    public BusinessLogicException(string message, Exception inner) : base(message, inner){}
}

Podríamos tener en cada capa más clases de excepciones personalizadas en función del tipo de error, forma de almacenamiento del mismo y posibles acciones a llevar a cabo en cada caso, al pasar de una capa a otra encapsularíamos estas excepciones en la genérica de cada capa.

Vamos a ver ahora como se implementarían las distintas clases de cada capa.

public class ExampleDataAccess : DataAccess
{
    public function List<Data> GetSomeData()
    {
        try
        {
            //Do DataAccess Work
        }
        catch(Exception ex)
        {
            LogError(ex);
            throw new DataAccessException("Some friendly Message", ex);
        }
    }
}

public class ExampleBusinessLogic : BusinessLogic
{
    public function bool DoSomeBusinessProcess()
    {
        try
        {
            //Do Business Work
        }
        catch(DataAccessException dae)
        {
            throw dae;
        }
        catch(Exception ex)
        {
            LogError(ex);
            throw new BusinessLogicException("Some Friendly Message", ex);
        }
    }
}

public class ExampleView : View
{
    public function void InitializeView()
    {
        try
        {
            //Do View Work
        }
        catch(DataAccessException dae)
        {
            ShowFinalFriendlyMessageToUser();
        }
        catch(BusinessLogicException ble)
        {
            ShowFinalFriendlyMessageToUser();
        }
        catch(Exception ex)
        {
            LogError(ex);
            ShowFinalFriendlyMessageToUser();
        }
    }
}

Y esto es todo, aquí tenéis el ejemplo, yo lo estaba empezando a usar en cierta medida en mis últimos desarrollos, pero con esto creo que mi manejo de errores quedará mucho más completo y me permitirá tener una mejor traza y seguimiento de los mismos.

Espero que vosotros lo podáis utilizar igualmente.

Un saludo

Anuncios