De esto se trata esta entrada.
Una de las razones por las que podemos utilizar interfaces además de su uso común es para hacer lo que llaman "Future proof" de nuestro código, podemos entender por "Future Proof" escribir código el cual resista a cambios sin tener que realizar demasiadas modificaciones al código existente, esto claro es más sencillo entenderlo con un ejemplo.
Para este ejemplo creé una solución usando Visual Studio 2012, y el primer proyecto es una aplicación tipo "Windows Forms", ustedes puede usar una aplicación WPF si desean, la idea es tener un proyecto que solo se encargue de la interfaz de usuario.
El proyecto es sencillo y solo cuenta con un boton y un ListBox.
El siguiente paso para nuestro ejemplo es crear un nuevo proyecto de tipo "Class Library" , despúes de añadirlo vamos a crear dos Clases, una llamada RepositoryBook y la otra llamada Book.
Aqui lo que vamos a tener es lo siguiente:
RepositoryBook, va a ser nuestra base de datos, solo vamos a crear por el momento un método que devuelva una lista de libros, ya entendieron entonces para que nos va a servir la otra clase que creamos llamada Book, miremos el código en esta clase:
public class Book{
public string bookName { get; set; }
public int totalPages { get; set; }
public string publisher { get; set; }
}// end of class book
Es una clase bastante sencilla, ahora veamos el código de la clase RepositoryBook.
public Book[] getBooks()
{ return new Book[]{
new Book{bookName="Amor en los tiempos del colera"}, new Book{bookName="De que manera te olvido"}, new Book{bookName="El país de las mujeres"}, new Book{bookName="El amor es eterno mientras dura"} }; }// end of getBooks
Podemos observar que esta clase tiene un método que devuelve un arreglo de objetos Book, y adentro de esto inicializamos los objetos y los devolvemos, con este método estamos simulando un Retrieve del conocido CRUD (Create,Retrieve,Update,Delete) que son operaciones básicas que se realizan a una base de datos, esto tambien es llamado mantenimientos.
Estas dos clases serían nuetra lógica de negocios, tratando de seguir un patron de separación de conceptos, en los cuales nuestra interfaz no tendría que saber cómo esta implementado todo esto. Ahora vamos a analizar el código en el boton de nuestra aplicación.
foreach (Book book in books)
{
lbData.Items.Add(book.bookName);
}
Aqui instanciamos una objeto de tipo repositoryBook en el cuerpo del Form, propiamente en el evento Click del botón creamos un arreglo de libro Book[] books y le asignamos el valor que nos devuelve el método getBooks, despúes usando un foreach recorrermos el arreglo e imprimimos la propiedad bookName.
Que quiero decir que las interfaces sirven para el concepto de "Future proof", en un ambiente laboral comúnmente nos asignan a trabajar en una parte específica de una aplicación, rara vez nos da una aplicación para que nosotros la desarrollemos de principio a fin, esto solía darse mucho antes cuando el tipo de metodología de desarrollo era cascada pero ahora con la adopción de prácticas como XP (Extreme programming) equipos se encargan de la intefaz de usuario, otro equipo de la lógica de negocios y otros equipos de probar la aplicación.
Si analizamos nuestro método getBooks solo nos devuelve un grupo de libros el cual se recorre y se imprime, que pasaría si el equipo que desarrolla la lógica de negocios decide que ya no se va a devolver más un arreglo de libros y cambian el código para que devuelve una lista de libros.
Ahora el método de nuestro repositoryBook sería el siguiente.
Si miramos la interfaz de usuario despúes de este cambio vamos a notar que algo no anda bien.
Visual Studio nos indica que hay un error debido a que estamos asignando una lista de objetos tipo Book a un arreglo de objetos tipo Book y esto no es posible, Implicitamente no se puede dar esta conversión.
Ahora, donde entra aqui el "Future Proof", nosotros podríamos desarrollar código el cúal no le importe la implementación de este método siempre y cuando cumpla con algún tipo de contrato, sí, contrato, lo que se supone que es una interfaz, un contrato.
En este caso específico no vamos a crear una interfaz, pero nos vamos a valer de las interfaces; al fin de cuentas para mostrar los resultados en nuestro control ListBox estamos recorriendo el arreglo de libros y agregando cada uno de los elementos a los items de la lista, aqui lo importante es entender que nuestra interfaz no le interesa saber como es la estructura de los datos que ocupa recorrer, solo que lo ocupa recorrer, no le interesa saber si es una lista genérica, si es un diccionario genérico si es una ArrayList solo le interesa recorrerlo.
Entonces necesitamos algo que podamos recorrer con un foreach y que lo que sea que este ahi tiene una series de objetos tipo Book los cuales se van a mostrar en la lista, para esto entonces vamos a decir lo siguiente.
Ahora el código compila y todo sirve como antes, volvamos a cambiar la actual lista de objetos tipo Book por el primer arreglo y veamos que pasa.
Nuestro programa no nos informa de ningún tipo de error, nuestra capa de interfaz no sabe la estructura que tiene nuestros datos, lo único que sabe es que puede recorrerla mediante un foreach y accesar a las propiedades del objeto tipo Book, asi sea un arreglo, una lista generica, un arrayList.
Podemos ver como fácilmente podemos cambiar la estructura de nuestros datos y la interfaz no sufre ningún problema, aqui estamos programando contra un tipo abstracto, IEnumerable, esto nos da la sensación de trabajar como un tipo de pluggins, podemos agregar otro método que nos devuelva datos y los procese como sea, solo se necesita que implemente la interfaz Ienumerable y podemos cambiar de un método a otro sin afectar nuestra interfaz.
Espero que les guste la entrada, este es un tema extenso y estaré escribiendo otra entrada sobre la idea
"Programar contra una abstracción y no un tipo concreto", "Program to an abstraction rather than a concrete type"
Estas dos clases serían nuetra lógica de negocios, tratando de seguir un patron de separación de conceptos, en los cuales nuestra interfaz no tendría que saber cómo esta implementado todo esto. Ahora vamos a analizar el código en el boton de nuestra aplicación.
public partial class Form1 : Form
{ //instancia a nuestro hard coded repository repositoryBook repository = new repositoryBook(); public Form1()
{ InitializeComponent(); } private void btnGetBooks_Click(object sender, EventArgs e)
{ /***Ejemplo usando una clase concreta***/ Book[] books;books = repository.getBooks();foreach (Book book in books)
{
lbData.Items.Add(book.bookName);
}
} }Aqui instanciamos una objeto de tipo repositoryBook en el cuerpo del Form, propiamente en el evento Click del botón creamos un arreglo de libro Book[] books y le asignamos el valor que nos devuelve el método getBooks, despúes usando un foreach recorrermos el arreglo e imprimimos la propiedad bookName.
Que quiero decir que las interfaces sirven para el concepto de "Future proof", en un ambiente laboral comúnmente nos asignan a trabajar en una parte específica de una aplicación, rara vez nos da una aplicación para que nosotros la desarrollemos de principio a fin, esto solía darse mucho antes cuando el tipo de metodología de desarrollo era cascada pero ahora con la adopción de prácticas como XP (Extreme programming) equipos se encargan de la intefaz de usuario, otro equipo de la lógica de negocios y otros equipos de probar la aplicación.
Si analizamos nuestro método getBooks solo nos devuelve un grupo de libros el cual se recorre y se imprime, que pasaría si el equipo que desarrolla la lógica de negocios decide que ya no se va a devolver más un arreglo de libros y cambian el código para que devuelve una lista de libros.
Ahora el método de nuestro repositoryBook sería el siguiente.
public List<Book> getBooks()
{ return new List{ new Book{bookName="Amor en los tiempos del colera"}, new Book{bookName="De que manera te olvido"}, new Book{bookName="El país de las mujeres"}, new Book{bookName="El amor es eterno mientras dura"} }; }// end of getBooks
Simplemente cambiamos el tipo de retorno del método pero seguimos retornando objetos tipo Book.Si miramos la interfaz de usuario despúes de este cambio vamos a notar que algo no anda bien.
Visual Studio nos indica que hay un error debido a que estamos asignando una lista de objetos tipo Book a un arreglo de objetos tipo Book y esto no es posible, Implicitamente no se puede dar esta conversión.
Ahora, donde entra aqui el "Future Proof", nosotros podríamos desarrollar código el cúal no le importe la implementación de este método siempre y cuando cumpla con algún tipo de contrato, sí, contrato, lo que se supone que es una interfaz, un contrato.
En este caso específico no vamos a crear una interfaz, pero nos vamos a valer de las interfaces; al fin de cuentas para mostrar los resultados en nuestro control ListBox estamos recorriendo el arreglo de libros y agregando cada uno de los elementos a los items de la lista, aqui lo importante es entender que nuestra interfaz no le interesa saber como es la estructura de los datos que ocupa recorrer, solo que lo ocupa recorrer, no le interesa saber si es una lista genérica, si es un diccionario genérico si es una ArrayList solo le interesa recorrerlo.
Entonces necesitamos algo que podamos recorrer con un foreach y que lo que sea que este ahi tiene una series de objetos tipo Book los cuales se van a mostrar en la lista, para esto entonces vamos a decir lo siguiente.
IEnumerable books = repository.getBooks(); foreach (Book item in books) { lbData.Items.Add(item.bookName); }Ahora el código compila y todo sirve como antes, volvamos a cambiar la actual lista de objetos tipo Book por el primer arreglo y veamos que pasa.
Nuestro programa no nos informa de ningún tipo de error, nuestra capa de interfaz no sabe la estructura que tiene nuestros datos, lo único que sabe es que puede recorrerla mediante un foreach y accesar a las propiedades del objeto tipo Book, asi sea un arreglo, una lista generica, un arrayList.
Podemos ver como fácilmente podemos cambiar la estructura de nuestros datos y la interfaz no sufre ningún problema, aqui estamos programando contra un tipo abstracto, IEnumerable, esto nos da la sensación de trabajar como un tipo de pluggins, podemos agregar otro método que nos devuelva datos y los procese como sea, solo se necesita que implemente la interfaz Ienumerable y podemos cambiar de un método a otro sin afectar nuestra interfaz.
Espero que les guste la entrada, este es un tema extenso y estaré escribiendo otra entrada sobre la idea
"Programar contra una abstracción y no un tipo concreto", "Program to an abstraction rather than a concrete type"

