Está en la página 1de 43
SOLID y GRASP Buenas practicas hacia el éxito en el desarrollo de software. Juan Garcia Carmona 4.jgc.it@gmail.com 15 de noviembre de 2012 Este documento contiene la practica totalidad de lo expuesto por el autor durante el simposio celebrado el dia 09 de Noviembre en la Escuela Técnica Superior de Ingenieria Informatica de la Universidad de Sevilla organizado por el grupo de investigacién de Ingenieria Web y Testing Temprano (IWT2). En él se analizan estos dos acrénimos, “SOLID” y “GRASP”, y se ven y ponen en practica algunos de los principios basicos del disefo y la programacién orientada a objetos con el objetivo de tomar conciencia de diversas buenas practicas que haran que los sistemas que disefemos y los productos de software que desarrollemos sean de la mas alta calidad. SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. Contenido CREATIVE COMMONS Attribution-NonCommercial-NoDerivs 3.0 Unported SOLID y GRASP... Buenas practicas hacia el éxito en el desarrollo de software. PRINCIPIOS SOLID, 5 > SRP > Single Responsibility Principle Principio de Unica responsabilidad, Ejemplo 1... Solucién: 0 > OCP > Open / Closed Principle Principio abierto/ cerrado... Ejempl Solucién L > LSP > Liskov Substitution Principle Principio de sustitucién de Liskov (Barbara Liskov)... Ejemplo 3... Solucién 1 ISP > Interface Segregation Principle Principio de Segregacién de Interfaces. Ejemplo 4... Solucién D> DIP > Dependency Inversion Principle Principio de Inversién de Dependencias. Ejemplo Solucion: RESUMEN GRASP: Patrones generales de asignacién de responsabilidades Alta cohesién y bajo acoplamiento Alta cohesién. Bajo acoplamiento Controtador. Creador Universidad de Sevilla || IWT2DojoUS || Juan Ga 10 2 2 12 14 16 16 16 18 9 19 19 20 2 23 23 24 24 27 29 Carmona || Noviembre de 2012 1 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. Experto en informacién. 2 Fabricacién Pura. a4 Indireccién. Polimorfismo Variaciones protegidas 39 Solucién: 40 NOTAS FINALES, 4a Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 2 SOLID y GRASP. Buenas practicas hacia el éxito en el desarrollo de software. CREATIVE COMMONS Attribution- NonCommercial-NoDerivs 3.0 Unported Esta obra, “SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software.", se distribuye bajo licencia Creative Commons Attribution- NonCommercial-NoDerivs 3.0 Unported (CC BY-NC-ND 3.0) lo cual significa que Usted es libre de: + Compartir éste documento - copiar, distribuir y comunicar publicamente la obra, Bajo las condiciones siguientes: ‘+ Attribution - Debe reconocer la autoria de la obra de a misma forma en la que se hace aqut y bajo las mismas condiciones (CC BY-NC-ND 3.0). + Noncommercial - No puede utilizar esta obra directa o indirectamente para fines comerciales 0 con énimo de lucro. + No Derivative Works - No se puede alterar, transformar o ampliar este trabajo. Entendiendo qui + Alguna de estas condiciones pueden no aplicarse si se obtiene el permiso explicito del titular de los derechos de autor, en éste caso Juan Garcia Carmona. + Cuando ta obra o alguno de sus elementos es de dominio piblico segin la legislacién aplicable, como sucede por ejemplo con los textos que han sido copiados directamente de Wikipedia, esta situacién no es en absoluto afectada por la licencia y no esta sujeto a las mismas condiciones. Tenga en cuenta que para cualquier reutilizacién o distribucién, usted debe dejar claro a los otros los términos de la licencia de esta obra. La mejor manera de hacer esto es con un enlace a esta pagina web (http://creativecommons.org/licenses/by: nne:nd/3.0/) 0 incluyendo la licencia asi SOLID Y GRASP: Buenas practicas hacia el éxito en el desarrollo de software. by Juan Garcia Carmona fs Heensed under a Creative Commons Reconacimiento-NoComerc Universidad de Sevilla || IWT2 DojoUS || Juan Garcia Carmona || Noviembre de 2012 3 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 4 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. SOLID y GRASP Buenas practicas hacia el éxito en el desarrollo de software. PRINCIPIOS SOLID Los principios SOLID son cinco principios enunciados por Robert C. Martin alrededor del afio 2000 enfocados a la elaboracién de software de calidad. Una clara definicién de los principios SOLID la podemos encontrar en Wikipedia: En ingenieria de software, SOLID (Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion) es un acronimo mneménico introducido por Robert C. Martin a comienzos de la decada del 2000 que representa cinco principios basicos de la programacién orientada a objetos y el disefto. Cuando estos principios se aplican en conjunto es mas probable que un desarrollador cree un sistema que sea facil de mantener y ampliar en el tiempo. Los principio SOLID son guias que pueden ser aplicadas en el desarrollo de software para eliminar cédigo sucio provocando que el programador tenga que refactorizar el cédigo fuente hasta que sea legible y extensible. Debe ser utilizado con el desarrollo guiado por pruebas o TDD, y forma parte de la estrategia global del desarrollo agil de software y programacién adaptativa. Esta definicién es perfectamente valida y se podria resumir diciendo que son cinco principios que hay que tener siempre presentes si queremos desarrollar un software de calidad, legible, entendible y facilmente testeable. sor qué facilmente testeable? Principalmente porque nos va a obligar a sacar muchas interfaces, cosa que favoreceré la utilizacién de Mocking, y haré que el trabajo de testear una clase sea conciso, ademas favorece el TDD porque se prepara el codigo para los sucesivos ‘cambios propios del TDD... Como bien dice la definicién de Wikipedia los cinco principios son ‘+ SRP: Single Responsibility Principle + OCP: Open/Closed Principle + LSP: Liskov Substitution Principle + ISP: Interfaze Segregation Principle + DIP: Dependency Inversion Principle En ésta sesién de trabajo veremos, uno por uno, cada principio, siguiendo éste guion con cada uno de ellos 1. Definicién original, en inglés. 2. Traduccién literal. 3. Interpretacién. Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 5 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. 4, Un ejemplo que no cumple el principio y una explicacién de por qué no lo ‘cumple que incluye diagramas estaticos UML y codigo C#. 5. Trabajo en grupo para arreglar dicho ejemplo aplicando el principio en cuestion. Asi que manos a la obra... S > SRP > Single Responsibility Principle Principio de Unica responsabilidad Enunciado original: "There should never be more than one reason for a class to change Traduccién literal: "No deberia haber nunca mas de una razén para cambiar una clase.” Interpretacién: Una clase deberia concentrarse sélo en hacer una cosa de tal forma que cuando cambie algin requisito en mayor 0 menor medida dicho cambio sélo afecte a dicha clase por una razon. Ejemplo 1 Enunciado: Supongamos que tenemos un paquete de software para la gestion de correos electrénicos. En algin lugar de dicho paquete, antes del envio de los correos en si, queremos establecer los distintos parametros que, por ahora, son: + Emisor + Receptor + Contenido UML ORIGINAL: De una forma muy sencilla la interpretacién de dicho enunciado podria ser ésta: interface IcorrepElectroniso + SatReceptorSting) sid + Saicontenide(Ssirg) void Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 6 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. CODIGO ORIGINAL: Y la implementacion es ésta: public interface ICorreoElectronico ‘void SetEmisor(String emisor); ‘void SetReceptor(string receptor); ‘void SetContenidosirinz contenido); y public class CorreoElectronico : ICorreoElectronico { public void SetEmisor(string emisor) { } public void SetReceptor(string receptor) } Public void SetContenido(string contenido) { } y @Por qué incumple el principio de tnica responsabilidad? ‘SRP nos dice que sélo deberia haber un motivo para cambiar una clase o una interfaz , por ende, las clases que la implementan. {Qué motivos veis que puedan hacer que la clase cambie? En éste caso la traduccién literal es clara, si cambiara el contenido Porque, por ejemplo, admitiera mas tipos, habria que modificar el cédigo cada vez que aiiadamos algin tipo de contenido o si, por ejemplo, cambiara el protocolo y quisiéramos afiadir mas campos también habria que modificar ta clase email. Por tanto hay mas de un motivo por el que tendriamos que modificar ésta clase. Veamos ‘otro ejemplo que no cumple con el SRP. Solucién: UML Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 7 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. cépiGo interface ICorreotlectronico void SetEmisor(String emisor); Void SetReceptor(stins receptor); ‘void SetContenido(/Contenido content); y Interface IContenido String GetContenidoSerializado(); // para serializar el contenido z ‘lass CorreoElectronico : ICorreotlectronico public void Setmisor(string sender) (} public void SetReceptor(strins receiver) (} public void SetContenido( Contenido content) {} z Si en vez de un contenido String utitizamos una interfaz IContenido que suponga un contrato para hacer viable cualquier tipo de contenido cada vez que nos pidan que afiadamos un tipo de contenido sélo tendremos que modificar dicha interfaz y/o las clases que lo implementen, a lo que afecte el cambio, y no ya a la clase de Correotlectrénico y a su interfaz. {Qué os parece? 0 > OCP > Open / Closed Principle Principio abierto/cerrado Enunciado original: “Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.’ Traduccién literal: "Las entidades de software (clases, médulos, funciones, etcétera) deberian estar abiertas a la extensién pero cerradas a la modificaciér Interpretacién: Cambia el comportamiento de una clase mediante herencia, polimorfismo y composicién, Esto es, anticipate al cambio, prepara tu cédigo para que los posibles cambios en el ‘comportamiento de una clase se puedan implementar mediante herencia y ‘composicién. Ejemplo: Enunciado: Disefiar un editor gréfico capaz de dibujar un circulo y un recténgulo Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 8 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. UML ORIGINAL: CODIGO ORIGINAL: [public interface IForma { int GetTipo(); z public class Rectangulo : Forma { Pees) return 1; 2 y public class Circulo : [Ferma ea return 2; ? z public class EditorGratico public void DibujarForma(iForma forma) t ieceresD) case ts DibujaUnRectangulo((jectangulo)forma); break; case 2: Dbujauncirst(Crelo}ormay, 2 y private void DibujaUnCireulo(Circulo ¢) {U/pinta un cireuo. Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 9 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. y private void DibujaUnRectangulo(ectangulo r) {pinta un rectangulo. } ePor qué incumple el principio abierto / cerrado? UML Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 10 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. Lo que buscamos es esto, mas simple, mas sencillo, mas robusto, mas cerrado a las modificaciones pues un circulo siempre se pinta igual y un rectangulo lo mismo pero ala vez abierto a la extensién porque podemos afadir las formas que queramos sin tener que modificar cédigo anterior en el EditorGrafico. {0s gusta? Siempre que tengais comportamientos que dependan del tipo pensad en si se puede implementar ‘con una clase abstracta... Hay muchos ejemplos en distintos lenguajes sobre éste tipo de soluciones... cépico public abstract class Forma public abstract void Dibujar(); protected void DibujarComun() 11 Parte comin en todos los métodos dibujar para todas las formas... 2 y public class Rectangulo : Forma { public override void Dibujar() { 11 Hay algo comin en todos los métodes dibujar? DibujarComun(); 77 Dibuja un Rectangulo 2 y public class Circulo : Forma public override void Dibujar() Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 a SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. ‘ 11 gHay algo comin en todos los métodos dibujar? DibujarComun(); 17 Dibuja un circulo 7 y public class EditorGrafico public void DibujarForma(Forma forma) forma.Dibujar(); ? y El cédigo de esto es realmente simple... Ademés, una de las ventajas de las clases abstractas es que podemos colocar en ellas todo el cédigo que es comin y nos evitamos tener que mantener bloques iguales de cédigo en distintos sitios, cosa que suele ser una auténtica pesadilla, amén de lo que supone esto si estamos haciendo TDD pues lo comin se testea una vez y lo particular también. UNo es genial? De una forma elegante hemos ganado en simplicidad, sélo hemos utilizado una clase abstracta con un método abstracto que sera implementado por cada clase hija. Voy a insistir en mi propia traduccién de éste principio, si has de cambiar una clase hazlo usando herencia y polimorfismo. No debes temer el uso de clases abstractas ni interfaces sino al revés, potenciarlo, ya que son una ayuda contra el acoplamiento de tu software que te protegen frente a cambios. L > LSP > Liskov Substitution Principle Principio de sustitucién de Liskov (Barbara Liskov) Enunciado original: “Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it. Traduccién literal: “Las funciones que utilicen punteros o referencias a clases base deben ser capaces de usar objetos de clases derivadas de éstas sin saberlo.” Interpretacién: Las subclasses deben comportarse adecuadamente cuando sean usadas en lugar de sus clases base. Ejemplo 3 Enunciado: Un cuadrado es un rectangulo con la peculiaridad de que sus lados miden exactamente lo mismo, al menos eso es lo que ha deducido el tan altamente cualificado y estimado grupo de anélisis que nos proporciona los requisitos para éste tan poco original ejemplo y quien nos proporciona a su vez el siguiente diagrama estatico de clases: Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 2 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. UML ORIGINAL: = Gute Teva | CODIGO ORIGINAL: Nosotros, desarrolladores bien mandados, cumplimos a rajatabla dicho diagrama y escribimos el siguiente cédigo: public class Rectangulo public int Alto { get; set; } public int Ancho { get; set; } public int GetArea() £ ? y Public class Cuadrado : Rectangulo return Alto * Ancho; public override int Alto { get {retumn base.Alto; } set { base.Alto = base.Ancho = value; } , public override int Ancho { set {return base-Ancho; } set { base.Ancho = base, Alto = valu 7 z public class Prueba private static Rectangulo GetNewRectanguto() 11 Podria ser cualquier objeto que también sea un rectangulo.... 11 por ejemplo un cuadrado... No? return new Cuadrado(); 2 Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 B SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. public static void Main() var r= GetNewRectangulo(); 11 El usuario “sabe” que r es un rectangulo T1y asume que puede darte valor al alto y al ancho... alto rancho Console,WriteLine(r.Getarea()); 17¥ al ver la consola el usuario dice: WTF! zPOR QUE INCUMPLE EL PRINCIPIO? Solucién: UML Universidad de Sevilla || IWT2 DojoUS Carmona || Noviembre de 2012 14 SOLID y GRASP Buenas practicas hacia el éxito en el desarrollo de software, copiGo public interface IRec { void SetAlto(int alto); void SetAncho(int ancho}; ‘int GetArea(); y public class Rectangulo : IRectangular { private int alto; private int “ancho; public void SetAlto(int alto) alto = alto; } public void Setanchotint ancho) { acho = ancho; 7 public int GetArea() return alto ? z _ancho; public class Cuadrado : Rectangular { private int lado; public void SetAlto(int alto) lado » alto; } public void Setanchotint ancho) lado = ancho; d public int GetArea() c return lado * lado; 2 y Universidad de Sevilla || IWT2D9joUS || Juan Garcia Carmona, Noviembre de 2012 15 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. 1 > ISP > Interface Segregation Principle Principio de Segregacién de Interfaces Enunciado original: “Clients should not be forced to depend upon interfaces that they do not use. Traduccién liters que no utilizan.’ “Los clientes no deberian ser forzados a depender de interfaces Interpretac unas con otras. Mantén las interfaces pequefias y cohesivas, que puedan coexistir Ejemplo 4 Enunciado: Supongamos la siguiente interfaz: public interface ITrabajador void Trabajar(); void Descansar(); void Comer); Imaginemos las siguientes implementaciones de dicha interfaz: public class TrabajadorPlanta ITrabajador { public void Trabajar() 11 Trabaja mucho ? public void Descansar() 11 Descansa poco } public void Comer() 11 Nada, como en casa y aqui no se contempla que un trabajador de planta pueda comer.. 11 Para qué public class Desarrollador ITrabajador public void Trabajar() 11 Parece que bastante 7 public void Descansar() 11 0 €5 que estoy compilande el cédigo..” 7 Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 16 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. public void Comer() 11 y también beber café } z public class Robot : ITrabajador { public void Trabajar() 11 Soy el que mas trabajo, de es0 no cabe duda public void Descansar() 11 pDescansar yo? } public void Comer() we 3 y Y para “controlar” a éstas implementaciones ;qué tenemos? Pues un... public class JefeDespota (1 éste no falla.. private ITrabajador _trabajador; public void ElegirTrabajador(/"rabajador trabajador) {11 WV si me elige amit trabajador = trabajador; 2 public void Mandar() (/1 jA.ver qué pide ahoral _trabajador.Trabajar(); ) z @Por qué incumple el principio de segregacién de interfaces? Qué significa segregar? Pues la RAE dice: segregar. (Del lat. segregare) 1. tr. Separar o apartar algo de otra u otras cosas. 2. tr. Separar y marginar a una persona o a un grupo de personas por motivos sociales, politicos 0 culturales. 3. tr. Secretar, excretar, expeler. Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 7 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. cODIGO public interface ITrabajar void Trabajar(); y Interface IDescansar t ‘void Descansar(); y public interface IComer t void Comer); y public class TrabajadorJornadaCompleta:ITrabajar, IDescansar, IComer t public void Trabajar() t 3 public oid Descansar() c 2 public void Comer() € 2 y public class TrabajadorMediaJomada : ITrabajar, IDescansar { public void Trabajar() { 3 Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 18 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. public void Descansar() € 7 y public class Robot:ITrabajar public void Trabajari) £ ? y D > DIP > Dependency Inversion Principle Principio de Inversion de Dependencias Enunciado original: "A. High level modules should not depend upon low level modules. Both should depend upon abstractions. B. Abstractions should not depend upon details. Details should depend upon abstraction: Traduccién literal: “A. Médulos de alto nivel no deberian depender de médulos de bajo nivel. Ambos deberian depender de abstracciones. B. Las abstracciones no deberian depender de los detalles. Los detalles deberian depender de las abstracciones. Interpretacion: para conseguir robustez y flexibilidad y para posibilitar la reutilizacion haz que tu cédigo dependa de abstracciones y no de concreciones, esto es, utiliza muchas interfaces y muchas clases abstractas y, sobretodo, expén, por constructor o por parémetros, las dependencias que una clase pueda tener. Ejemplo Enunciado: Nuestro cliente nos da el siguiente requisito: “Quiero que la casa tenga puerta y ventana” Los clientes SIEMPRE son asi te dicen: parece muy simple y en realidad lo es, hasta que luego “También quiero que las puertas y las ventanas sean personalizables”.. Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 19 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. CODIGO ORIGINAL: Codificar esto no tiene ninguna complicacién, :no es cierto?: public class Door { } public class Window { } public class House { private Door _door; private Window window; public House() t oor = new Do0r()s Swindow = new Window); ? @Por qué incumple el principio de inversién de dependencias? Solucién: Public class House { private IDoor _door; private Window windows public House() { oor = new Door(}; window = new Window(); z public IDoor Doors public Window Windows, Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 20 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. public interface IDoor { string GetColor(); void OnOpen(); void Onclose(); y public class BrownDaor : IDoor t public void OnOpent) { } public void OnClose() { public string GetColor() { ‘return “Soy una puerta marrén’; 2 y public interface IWindow string GetSize(); ‘void OnOpen(); void Onclose(); y public class BigWindow + IWindow t public void Ondpent) { } public void OnClose() { } public string GetSize() C ‘return “Soy una ventana grande"; 7 y public class House { private IDoor _door; private IWindaw windows public House()0 public House(D00r door, iWindow window) { door = door “window = window; 2 public 1Do0r Doors, public Window Windows, Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 21 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. UML EE RESUMEN Es el momento de tomar un descanso... Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 22 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. GRASP: Patrones generales de asignacién de responsabilidades En el mundo anglosajén gustan mucho los juegos de palabras. Esto lo digo porque, de ‘gual forma que estoy seguro de que SOLID, que significa sélido, no fue elegido al azar, no creo que sea casualidad que se haya elegido el acrénimo GRASP para designar a los “General Responsibility Assignment Software Patterns’, 0 lo que es lo mismo, patrones generales de asignacién de responsabilidades en software ya que la palabra ‘grasp’ significa comprender, entender 0 alcanzar, GRASP son una serie de buenas practicas enfocadas a la calidad del software, calidad structural” por llamarla de alguna manera, ya que no se ha centrado en pruebas, sino en la estructura y las responsabilidades de las clases que componen el software que desarrollamos. GRASP hay que considerarto como una serie de buenas practicas, unos pocos consejos, que hay que seguir si se quiere hacerlo bien. GRASP son siete patrones o “consejos”: Alta cohesién y bajo acoplamiento Controtador Creador Experto en informacién Fabricacién pura Indireccién Polimorfismo Variaciones protegidas Novae ‘AL igual que con SOLID vamos a ir uno por uno viendo primero la definicién, vamos a entenderla y vamos a aplicar cada patrén de una manera lo mas practica posible. En Internet probablemente los encontréis en otro orden, en mi opinién el orden alfabético, en castellano, es tan bueno como cualquier otro, Vamos a ello: Alta cohesion y bajo acoplamiento Qué significa? {Qué es cohesion y acoplamiento? El grado de cohesién mide la coherencia de una clase, esto es, lo coherente que es la informacion que almacena una clase con las responsabilidades y relaciones que ésta tiene con otras clases. El grado de acoplamiento indica lo vinculadas que estén unas clases con otras, es decir, lo que afecta un cambio en una clase a las demas y por tanto lo dependientes ue son unas clases de otras. Como se ve claramente, los conceptos de cohesién y acoplamiento estan fntimamente relacionados. Un mayor grado de cohesién implica uno menor de acoplamiento. Maximizar el nivel de cohesién intramodular en todo el sistema resulta en una minimizacién del acoplamiento intermodular. Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 23 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. Alta cohesion Nos dice que la informacién que almacena una clase debe de ser coherente y debe estar, en la medida de lo posible, relacionada con la clase. Los puritanos y teéricos diferencian 7 tipos de cohesion 1. Cohesién coincidente: el méduto realiza miltiples tareas pero sin ninguna relacién entre ellas. 2. Cohesién légica: el médulo realiza miiltiples tareas relacionadas pero en tiempo de ejecucién sélo una de ellas sera llevada a cabo. 3. Cohesién temporal: las tareas llevadas a cabo por un médulo tienen, como unica relacion el deber ser ejecutadas al mismo tiempo. 4, Cohesién de procedimiento: a dinica relacién que guardan las tareas de un médulo es que corresponden a una secuencia de pasos propia del producto. 5. Cohesién de comunicacién: las tareas corresponden a una secuencia de pasos propia del producto y todas afectan a los mismos datos. 6. Cohesién de informacién: las tareas llevadas a cabo por un médulo tienen su propio punto de arranque, su codificacién independiente y trabajan sobre los mismos datos. El ejemplo tipico: OBJETOS 7. Cohesién funcional: cuando el médulo ejecuta una y sélo una tarea, teniendo tun Gnico objetivo a cumplir. Bajo acoplamiento Es la idea de tener las clases lo menos ligadas entre si que se pueda, de tal forma que, en caso de producirse una modificacién en alguna de ellas, tenga la minima repercusién posible en el resto de clases, potenciando la reutilizacién, y disminuyendo la dependencia entre las clases. También hay varios tipos de acoplamiento. 1. Acoplamiento de contenido: cuando un médulo referencia directamente el contenido de otro médulo. (hoy en dia es dificil verlo, quizé es més facil verlo ‘en entornos de programacién funcional) 2. Acoplamiento comtin: cuando dos médulos acceden (y afectan) a un mismo valor global. 3. Acoplamiento de control: cuando un médulo le envia a otro un elemento de control que determina la légica de ejecucién del mismo. Pero basta de palabreria, pasemos a los ejemplos. Para éste primer principio tengo varios ejemplos malos y uno bueno. Sin conocer nada de C#, public class ClaseDeLogicaDeNegocio { public void DoSomething() { 11 Coge parametros de configuracién ‘var umbral = int.Parse(Configuration\anager.AppSettings["umbrat]); ‘var connectionString = Coniguration\ianager.AppSettings|"connectionString’); 11 Nammos a por datos... var sql = @'select* from cosas like parametro >"; sql += umbral; Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 24 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. using (var connection = new SolConnection(connectionString)) ‘connection. Open(); ‘var command = nev SeiCommand(sql, connection); using (var reader = command.ExecuteReader()) t while (reader. Read) ( var nombre = reader[ Nombre'] ToString(); var destino = reader{'Detino"].ToString(); 1/ Haz algo més de ldgica de negocio por otro lado. HacerMasLogicaDeNegocio(nombre, destino, connection); d y z Dublic void HacerMasLogicaDeNegocio(string nombre, string destino, SqjConnection conexton) € } y iNo huele un poco mal éste cédigo? Aunque éste cédigo podria haberlo escrito yo, cosas Peores he escrito, leo esto y tengo que soltar un tremendo WTF! ,Quién tiene que arreglar ‘esto? Nadie nace sabiendo... Otro ejemplo, imagina que tenemos la clase mensaje: lass Mensaje { private string para; private string ~asunto; private string _mensaje; public Mensaje(string to, string subject, string message) paras to; Tasunto = subject; Tmensaje = message; ublic void Enviar() 11 enwia el mensa} 7 z Imagina que después alguien pide que se haga login antes del envio y el desarrollador hace lo siguiente: lass MensajeVersion2 { private string _para; private string _asunto; private string _mensaje; private string “nombreUsuario; public MensajeVersion2(string to, string subject, string message) £ _para = to; Tasunto = subject; Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 25 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. _mensaje = message; public void Enviar() 11 envia el mensaje. 2 public void Login(string nombreUsuario, string contrasefia) { _nombreUsuario = nombreUsuario; 71 code to login 2 y Una buena solucién podria ser la inversion de dependencias, la D de SOLID asi: public interface Servicioemail void Enviar(string asunto, string mensaje); Public interface IServicioLogin void Login(string nombreUsuario, string contrase‘ia); public interface |UserControtler { void Registrar(}; y public class UserController : [UserController { private readonly IServiciomail _servicioemait; private readonly IServiciol ogin “servicioLogin; public UserController(\Serviciof mall servicioEmail,IServicioLogin servicioLogin) £ 11 Se harian las debidas comprobaciones y después: -servicioE mail = servicioEmail; “servicioLogin = servicioLogin; z public void Registrar() { // Autenticar y enviar: _setvicioLogin.Login(‘usuari Tservicio€ mail Enviar(‘asun 2 ce 11 Etcétera.. Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 26 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. 2Qué principios SOLID se ven en éste cédigo? Controlador El patron controlador es un patrén que sirve como intermediario entre una determinada interfaz y el algoritmo que la implementa, de tal forma que es el controlador quien recibe los datos del usuario y quien los envia a las distintas clases segin el método llamado. Este patrén sugiere que la légica de negocio debe estar separada de la capa de presentacién, lo que aumenta la reutilizacién de cédigo y permite a la vez tener un mayor control. Hay muchas arquitecturas de aplicacién que se basan en esto, desde el famoso MVC que ya vi estudiando la carrera hasta la arquitectura MVVM tan utilizada Ultimamente en aplicaciones de escritorio y la Ultima que he practicado profesionalmente, MVVMP, que no es mas que un refinamiento sutil de la anterior. Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 27 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. Un Controtad + Deberia ser el primer objeto llamado después de un cambio en la interfaz de usuario, + Controla/ejecuta un caso de uso. No hace demasiado por si solo, controla, coordina, + Pertenece a la capa de aplicacién 0 a la de servicios. Este ejemplo se centra en que el controlador debe ser el primer objeto llamado por objetos de la Ul: public class Albumview { } public class AlburPresenter AlbumiView _vista; AlbumContraller _controtador; public void EtiquetaAdded(string etiqueta) € controlador. EtiquetarFoto(etiqueta); } y public class AlbumController public void EtiquetarFoto(string newTag) { ) y Este otro ejemplo se centra en que el controlador no deberia hacer demasiado, tan sélo coordinar: public class AlbumView { d public class AlbumPresenter { AlbumView _vistay AlbumContraller _controtador; public void EtiquetaAdded(string etiqueta) controlador. EtiquetarFoto(etiqueta); ) y public class AlburControtler { private RepositorioDeFotos repository; public void EtiquetarFoto(string nuevaétiqueta) £ var foto = _repository.ReadFoto(); foto. Addétiqueta(nuevaEtiqueta); Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 28 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. _tepository.UpdateFoto(foto); y public class RepositorioDeFotos { 11 Operaciones CRU public Foto ReadFoto() i return new Foto(); 7 public void UpdateFoto(Foto foto) € } z public class Foto public void Addtiqueta(string tag) £ } z Creador La creacién de instancias es una de las actividades mas comunes en un sistema orientado a objetos. En consecuencia es itil contar con un principio general para la asignacién de las responsabilidades de creacién. Si se asignan bien el disefio puede soportar un bajo acoplamiento, mayor claridad, encapsulamiento y reutilizacion. El patrén creador nos ayuda a identificar quién debe ser el responsable de la creacién o instanciacién de nuevos objetos o clases. Este patrén nos dice que la nueva instancia podra ser creada por una clase si: + Contiene o agrega la clase. + Almacena la instancia en algiin sitio (por ejemplo una base de datos) + Tiene la informacién necesaria para realizar la creacién del objeto (es “Experta’) + Usa directamente las instancias creadas del objeto Una de las consecuencias de usar este patrén es la visibilidad entre la clase creada y la clase creadora. Una ventaja es el bajo acoplamiento, lo cual supone facilidad de mantenimiento y reutilizacion. ‘Veamos, con una serie de ejemplos de cémo aplicar éste patrén correctamente bajo distintas circunstancias. Ejemplo base: public class ListaDeClientesPresenter Cliente clientes; public void AddButtonClicked() Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 29 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. ¢ 2 y public class Cliente ListePedido> _pedides; y public sealed class Pedido { ? Ejemplo 2: public class ListaDeClientesPresenter Cliente cliente; public void AddButtonClicked() © tent. AdaPedidod; » 11 En éste caso contiene o agrega la clase y ademas maneja varias instancias.. public class Cliente ListePedido> _pedides; public void AddPedidot) { var nuevoPedido = new Pedio(); —Dedidos.Add(nuevoPedio); y public sealed class Pedido { 1 11 Pero hay mas posibilidades. Ejemplo 3: 11 Sila clase quaréa (persiste) la clase creada.. 11 Lo mis facil es implementar un repositorio: public class ListaDeClientesPresenter { private RepositoriaDePedidos reposttorioDePedidos; public void AddButtonlicked() £ Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 30 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. } y public class Cliente ListePedido> _pedidas; z public class RepositorioDePedidos © seam _pediostmt public Pecido LoadOrders() caro a pedi yl deneo return pedido; » public tad cP string public Pedido(string td) ( -id=id; 7 z Ejemplo 4: 71 La clase tiene la informacién necesaria para crear la nueva clase 11 Por ejemplo si queremos que Pedido tenga et Id de cliente public class ListaDeClientesPresenter Cliente clientes public void AddButtonClicked() € _sliente,AddPedido(); } y public class Cliente { ListePedido> _pedidos; int _id; public void AddPedido() € var nuevoPedido = new Pedido( id); —edidos.Add{nuevoPedido); 7 z public seated class Pedido private int _clienteld; public Peaido(int clientela) _ctienteld = clienteld; ? y Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 31 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. Ejemplo 5: 1/ La clase usa directamente la clase creada 11 Por ejemplo si queremos que el Cliente gestione Pedido/s public class ListaDeClientesPresenter Cliente cliente; public void AddButtonClicked() ( } y public class Cliente { Pedido _pedido; 1/ La responsabilidad de crear esta clase que él mismo maneja tantas veces recae sobre &l aqui ‘en cualquier otro lugar. public Ctienteg) ~pedido = new Pecido(); 7 public void DeleteOrder() Reece public void RenameOrder(string newName) ( _pedido.Modificar(); ? y public sealed class Pedido public void Borar()Q public void ModificarQQ z De nuevo no hay mucho mas que decir sobre éste patrén, tan solo que hay que tener en cuenta esos cuatro puntos a la hora de instanciar un objeto y preguntarse si el lugar en el que se esta realizando es el idéneo 0 no. Darse cuenta de que no se esta cumpliendo con el patrén creador es un buen motivo para refactorizar nuestro codigo. Experto en informacién Este es el principio basico de asignacién de responsabilidades, la S de SOLID, y para i es de los mas importantes de los patrones o principios GRASP. Experto en informacién nos dice que la responsabilidad de la creacién de un objeto o la implementacién de un método, debe recaer sobre ta clase que conoce toda la informacion necesaria para crearlo o ejecutarlo, de este modo obtendremos un Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 32 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. disefio con mayor cohesién y cuya informacién se mantiene encapsulada, es decir, disminuye el acoplamiento. public class informe public int{] Parciales { get; set; } public class InformePresenter Informe _fnforme; public void CalculateTotalButtonClicked() eee foreach (var parcial in informe. Parciales) total = total + parcial; } 11 TIP: éste bucle lo podemos convertir en un una expresién funcional usando Ling: forme.Parciales.Aggregate(0, (current, parcial) => current + parcial); qué falla aqui? zPor qué viola éste principio? Por lo mismo que viola la S de SOLID, la responsabilidad de InformePresenter es, ‘como su propio nombre indica, presentar un informe y en éste caso esta calculando cel total, {Mall El total deberfa darselo la clase Informe, que es la que tiene toda la informacion al respecto, ella es la experta y quien deberia calcularlo. public class Informe public int{) Parciales { get; set; } public void CalcularTotal() € var total = 0; foreach (var parcial in Parciales) total = total + parcial; } 7 y public class InformePresenter private Informe informe; public void CalculateTotalButtonClicked) ( -informe.CatcularTotal(); ? y Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 33 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. Regla de oro: Este es el principio que se deberia aplicar mas a menudo, el que hay que tener mas fen cuenta. La suma de "Experto en informacién’ y SRP es que una clase sélo deberia tener un motivo para cambiar y deberia ser ella misma la encargada de crear los ‘objetos e implementar los métodos sobre los que es experta. Fabricacién Pura La fabricacién pura se da en las clases que no representan un ente u objeto real del dominio del problema sino que se han creado intencionadamente para disminuir el acoplamiento, aumentar la cohesién y/o potenciar la reutilizacién del cédigo. La fabricacién pura es la solucién que surge cuando el disefiador se encuentra con tuna clase poco cohesiva y que no tiene otra clase en la que implementar algunos métodos. Es decir que se crea una clase “inventada” o que no existe en el problema como tal, pero que, aijadiéndola, logra mejorar estructuralmente el sisterna. Como contraindicacién deberemos mencionar que al abusar de este patrén suelen aparecer clases funcién o algoritmo, esto es, clases que tienen un solo método. Un ejemplo de porqué tendriamos que inventarnos una clase fuera del dominio del problema, imaginemos que estamos programando el famoso Angry Birds: public class Pajarofnfadado public void Votar() £ 7 public void Mostrar() 11 €n una interfaz de usuario 7 y El método Mostrar “acopla” al pajaro a la interfaz de usuario y como no queremos enfadarlo atin mas hariamos lo siguiente: public class Pajarotnfadado public void Votar() { } y public class PajaroEnfadadoPresenter public PajaroEnfadadoPresenter(2jaroEnfadadoView view) view. Mostrar(new PajaroEnfadado()}s } y Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 34 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. public class PajaroenfadadoView public void Mostrar(PajaroEnfadado pajaroEnfadado) £ 7 y Ahora tenemos dos nuevas clases, view y presenter. Estas dos clases no existen en el dominio real del problema pero desacoplan enormemente ta implementacién del pajaro de la interfaz de usuario... Y nos dejan que la implementacién del pajaro enfadado se centre en ta légica de negocio y en nada mas, una dnica responsabilidad... {No te suena? Seguro que si pero quizé nunca te habias preguntado el porqué de las arquitecturas de n capas, me da igual que sea MVC que MVP, que MVVM o MVVMP. Es una idea simple e intuitiva a la que ahora puedes ponerle un nombre y decir que se basa en el patron GRASP de "Fabricacién pura’ Indireccion Voy Uegando al final de los patrones o principios GRASP, éste, la indireccién, es fundamental y, como buenos profesionales, deberiamos tenerlo muy presente en nuestros andlisis y decisiones arquitecturales. El patron de indireccién nos permite mejorar el bajo acoplamiento entre dos clases asignando la responsabilidad de la mediacién entre ellos a una clase intermedia. Problema: ;dénde debo asignar responsabilidades para evitar o reducir el acoplamiento directo entre elementos y mejorar la reutilizacion? Es decir, si sabemos que un objeto utiliza otro que muy posiblemente va a cambiar, {como protegemos a un objeto frente a cambios previsibles? Solucién: asignar la responsabilidad a un objeto que medie entre los elementos para proteger al primer objeto de los posibles cambios del segundo, Imaginemos que estamos desarrollando un componente de software para hacer logs dentro de una gran arquitectura... public class CualquierPresentador LogaNet logger; public void AlgoHaSucedido() ~logger.Log(‘Aigo ha sucedido y hemos tratado en el presentador dicho algo..." y public class LogaNet public void Log(string message) i Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 35 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. En éste caso Log4Net podria cambiar, de hecho esperamos que cambie porque lo estamos utilizando, si, pero se nos queda cortos. ;Cémo aplicamos la indireccién? {Qué tal si creamos un servicio de login intermedio? Asi el presentador utilizar el servicio y con un poco de suerte los cambios en Log4Net no afectaran demasiado al resto del programa. public class CualquierPresentador { private Serviciolog logger; public void AlgoHaSucedido() { —logger.Log(Algo ha sucedido y hemos tratado en el presentador dicho algo..."} y public class ServicioLog ( private Loz4Net logger; public void Logi string message) 1 “eerLorinesagey y public class LogaNet pute vd Logtsving message) } y Este patrén es fundamental para crear abstracciones ya que nos permite introducit ‘API's externas en la aplicacién sin que tengan demasiada influencia en el cédigo que tendria que cambiar cuando cambiara la API. Ademés, la primera clase podria cambiarse facilmente para que en vez de ésta AP! utitizara cualquier otra. Polimorfismo ‘Alo largo de todos de ésta sesién ha aparecido la palabra polimorfismo alrededor de una decena de veces y he dado por hecho que todo el mundo sabia de qué estaba hablando, pero iqué es polimortismo? Polimorfismo, en programacién orientada a objetos, es un concepto muy simple con el que la gente a veces se lia, polimorfismo es permitir que varias clases se comporten de manera distinta dependiendo det tipo que sean. Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 36 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. ‘Siempre que se tenga que llevar a cabo una responsabilidad que dependa de un tipo, se tiene que hacer uso del polimorfismo, es decir, asignaremos el mismo nombre a servicios implementados en diferentes objetos acordes con cada tipo. Como de costumbre, veamos esto con un ejemplo "malo", es decir, mejorable, la explicacién y un ejemplo que lo soluciona, public enum TipoDeLog Debug, Error y public class Loz © seameter_cherolog: public void Registrar(string mensaje, TipoDe!lo2 tipaDeLog) ‘ penny case TipoDeLog. Debug: ficheroLog. WriteLine( [DEBUG);(0}", mensaje); Break; ‘case TipoDeL og. Error ficheroLog. WriteLine("[ERROR}:(0)", mensaje); Break; } 2 y public class CualquierPresentador Log tog; public void AlgoHaSucedido() € log. Registrar(‘Algo ha sucedido y queremos dejar constancia en un registro.", ‘TipobeLog. Debug); 7 y {Por qué esta mal? ;Por qué hemos de refactorizar éste codigo? Se ve claramente la dependencia de la clase Log y el método registrar con el TipoDeLog. Podemos evitar esto creando una interfaz para el mensaje implementada de dos formas distintas, una por cada tipo, y sélo tendremos que pedir a la clase Log ‘que registre un Mensaje. Y dependiendo de qué mensaje queramos registrar, quien sepa de qué tipo debe ser registrado, es decir, el experto en informacion, que cree tuna instancia concreta y llame a Log.Registrar. public interface INensajeDelLog string Valor { gets } public class MensajeDebug : IMensajeDelLog Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 37 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. readonly string _mensaje; public MensajeDebug(string mensaje) £ _mensaje = mensaje; } public string Vator { get { return string.Format(‘[DEBUG];(0)", _mensaje); } } z public class MensajeError : IMensajeDelLog { readonly string _mensaje; public MensajeError(string mensaje} € _mensaje = mensaje; } public string Valor c get { return string,Format("[ERROR];(0)", _mensaje); y d y public class Los { StreamWriter _ficheroLog; public void Registrar(INiensayeDelLog message) ficheroLog, WriteLine(message.Valor); d y public class CualquierPresentador { Log tog; public void AlgoHaSucedidoYQueremosRegistrarUnError() log. Registrar(new INensajeError(‘Algo ha sucedido y queremos dejar constancia en un registio. ) public void AlgoHaSucedidoYQueremosRegistrartoParaDepurar() {1/ Por ejemplo una excepcién log. Registrar(new IvensajeDebug("Algo ha sucedido y queremos dejar constancia en un registro. } y Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 38 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. Variaciones protegidas Siempre se ha dicho que, aplicando metodologias agiles al desarrollo de software, el cambio es bienvenido, ahora bien, el cambio es bienvenido si lo esperamos. ;Cuantos proyectos de software se habran ido a pique y cuantos profesionales habran visto su reputacién por los suelos cuando el cliente ha pedido un pequefio cambio cuyas implicaciones obligaron a arquitectos y desarrolladores a empezar de cero? No sé la respuesta pero seguro que han sido demasiados. El cambio debe ser bienvenido, claro, porque los clientes siempre quieren cambios y les cobraremos por desarrollarlos, pero no deben ser motivo de desesperacian. Variaciones protegidas, es el principio fundamental de protegerse frente al cambio. Esto quiere decir que lo que veamos en un anélisis previo que es susceptible de modificaciones lo envolvamos en una interfaz y utilicemos el polimorfismo para crear varias implementaciones y posibilitar implementaciones futuras de manera que quede to menos ligado posible a nuestro sistema. De ésta forma, cuando se produzca la variacién 0 el cambio que esperamos, dicho cambio nos repercuta lo minimo.Este principio esta muy relacionado con el polimorfismo y la indireccién. Imaginemos el siguiente cédigo: public class imagenspeg public void Redimensionar(int nuevoAlto, int nuevoancho) ‘ 11 Resize ) y public class MostrarlmagenController public void BotonRedimensionarClicked(\maaenpe2 image) image.Redimenstonar(10, 20); } y {Qué problemas pueden surgir? “Qué podria variar? {Cémo lo mejoramos? {Qué problemas pueden surgir? Simple, puede suceder que en vez de una imagen jpeg nos manden otro tipo de imagen. 2 cémo lo solucionamos? También simple si has seguido toda la serie de articulos sobre GRASP y las distintas refactorizaciones que hemos hecho en cada caso, basta con afadir una interfaz llmagen con un método Redimensionar, dejando el cédigo asi: Universidad de Sevilla || IWT2DojoUS || Juan Garcia Carmona || Noviembre de 2012 39 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. Solucién: public interface limagen void Redimensionar(int nuevoalto, int nuevoAncho); public class ImagenJpeg : lImagen © otc void Redimensionartint nuevo, nt nuevadncho) { 11 Resize } public class MostrarimagenController public void BotonRedimensionarClicked(limagen image) C mage.Redimensionar(10, 20); 2 Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 40 SOLID y GRASP Buenas précticas hacia el éxito en el desarrollo de software. NOTAS FINALES ‘Merece la pena comentar: + gPor qué SOLID y GRASP en unas charlas sobre TDD? © Beneficios de la extraccién de interfaces y clases abstractas para Mocking en Test unitarios © Nomenclatura When - ItShould en Tests unitarios reforzada gracias a la separacacién de responsabilidades y a la limpieza en nuestro cédigo + Otros princios: © DRY > Don't Repeat Yourself © KISS > Keep It Simple, Stupid! © YAGNI > You ain’t gonna need it + Mas informacién: © Robert C Martin (“Dios” cuando hablamos de POO, autor a tener en cuenta como referencia...) © Libros recomendados: = Clean Code = Pragmatic Programmer Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 41 SOLID y GRASP. Buenas précticas hacia el éxito en el desarrollo de software. Universidad de Sevilla || IWT2DojoUS || Juan Ga Carmona || Noviembre de 2012 42

También podría gustarte