Principios de diseño, ¿Los tenemos en cuenta?
En este articulo me pareció interesante repasar algunos principios de diseño desde la óptica de componentes, particularmente que son para mi punto de vista son "no negociables" en la ingenieria de software.
Hay cuatro principios básicos de diseño aplicables al diseño al nivel de componentes y se han adoptado ampliamente cuando se aplica ingenieria de software orientada a objetos. La idea es lograr diseños que sean más sensibles al cambio y reducir la propagación de efectos secundarios cuando ocurren cambios.
El objetivo del artículo es cubrir uno de los principios nombrados, "el principio abierto-cerrado (PAC)".
¿Qué dice este principio?
"El componente de un módulo debe estar abierto para la extensión, pero cerrado para modificación"
Para expresarlo de manera simple, el diseñador debe especificar el componente de manera que permita extenderlo (dentro del dominio funcional que atiende) sin necesidad de modificaciones internas al propio componente (al nivel de código o lógica).
Caso normal, tenemos declarada un clase "Validador" que realiza revisiones sobre el estado de un objeto "Documento", si nuestra implementación es del tipo "if then" para determinar el documento a operar y el validador no solo atiende documento, sino que se amplía a "documento gerencial", "documento de calidad", etc, se requerirá lógica de procesamiento interno adicional, una clara violación al PAC.
Ahora miremos la siguiente propuesta:
De esta forma tenemos un diseño que no viola el principio PAC y es sensible a la extensión.
¿Cómo lo podemos implementar?
Para este ejemplo realicé una implementación de un componente de WCF (en C#) donde el servicio de validación expone la interface "IDocumento" como contrato para ser consumida por un client.
Veamos el code:
La interface
[ServiceContract]
public
interface
IDocumento
{
[OperationContract]
bool ConfirmarEstado();
}
La clase
public
class
Documento:IDocumento
{
#region IDocumento Members
public
bool ConfirmarEstado()
{
return
true;
}
#endregion
}
Muy simples implementaciones del validador.
Configuración del host que brinda el servicio de validador:
<system.serviceModel>
<services>
<service
name="ServicioDeValidacion.Documento"
behaviorConfiguration="metadataBehavior">
<endpoint
address="ServicioValidador"
binding="basicHttpBinding"
contract=" ServicioDeValidacion.IDocumento"></endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"></endpoint>
<host>
<baseAddresses>
<add
baseAddress="http://localhost:8000/Validador/"/>
<add
baseAddress="net.tcp://localhost:8010/ Validador /"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior
name="metadataBehavior">
<serviceMetadata
httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
De esta forma tenemos nuestro servicio configurado para la utilización soportando un esquema extensible, sin violar el PAC y con una implementación básica de servicio.
En próximos artículos veremos los demás principios, y les dejo un interrogante importante ¿Hacemos ingenieria de software? ....
Espero les sea de utilidad…
Bibliografía: Ingenieria del Software – Un enfoque práctico - Pressman
Creo que el PAC es muy dificil de respetar en algunos casos, en cuanto a tu pregunta, creo que la mayoria de las empresas hacen "software", pero "ingenieria de software" son muy pocas, y más si hablamos de Argentina.
ResponderBorrarMuy buen articulo como siempre...
EL PAC es un principio similar al que se aplica a las extensiones de los casos de uso cuando se modela un sistema para un dominio particular, si no me equivoco.
ResponderBorrarEs decir, cuando cerramos un CU base en sistemas ya avanzados (alta iteracion durante la elaboracion x ej.), para evitar tener que cambiar su contenido en futuras modificaciones, se extiende.
En definitiva si seguimos un modelado basado en CU, esta filosofía se terminaría trasladando por todo el PU hasta la etapa final de construcción (se terminaría aplicando a los componentes).
Es posible? y es buena la analogia?