Anda di halaman 1dari 7

21/05/2014

Principios de Diseo SOLID


Clase 8

Lic. Ariel Trellini

Diseando soluciones larga vida

DCIC - UNS
Desarrollo de Aplicaciones Empresariales 190

Lic. Ariel Trellini DCIC UNS

Principios SOLID Bibliografa

Principios SOLID Introduccin

Bibliografa

Introduccin

Design Principles and Design Patterns


Robert C. Martin

Los Principios SOLID surgieron a comienzos del ao 2000 y su


autor-mentor es Robert C. Martin.

http://www.objectmentor.com/resources/articles/
Principles_and_Patterns.pdf

El trmino es un acrnimo que surge de los siguientes conceptos:


S Single Responsibility Principle Un objeto debera tener una nica responsabilidad.

Agile Software Development Principles, Patterns, and Practices


Robert C. Martin, Prentice Hall, 2002.
Slides presentadas por Jon Kruger, desarrollador de software
independiente de Columbus, Ohio, USA.

Desarrollo de Aplicaciones Empresariales 191

Lic. Ariel Trellini DCIC UNS

Principios SOLID Introduccin

O Open/Closed Principle

Las entidades de software deberan estar abiertas


para extensin pero cerradas para modificacin.

L Liskov Substitution Principle

Un objeto en un programa podra ser reemplazado


con instancias de sus subtipos sin alterar la
correctitud del programa.

Muchas interfaces especficas son mejores que


interfaces de propsitos generales.

Interface Segregation
Principle

D Dependency Inversion
Principle

Desarrollo de Aplicaciones Empresariales 192

Lic. Ariel Trellini DCIC UNS

Principios SOLID Introduccin

Introduccin (cont.)

Consideraciones

Se los considera los cinco principios bsicos en el diseo y la


programacin orientada a objetos.

Reglas Bsicas

La intencin es aplicar estos principios en conjunto para que sea


ms probable obtener un software fcil de mantener y extender
en el tiempo.

Los principios SOLID son guas, no son reglas inamovibles.


Us tu cerebro haciendo cosas que tengan sentido.
Preguntar por qu?

Desarrollo de Aplicaciones Empresariales 193

Deberamos depender de las abstracciones y no de


las concreciones.

Lic. Ariel Trellini DCIC UNS

Por qu hago lo que hago?


Por qu tom tal decisin?
Etc.

Desarrollo de Aplicaciones Empresariales 194

Lic. Ariel Trellini DCIC UNS

21/05/2014

Principios SOLID Single Responsability Principle

Principios SOLID Single Responsability Principle

Single Responsability Principle


Qu es una responsabilidad?

Nunca debera haber ms de una razn para que una clase


cambie.

Este principio se basa en el principio


de cohesin de Tom DeMarco.
Si una clase tiene ms de una
responsabilidad, entonces las
mismas quedan acopladas.
Los cambios en una responsabilidad
pueden afectar o inhibir la
capacidad de la clase para cumplir
con el resto.
Esta clase de acoplamiento conduce a diseos frgiles que se
rompen de maneras inesperadas cuando se producen cambios.
Desarrollo de Aplicaciones Empresariales 195

Lic. Ariel Trellini DCIC UNS

Principios SOLID Single Responsability Principle

Manejo de la conexin
Comunicacin de datos

Es necesario separarlas?

Sera mejor tener dos interfaces: DataChannel (send, recv) y Connection (dial,
hangup)
Sin embargo, como son funcionalidades que no se entremezclan y que
cambian por distintas razones, su implementacin podra seguir estando en
una nica clase.

Desarrollo de Aplicaciones Empresariales 196

+dibujar()
+area(): double

Debemos incluir una dependencia con la GUI en la aplicacin geomtrica.


Si un cambio en la aplicacin grfica causa que cambie la clase rectngulo,
podra forzarnos a re-compilar, re-testear y re-instalar la aplicacin geomtrica,
de manera tal de asegurar su correcto comportamiento.

