16. Principio de Responsabilidad Única
public class Factura
{
public string _codigo;
public DateTime _fechaEmision;
public decimal _importeFactura;
public decimal _importeIVA;
public decimal _importeDeducir;
public decimal _importeTotal;
public ushort _porcentageDeduccion;
//método que calcula el Total de la factura
public void CalcularTotal()
{
//Calculamos la deducción
_importeDeducir = (_importeFactura*_porcenDeduccion)
/100;
//Calculamos el IVA
_importeIVA = _importeFactura * 0.16m;
//calculamos el total
_importeTotal = (_importeFactura - _importeDeducir)
+ _importeIVA;
}
}
17. Principio de Responsabilidad Única
Una clase debe tener una y sólo una
única causa por la cual puede ser
modificada
Robert C. Martin
18. Principio de Responsabilidad Única
//clase IVA que calcula el iva en base a un importe
public class IVA {
public readonly decimal _iva = 0.16m;
public decimal CalcularIVA(decimal importe)
{
return importe*_iva;
}
}
//clase deduccion que calcula la deducción en base a un importe
public class Deduccion {
public readonly decimal _deduccion;
public Deduccion(ushort porcentage)
{
_deduccion = porcentage;
}
public decimal CalcularDeduccion(decimal importe)
{
return (importe*_deduccion)/100;
}
}
19. Principio de Responsabilidad Única
public class Factura
{
public string _codigo;
public DateTime _fechaEmision;
public decimal _importeFactura;
public decimal _importeIVA;
public decimal _importeDeducir;
public decimal _importeTotal;
public ushort _porcentageDeduccion;
public void CalcularTotal()
{
//calculamos el IVA
IVA iva = new IVA();
_importeIVA = iva.CalcularIVA(_importeFactura);
//calculamos la deducción a aplicar
Deduccion deduccion = new Deduccion(_porcentageDeduccion);
_importeDeducir = deduccion.CalcularDeduccion(_importeFactura);
//calculamos el total
_importeTotal = (_importeFactura - _importeDeducir) + _importeIVA;
}
}
20. Principio de Responsabilidad Única
interface Modem
{
void dial(int pNumber);
void hangup();
void send(char[] data);
char[] receive();
}
24. Principio Open/Closed
public void Finalizar()
{
switch (_estadoTarea)
{
case TareasEstadosEnum.Pendiente:
//finalizamos
break;
case TareasEstadosEnum.Finalizada:
throw new
ApplicationException
("Ya esta finalizada");
case TareasEstadosEnum.Cancelada:
throw new
ApplicationException
("Imposible finalizar. Tarea cancelada");
default:
throw new ArgumentOutOfRangeException();
}
}
25. Principio Open/Closed
public void Finalizar()
{
switch (_estadoTarea)
{
case TareasEstadosEnum.Pendiente:
//finalizamos
break;
case TareasEstadosEnum.Finalizada:
throw new ApplicationException("Ya esta finalizada");
case TareasEstadosEnum.Cancelada:
throw new ApplicationException("Imposible finalizar. Tarea cancelada");
case TareasEstadosEnum.Pospuesta:
throw new ApplicationException("Imposible finalizar. Tarea no completada");
default:
throw new ArgumentOutOfRangeException();
}
35. Principio de Substitución de Liskov
class Ciclomotor: Vehiculo
{
public string ObtenerNumLicencia()
{
//devuelve num licencia
}
}
class Coche: Vehiculo
{
public string ObtenerMatricula()
{
//devuelve matricula
}
}
class Impuestos
{
public void CalcularImpuesto(Vehiculo vehiculo)
{
string matricula = ((Coche) vehiculo).ObtenerMatricula();
ServicioCalculoImpuestos(matricula, vehiculo.Cilindrada);
}
}
36. Principio de Substitución de Liskov
Si por cada objeto o1 del tipo S
existe un objeto o2 del tipo T
tal que para todos los programas P
definidos en términos de T
y el comportamiento de P
permanece invariable
cuando o1 es sustituido por o2,
entonces S es un subtipo de T.
Barbara Liskov
37. Principio de Substitución de Liskov
public void CalcularImpuesto(Vehiculo vehiculo)
{
string matricula = string.Empty;
if (vehiculo.GetType().Name == "Coche")
matricula = ((Coche) vehiculo).ObtenerMatricula();
else if (vehiculo.GetType().Name == "Ciclomotor")
matricula = ((Ciclomotor)vehiculo).ObtenerNumLicencia();
ServicioCalculoImpuestos(matricula, vehiculo.Cilindrada);
}
38. Principio de Substitución de Liskov
public class Cuadrado : Rectangulo
{
public override int Ancho
{
get
{
return base.Ancho;
}
set
{
base.Ancho = value;
base.Alto = value;
}
}
public override int Alto
{
get
{
return base.Alto;
}
set
{
base.Ancho = value;
base.Alto = value;
}
}
}
public class Rectangulo
{
public virtual int Ancho { get; set; }
public virtual int Alto { get; set; }
}
39. Principio de Substitución de Liskov
[Test]
public void AreaRectangulo()
{
Rectangulo r =
new Cuadrado
{
Ancho = 5,
Alto = 2
};
// Fallará pues cuadrado establece
// a 2 el ancho y el alto
Assert.IsEqual(r.Ancho*r.Alto, 10); // false
}
41. Diseño por Contratos
[Test]
public void AreaRectangulo()
{
Rectangulo r = new Cuadrado {Ancho = 5, Alto = 2};
// Fallará pues cuadrado establece
// a 2 el ancho y el alto
Assert.IsEqual(r.Ancho*r.Alto, 10); // false
}
44. Principio Inyección Dependencias
public class EstacioMeteorologica
{
public void MostrarDatos()
{
Barometro barometro = new Barometro();
Termometro termometro = new Termometro();
int presion = barometro.Valor;
int temperatura = termometro.Valor;
Console.WriteLine(
string.Format("Datos a {0} nTemperatura: {1}nPresión:{2}",
DateTime.Now, temperatura, presion));
}
}
45. Principio Inyección Dependencias
•Las clases de alto nivel no deberían depender sobre
las clases de bajo nivel. Ambas deberían
depender de las abstracciones.
•Las abstracciones deberían no depender
de los detalles. Los detalles deberían depender
de las abstracciones.
Robert C. Martin
57. Principios OO
• Encapsular aquellas partes susceptibles de
variaciones
• Más composición, menos herencia
• Programa interfaces, no implementaciones
• Aboga por el bajo acoplamiento
• Ábrete a extensiones, ciérrate a modificaciones.
• Depende de abstracciones, no de clases concretas
• Sólo habla a “tus amigos”.
• “No nos llames; nosotros lo haremos”
• Una clase debe tener una única razón de cambio.
• Analiza el tamaño de los métodos. Los if/switch nos
hablan.