Introducción A partir de la versión 4.5 de .Net framework se ha simplificado de forma considerable la forma en que podemos trabajar con código asíncrono. Con los anteriores frameworks, si queríamos contar con los beneficios de una programación asíncrona nos veíamos obligados a lidiar con una gran complejidad en nuestro código. Esto nos hacía evitar su uso en lo posible a pesar de perder esta importante característica. Stephen Cleary , un MVP especializado en concurrencia define la programación asíncrona como: Una forma de concurrencia que utiliza futuros o "callbacks" para evitar hilos innecesarios. La programación moderna con async y await nos abstrae de la utilización de "callbacks" y nos permite utilizar futuros (Tasks) que se encargarán de notificar al llamante cuando el método asíncrono se complete. async y await Las palabras async y await son las palabras clave que .Net ha introducido en el lenguaje para que podamos implementar métodos asíncronos co...
Introducción
- Como mecanismo de restricción del acceso a componentes de un objeto;
- Como construcción del lenguaje para facilitar el “empaquetado” del estado y el comportamiento.
- ¿Para qué perder el tiempo? Hago todo público y así seguro que compila. Más adelante ya veré si me conviene cambiar el modificador.
- ¿Y si permito que se lea y escriba en todos mis campos? El código no se rompe y si más adelante necesito acceder ya lo tendré disponible.
- ¿Qué más da si este método se ve desde fuera o no? A nadie le molesta que haya un método más disponible. De todas formas no creo que sea de mucha utilidad a terceros y seguramente ni lo usen.
- Está bien, intentaré no abusar del modificador public. Pero… ¿Y si establezco el modificador de todos mis miembros como protegidos? De este modo encapsulo hacia el exterior pero si extiendo la clase no tendré problemas para acceder a los miembros de la base. Al fin y al cabo es su legítimo heredero.
Ventajas de encapsular
El encapsulamiento de objetos oculta su interior protegiendo su integridad. Previene que desde fuera se pueda manipular el estado del objeto. Si no se restringe el acceso podría dejar al objeto en un estado inválido o inconsistente.Otra ventaja del encapsulamiento es la reducción de la complejidad. Una clase debe tener una interfaz pública mínima para su manipulación. Si vamos a usar una clase en la que no se ha restringido de forma eficiente el acceso a sus miembros podemos encontrarnos con un exceso de funcionalidad irrelevante para nosotros, o peor aún, una puerta abierta a miembros que no debería acceder por riesgo a modificar el estado de la clase sin ningún criterio.
Controlando el alcance de nuestros cambios
Una ventaja muy importante subyacente de un buen encapsulamiento es que mejora notablemente nuestra visión del alcance del cambio.Cuando controlamos de forma eficientemente el encapsulamiento de nuestro código también estamos marcando los límites físicos a los que puede llegar ese código. De esta forma acotamos los “daños colaterales” de futuros cambios.
Por ejemplo, si hacemos un miembro público en una clase publica quiere decir que este miembro puede estar accesible para cualquiera dentro y fuera de nuestro ensamblado. Un cambio de nombre o eliminación de este miembro puede significar que se rompa el código de nuestro ensamblado, algo no muy grave ya que nos daríamos cuenta al compilar y podríamos corregirlo. Pero también podríamos estar rompiendo código de otros ensamblados que dependen del nuestro.
Esto representa un mayor problema porque a veces ni siquiera tenemos acceso a estos ensamblados. La forma correcta de proceder sería mantener esta propiedad “viva” aunque hayamos creado un código alternativo mejor que éste por el mero hecho de mantener la compatibilidad binaria. Podríamos marcar como obsoleto el miembro y esperar a una futura versión para romper esta compatibilidad binaria.
¿Y si este miembro no estuviera debidamente encapsulado?
Imaginemos que este miembro, en realidad, sólo lo hemos utilizado en la propia clase y en dos extensiones de la propia clase, y además la clase podría haber sido internal ya que no se debería utilizar fuera del contexto de nuestro ensamblado. Hubiera sido suficiente un modificador protected para dar visibilidad sólo a la propia clase y a sus extensiones. De esta forma, cuando se deba realizar algún cambio sobre este miembro sabemos con certeza que:- no va a romper nada fuera de nuestro ensamblado;
- podemos revisar fácilmente las dos clases que extienden de la nuestra para ver si afecta nuestro cambio de alguna manera.
La tranquilidad que da modificar o eliminar un miembro privado de una clase no tiene precio. Sabes que el cambio está afectando sólo a la clase que tienes delante.
Un programador que hace todo público nunca tendrá este tipo de control. El código es mucho menos mantenible y más propenso a errores.
¿Cómo deberíamos proceder?
La regla que yo sigo para encapsular una clase es: asignar la mínima visibilidad posible a los miembros de nuestras clases, tanto campos como métodos. Y si un miembro tiene que ser accesible, deberemos pensar en qué forma y en qué nivel de acceso lo hacemos. Si más adelante necesito ampliar la accesibilidad de un miembro o de un tipo aumentaré su visibilidad hasta el nivel mínimo que cumpla con mis necesidades de acceso.A nivel de clase procedo de la misma forma: siempre internal y, sólo cuando lo necesito, lo cambio a public.
En definitiva se trata de definir la “interfaz visible” de las clases y sus miembros para que sean accesibles desde otras clases que la usen o desde clases que la extiendan.
Estos son los modificadores utilizados en C# en orden de menor a mayor restricción:
Modificador | Accesible desde… | |
public | Sin restricción | |
protected internal | El propio ensamblado, la propia clase y sus extensiones | |
internal | El propio ensamblado y la propia clase | |
protected | La propia clase y sus extensiones | |
private | La propia clase |
>> Ir a Parte 2. Un ejemplo de encapsulamiento en la vida real.
Muy buen artículo
ResponderEliminar