Posible solucin: Separar las responsabilidades en clases distintas


Aplicacin
Geomtrica

Usa Rectngulo para ayudarla con las matemticas de las figuras geomtricas.
Nunca dibuja un rectngulo en la pantalla.

La otra es grfica en naturaleza. Tambin dibuja el rectngulo en la pantalla.

Este diseo viola a SRP porque Rectngulo tiene dos responsabilidades:

Aplicacin
Grfica

Una se encarga de la geometra computacional.

Lic. Ariel Trellini DCIC UNS

Problemas que podran ocurrir:

Aplicacin
Grfica

La clase Rectngulo es utilizada por dos aplicaciones diferentes:

La interfaz Modem parecera lucir


perfectamente razonable.
Existe ms de una responsabilidad

Ejemplo 1: Super-Rectngulo (cont.)

Rectngulo

GUI

Principios SOLID Single Responsability Principle

Ejemplo 1: Super-Rectngulo
Aplicacin
Geomtrica

En el contexto de SRP, definimos una responsabilidad a una


razn de cambio.

i) proveer un modelo matemtico para la geometra de un rectngulo


ii) dibujar el rectngulo en una interface grfica.

Desarrollo de Aplicaciones Empresariales 197

Lic. Ariel Trellini DCIC UNS

Rectngulo
Geomtrico
+area(): double

Rectngulo
+dibujar()
+area(): double

Desarrollo de Aplicaciones Empresariales 198

Principios SOLID Single Responsability Principle

Principios SOLID Single Responsability Principle

Ejemplo 2: Mltiples Funciones

Ejemplo 3: Violacin por Cdigo Spaghetti

La clase Persona maneja tanto los datos


filiatorios de la persona como la
informacin de su saldo de cuenta
Qu sucedera si ahora se permite que
una cuenta sea compartida por ms de
una persona?

GUI

Lic. Ariel Trellini DCIC UNS

public class OrderProcessingModule {


public void Process(OrderStatusMessage orderStatusMessage) {
// Get the connection string from configuration
string connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
Order order = null;
using (SqlConnection connection = new SqlConnection(connectionString)) {
// go get some data from the database
order = fetchData(orderStatusMessage, connection);
}
// Apply the changes to the Order from the OrderStatusMessage
updateTheOrder(order);

// International orders have a unique set of business rules


if (order.IsInternational)
processInternationalOrder(order);

Posible Solucin:

La clase Cuenta
no tiene nocin
sobre quin la
posee.
Persona puede o bien exponer la
propiedad Cuenta, o replicar la interfaz de
Cuenta, delegando la implementacin de
sus mtodos

Desarrollo de Aplicaciones Empresariales 199

// We need to treat larger orders in a special manner


else if (order.LineItems.Count > 10)
processLargeDomesticOrder(order);
// Smaller domestic orders
else
processRegularDomesticOrder(order);
// Ship the order if it's ready
if (order.IsReadyToShip()) {
ShippingGateway gateway = new ShippingGateway();
// Transform the Order object into a Shipment
ShipmentMessage message = createShipmentMessageForOrder(order);
gateway.SendShipment(message);

Lic. Ariel Trellini DCIC UNS

Desarrollo de Aplicaciones
Empresariales 200
}

Lic. Ariel Trellini DCIC UNS

21/05/2014

Principios SOLID Single Responsability Principle

Principios SOLID Single Responsability Principle

Tips para no violar SRP

Tips para no violar SRP (cont.)

Usar capas

Permite lograr una primera separacin de las responsabilidades de acuerdo al


alcance de cada capa.

Escribir los comentarios de cdigo para las clases antes de comenzar a


implementarlas.

public class SaveOrderService


{
public Order Save(Order order) { ... }
}
public class SubmitOrderService
{
public Order SubmitOrder(Order order) { ... }
}

Usar mtodos pequeos

Un mtodo debera tener un nico propsito (razn para cambiar)


Un mtodo debera ser fcil de leer y escribir.
Escribir los pasos de un mtodo usando verbos y sustantivos en los nombres de
los mtodos

Desarrollo de Aplicaciones Empresariales 201

Los servicios de domino deberan tener un verbo en el nombre de la clase.


public class GetOrderService
{
public Order Get(int orderId) { ... }
}

/// <summary>
/// Gets, saves, and submits orders.
/// </summary>
public class OrderService
{
public Order Get(int orderId) {...}
public Order Save(Order order) {...}
public Order SubmitOrder(Order order) {...}
}

Evitar servicios de dominio generalistas (que realizan muchas operaciones


sobre, quizs, una misma entidad)

Lic. Ariel Trellini DCIC UNS

Principios SOLID Single Responsability Principle

Desarrollo de Aplicaciones Empresariales 202

Lic. Ariel Trellini DCIC UNS

Principios SOLID Open Closed Principle

Open Closed Principle


Por qu es importante SRP?

Las mdulo de software debiera estar abierto para extensin


pero cerrado para modificacin

Porque buscamos que sea fcil reusar cdigo.


Cuanto ms grande es una clase, ms difcil es modificarla.
Cunto ms grande es una clase, ms dura es de leer y entender.

Clases y mtodos pequeos nos darn ms flexibilidad, sin


tener que escribir demasiado cdigo extra.

Debiramos escribir mdulos que


puedan ser extendidos sin
necesidad de ser modificados.
Los mdulos que cumplen OCP
tienen dos atributos primarios:

Estn Abiertos para Extensin: El


comportamiento del mdulo puede ser
extendido.
Estan Cerrados para Modificacin: El
cdigo fuente del mdulo es inviolable.

La clave es la ABSTRACCIN
Desarrollo de Aplicaciones Empresariales 203

Lic. Ariel Trellini DCIC UNS

Desarrollo de Aplicaciones Empresariales 204

Principios SOLID Open Closed Principle

Principios SOLID Open Closed Principle

Ejemplo 1: Abstracto

Ejemplo 2: Filtros de Consultas

No soporta OCP
Soporta OCP

Las clases Client y Server son


clases concretas.
Si por algn motivo la clase o
implementacin del Server es
modificada, entonces la clase
Client tambin debe ser
modificada.

Desarrollo de Aplicaciones Empresariales 205

Se agrega una clase intermedia,


Abstract Server, entre Client y Server.
Si, por algn motivo, la
implementacin del servidor
cambia, el cliente probablemente no
requiera cambios.
La clase Abstract Server es cerrada
para modificacin aunque si est
abierto para extensin.
Lic. Ariel Trellini DCIC UNS

Lic. Ariel Trellini DCIC UNS

public class GetUserService


{
public IList<UserSummary> FindUsers(UserSearchType type)
{
IList<User> users;
switch (type)
{
case UserSearchType.AllUsers:
// load the users variable here
break;
case UserSearchType.AllActiveUsers:
// load the users variable here
break;
case UserSearchType.ActiveUsersThatCanEditQuotes:
// load the users variable here
break;
}
return ConvertToUserSummaries(users);
}
}

Si se quisiera agregar un nuevo filtro, habra que modificar el enumerado y


agregar el caso a la sentencia switch.

Desarrollo de Aplicaciones Empresariales 206

Lic. Ariel Trellini DCIC UNS

21/05/2014

Principios SOLID Open Closed Principle

Principios SOLID Open Closed Principle

Ejemplo 2: Filtros de Consultas (cont.)

Ejemplo 2: OCP por Composicin

public interface IUserQuery


{
IQueryable<User> FilterUsers(IQueryable<User> allUsers);
}
public class GetUserService
{
public IList<UserSummary> FindUsers(IUserQuery query)
{
IQueryable<User> users = query.FilterUsers(GetAllUsers());
return ConvertToUserSummaries(users);
}
}

Permite agregar cualquier filtro sobre la bsqueda de usuarios, sin que la


consulta se entere.

Desarrollo de Aplicaciones Empresariales 207

Lic. Ariel Trellini DCIC UNS

public class AuthenticationService


{
private ILogger logger = new TextFileLogger();
public ILogger Logger { set{ logger = value; }}
public bool Authenticate(string userName, string password)
{
logger.Debug("Authentication '{0}'", userName);
// try to authenticate the user
}
}
public interface ILogger
{
void Debug(string message, params object[] args);
// other methods omitted for brevity
}

El servico slo depende de una abstraccin (ILogger), sin interesarle cul es


su verdadera implementacin. AuthenticationService est cerrado para
modificacin, pero abierto para extensin.

Desarrollo de Aplicaciones Empresariales 208

Principios SOLID Open Closed Principle

Principios SOLID Open Closed Principle

Ejemplo 2: OCP por Composicin con Expresiones Lambda

Ejemplo 3: OCP por Herencia

var model = new AutoPersistenceModel();


model.WithConvention(convention =>
{
convention.GetTableName = type => "tbl_" + type.Name;
convention.GetPrimaryKeyName = type => type.Name + "Id";
convention.GetVersionColumnName = type => "Version";
}
);

public class Line


{
public void Draw(ICanvas canvas) { /* draw a line on the canvas */ }
}
public class Painter
{
private IEnumerable<Line> lines;

public AutoPersistenceModel WithConvention(Action<Conventions>


conventionAction)

Ejemplo sacado del cdigo de Fluent Nhibernate.


Permite definir las convenciones de nombres tablas, claves primarias, etc.
Sin cambiar el cdigo de la clase AutoPersistenceModel , podemos cambiar
el comportamiento del auto-mapping.
Esta modificacin del comportamiento en ejecucin es posible puesto que
AutoPersistenceModel depende de abstracciones (en este caso expresiones
lambda), y no sobre implementaciones especficas.

Desarrollo de Aplicaciones Empresariales 209

Lic. Ariel Trellini DCIC UNS

Principios SOLID Open Closed Principle

Lic. Ariel Trellini DCIC UNS

public void DrawAll()


{
ICanvas canvas = GetCanvas();
foreach (var line in lines)
{
line.Draw(canvas);
}
}
}

Qu pasa si se quiere agregar un rectngulo?


Desarrollo de Aplicaciones Empresariales 210

Lic. Ariel Trellini DCIC UNS

Principios SOLID Liskov Substitution Principle

Liskov Substitution Principle


Por qu es importante OCP?

Subclases deberan poder ser sustituidas por sus clases base.

Porque la modificacin de cdigo existente y funcionando puede


introducir bugs.
A veces, necesitamos modificar libreras de terceros o nuestras, pero
no podemos/queremos generar una nueva versin de las mismas.

Diseos extensibles son menos propensos a errores ante


cambios de requerimientos.

Desarrollo de Aplicaciones Empresariales 211

Lic. Ariel Trellini DCIC UNS

Fue acuado por Barbara Liskov y


est relacionado al concepto
Diseo por Contratos de Bertrand
Meyer.
El contrato de una clase base debe
ser honrado por sus clases
derivadas.

Desarrollo de Aplicaciones Empresariales 212

Lic. Ariel Trellini DCIC UNS

21/05/2014

Principios SOLID Liskov Substitution Principle

Principios SOLID Liskov Substitution Principle

Ejemplo 1: Ejemplo Cannico

Ejemplo 1: Ejemplo Cannico (cont.)

La herencia generalmente se interpreta como una


relacin es un
Un Cuadrado es un Rectngulo
Sin embargo:

Qu problema encuentran
con la siguiente funcin
cuando se le pasa una
instancia de Cuadrado?

Cuadrado no necesita tener un Alto y un Ancho, slo


le alcanza con un Lado Desperdicion de memoria.
A un Cuadrado se le puede setear el Alto y el
Ancho Problema de consistencia !!!!

Solucin: Sobreescribir esas propiedades en la clase


Cuadrado

public override double Alto


{
get { return base.Alto; }
set
{
base.Alto = value;
base.Ancho = value;
}
}

Desarrollo de Aplicaciones Empresariales 213

Podra un desarrollador asumir que cuando se cambia el valor al Alto de


un rectngulo realmente no se cambia?
Se ha violado el contrato de Rectangulo Violacin de LSP !!!!
Cuidado: La validez de un modelo no es intrnseca

public override double Ancho


{
get { return base.Ancho; }
set
{
base.Ancho = value;
base.Alto = value;
}
}
Lic. Ariel Trellini DCIC UNS

Un modelo, visto de manera aislada, no puede ser validado significativamente.


La validez del modelo slo puede ser expresada en funcin de sus clientes.

Qu fall?

Un cuadrado puede ser un rectngulo, pero un objeto Cuadrado NO ES un


objeto Rectngulo, ya que el comportamiento del objeto Cuadrado no es
consistente con el comportamiento del objeto Rectngulo.

Desarrollo de Aplicaciones Empresariales 214

Principios SOLID Liskov Substitution Principle

Principios SOLID Liskov Substitution Principle

Diseo por Contrato

Ejemplo 2: Ejemplo ms Real

Lic. Ariel Trellini DCIC UNS

Definicin:

public void Calcular(Rectangle r)


{
r.Alto = 5;
r.Ancho = 4;
Debug.Assert(r.Alto * r.Ancho == 20);
}

Utilizando este concepto, los mtodos definiran pre-condiciones y postcondiciones.


cuando se redefine un mtodo [en una clase derivada], slo se pueden
reemplazar su pre-condicin por una ms dbil y su post-condicin por una
ms fuerte.

Si el lenguaje no permite definir las aserciones, mnimamente debieran


quedar documentadas en el cdigo.

Modelo

Cliente
void SaveAll(List<IPersistedResource> res)
{
res.ForEach(r => r.Persist());
}
List<IPersistedResource> LoadAll()
{
var all = new List<IPersistedResource>
{
new UserSettings(),
new ApplicationSettings()
};
all.ForEach(r => r.Load());
return all;
}

Desarrollo de Aplicaciones Empresariales 215

Lic. Ariel Trellini DCIC UNS

Desarrollo de Aplicaciones Empresariales 216

Principios SOLID Liskov Substitution Principle

Principios SOLID Liskov Substitution Principle

Ejemplo 2: Ejemplo ms Real (cont.)

Ejemplo 2: Ejemplo ms Real (cont.)

Qu pasa si quiero agregar la clase ReadOnlySettings al modelo?

Qu sucede con el mtodo SaveAll del cliente?

public class ReadOnlySettings : IPersistedResource


{
public void Load()
{
// stuf...
}
public void Persist()
{
throw new NotImplementedException();
}
}

Desarrollo de Aplicaciones Empresariales 217

EXPLOTA con una NotImplementedException !

Solucin:

Manejar el caso diferente en el cliente (mtodo SaveAll):


void SaveAll(List<IPersistedResource> res)
{
res.ForEach(r =>
{
if (r is ReadOnlySettings)
return;
r.Persist();
});
}

Debemos cambiar el cliente:


List<IPersistedResource> LoadAll()
{
var all = new List<IPersistedResource>
{
new UserSettings(),
new ApplicationSettings(),
new ReadOnlySettings ()
};
all.ForEach(r => r.Load());
return all;
}

Lic. Ariel Trellini DCIC UNS

Lic. Ariel Trellini DCIC UNS

No es una manera muy acertada de sobrellevar el problema.

Mejor Solucin:
Separar la interfaz IPersistedResource en IPersistResource e ILoadResource y
asignarle a cada cliente la interfaz ms apropiada.

Desarrollo de Aplicaciones Empresariales 218

Lic. Ariel Trellini DCIC UNS

21/05/2014

Principios SOLID Open Closed Principle

Principios SOLID Interface Segregation Principle

Interface Segregation Principle


Por qu es importante LSP?

Varias interfaces especficas a los clientes son mejores que una


interfaz de propsito general.

Es una importante caracterstica de todos los programas que cumplen


con OCP.
Permite definir herencias consistentes.

Desarrollo de Aplicaciones Empresariales 219

Lic. Ariel Trellini DCIC UNS

Ataca las desventajas de interfaces


gordas (no cohesivas /
contaminadas).
La interfaz gorda es dividida en
grupos de mtodos cohesivos. Cada
grupo sirve a un tipo de cliente
especfico.
Clientes no deben ser forzados a
depender de interfaces que no
usan.

Desarrollo de Aplicaciones Empresariales 220

Principios SOLID Interface Segregation Principle

Principios SOLID Interface Segregation Principle

Polucin de las interfaces

Polucin de las interfaces (cont.)

Escenario

Tenemos la abstraccin Door.


Queremos agregar una implementacin
especfica de TimedDoor
Cmo implemento la relacin entre
TimerClient y TimedDoor?

Solucin 1: Herencia (cont.)

No todas las variedades de puerta requieren


timing. La abstraccin Door no tiene nada que
ver con timings.
Todas las sub-clases de Door tendrn que
implementar el mtodo Timeout.
La interfaz Door ha sido contaminada por la
interfaz TimerClient porque una de sus subclases lo requiere.

Desarrollo de Aplicaciones Empresariales 221

Lic. Ariel Trellini DCIC UNS

Desarrollo de Aplicaciones Empresariales 222

Implementaciones de ISP

Separacin a travs de delegacin

Consideraciones

TimedDoor tiene dos interfaces utilizadas por dos tipos de cliente distintos:
Timer y los clientes de Door.
Los clientes de TimedDoor no necesitan acceder a las dos interfaces a la vez,
slo necesitan conocer una o la otra.
Esto nos llevara a separar las interfaces y que cada tipo de cliente consuma
la interfaz que necesita.

Desarrollo de Aplicaciones Empresariales 223

Lic. Ariel Trellini DCIC UNS

Diseo de Software Interface Segregation Principle

De qu manera se podra resolver el problema anterior?

Agrego un timeoutID a cada registracin para


saber de dnde se produjo un timeout.
Ha que modificar todas las implementaciones
de TimerClient incluso aquellas puertas que
no tiene nada que ver con timings.
Aun ms, se van a ver afectados tambin todos
los clientes de Door !!!!

Cuando un cambio en un componente afecta a otros


componentes que no estn relacionados, el costo de
repercusin de cambios se torna impredecible, y el riesgo de
romper algo se incrementa dramticamente.

Principios SOLID Interface Segregation Principle

Qu sucede si una puerta necesita


registrarse ms de una vez en el timer?

Solucin 1 : Herencia

Lic. Ariel Trellini DCIC UNS

Lic. Ariel Trellini DCIC UNS

Aplica el patrn Adapter de GoF


Evita el acoplamiento de Door y Timer.
Si ocurriera un cambio en TimerClient, ningn cliente de Door se vera afectado.
Ms aun, TimedDoor no tiene que tener la misma interfaz propuesta por
TimerClient, ya que el adapter podra transformarla.

Desarrollo de Aplicaciones Empresariales 224

Lic. Ariel Trellini DCIC UNS

21/05/2014

Diseo de Software Interface Segregation Principle

Implementaciones de ISP

Separacin a travs de Herencia Mltiple

Implementando herencia mltiple con interfaces


Desacopla las interfaces, aunque se siguen implementando ambas en el mismo
objeto.
Es ms elegante que la anterior (y ms utilizada)

Desarrollo de Aplicaciones Empresariales 225

Lic. Ariel Trellini DCIC UNS

Anda mungkin juga menyukai