You are on page 1of 73

Código Limpio & Principios SOLID

El arte de escribir código

Instructor: PhD Luis Roberto Pérez


luis.robertop87@gmail.com
Si estás aquí es por que eres
programador y quieres ser
mejor programador

¡Es perfecto!
El mundo necesita mejores
programadores
Contenido
1. Código Limpio
2. Malos olores en el código (Code Smells)
3. Principios SOLID
Evolución del programador

Inconsciente de Clean Code / SOLID / Patrones de Diseño


Consciente de Clean Code / SOLID / Patrones de Diseño
1. Código Limpio
La única medida válida en el Software WTF/minuto
- ¿Qué puerta representa su código?
- ¿Qué puerta representa a su equipo o
empresa?
- ¿Por qué estamos en esa habitación?
- ¿Es una sencilla revisión de código o
hemos detectado miles de
problemas?
- ¿Depuramos con pánico el código que
pensábamos que funcionaba?
La maestría

Conocimiento y trabajo

Practicar y fallar

Sudar las manos y aplanar el...


Comencemos...
- There will be code (Hágase el
código)
- Bad code (Código Incorrecto)
Lecturas - The total cost of owning a mess
(El costo total del desastre)
Tomadas del libro Clean Code de - The grand redesign in the sky
Robert C. Martin (El gran cambio de diseño)
Efecto del código NO limpio
¿Tuviste que arreglar algo grave en
semanas, cuando aparentemente

Actitud debía durar solo un par de horas?

¿Haz visto un cambio que tuvo que


Programador profesional hacerse en línea (aplicado a cientos
de módulos distintos)?
- Malos convenios de nombramiento
- Malos nombres
- Malas firmas de métodos
- Ubicación polarizada en la
declaración de variables
- Números mágicos
- Condicionales anidadas

2. Code Smells -
-
Sentencias de bifurcación (switch)
Código duplicado
Malos olores en el código - Comentarios + Comentarios
- Métodos largos

“Bad code smells are symptoms of poor design or


implementation choices”
[Martin Fowler]
Convenios de - camelCase
Nombramiento -
-
PascalCase
snake_case
Cada equipo y/o empresa de - Notación Hungara
definir y socializar los convenios a
utilizar durante la codificación
Nombres con - Deben revelar intenciones
sentido
Revelar intenciones

int d; // elapsed time in days

int s; // elapsed time in seconds

int elapsedTimeInDays;

int daysSinceTheCreation;

int fileAgeInDays;
● Escoger buenos nombres toma tiempo pero ahorra
más tiempo del que se invierte.
● Siempre estar al tanto de los nombres y cambiarlos
cuando pienses en uno mejor
● El nombre de una variable, función o clase debe
responder a las grandes interrogantes: ¿Por qué
existe?, ¿Qué hace?, ¿Cómo usarlo?
● Si un nombre requiere un comentario entonces el
nombre no revela sus intenciones.
Evitar desinformación

double hp; // hypotenuse

List accounList;

double hypotenuse;

List bunchOfAccounts;

List accounts;
Evitar variaciones mínimas

var xyzControllerForEfficientHandleOfStrings;
var xyzControllerForEfficientStorageOfStrings;
● Debemos evitar “pistas falsas” que nublen el
significado del código. (hp)
● No agregar el tipo de dato (a menos que realmente
pertenezca al tipo de dato). Ejemplo:
accountList, para los programadores List tiene
un significado propio y exclusivo
● Evitar nombres con mínimas variaciones
Ejemplo desinformativo l y O

int a = l;

if (O == 1)

a = 11;

else

l = 01;
Realizar distinciones con sentido

public void copyChars(char[] a1, char[] a2) {

for(int i = 0; i < a1.length; i++) {

a2[i] = a1[i];

}
private aBall;
private theBall;

getActiveAccount();
getActiveAccounts();
getActiveAccountInfo();

String cust;
String customer;

class ProductInfo { … }
class ProductData { … }

¿Cómo sabe los desarrolladores a cual invocar?


● Distinguir nombres de tal forma que los lectores
entiendan la diferencia. Ejemplo: ProductInfo y
ProductData, efectivamente son diferentes pero
Info y Data no ofrecen un valor de distinción
Usar nombres pronunciables

FLDSMDFR
Flint Lockwood's Diatonic Super Mutating Dynamic Food Replicator
Usar nombres pronunciables

class DtaRDC102 { class Customer {

private Date genymdms; private Date generationTimestamp;

private Date modymdms; private Date modificationTimestamp;

private final String pazint = private final String recordId =


“102” “102”

} }
● El cerebro humano tiene un área específica para el
lenguaje hablado, esta área relaciona conocimiento
con palabras. Se debe tomar ventaja de esto.
● Si una variable es no pronunciable entonces
cualquier discusión o explicación que involucre ese
nombre, sonará estúpida
“One difference between a smart programmer and a professional
programmer is that the professional understands that clarity is king.
Professionals use their powers for good and write code that others can
understand”

“La diferencia entre un programador inteligente y un


programador profesional es que este último sabe que
la claridad es lo que importa. Los profesionales usan
sus poderes para hacer el bien y escriben código que
otros pueden entender”

Robert C. Martin
Taller: Malos nombre de métodos

Orange getCustomer(int airplane) {} !!!

void parse(int command) {} ?


● Revisar el tipo que retorna

● Revisar el nombre del método

● Revisar parámetros
Fin de la primera sesión
SOLID
Principios fundamentales para la profesionalización del programador
Cada cambio en el código tiene consecuencias

SOLID previene consecuencias destructivas/inesperadas


- Contener las consecuencias en
una sola clase

SOLID - Separar intereses (área de


implicación y/o aplicación)
- Intereses comunes
Su buena aplicación logrará - Técnicas de separación (patrones)
- Manejo de cambios
- Previene problemas (Lo que
puede estar mal, estará mal)
SOLID - Distingue la forma de la sustancia
(¿estamos realmente solo
Objetivos ordenando espacios en blanco?)
Clean Code

DRY: Don’t Repeat Yourself

SOLID GRASP: General Responsibility


Assignment Software Principles
Los aliados TDD: Test Driven Development
SOLID ILODS
Moda, no pragmático Pragmático
I
Interface Segregation
Principle
Principio de
Segregación de Interfaces
La segregación nos indica que: Ninguna clase debe estar
obligada a implementar o
Las interfaces pueden ser divididas en grupos
dejar de implementar
de métodos. Cada grupo sirve a un grupo
diferente de clientes. Entonces algunos clientes métodos que no utilizará
usaran un grupo de métodos y otros usarán
diferentes grupos.
Robert C. Martin
L
Liskov Substitution
Principle
Principio de
LSP
Sustitución de Liskov Si se ve como un pato, suena como un pato,
pero necesita baterias… Probablemente
tenemos una mala abstracción
Si para cada objeto o1 de tipo S existe un objeto
o2 de tipo T tal que para todos los programas P Se debe apuntar o
definidos en términos de T, el comportamiento referenciar al tipo base
de P no cambia cuando o2 es substituido por
de cada elemento y la
o1; entonces S es un subtipo de T
substitución del mismo
Beneficio del LSP: por cualquier elemento
extendido no debe
Funciones que usan punteros o referencias a las afectar el funcionamiento
clases base, deben estar habilitadas para usar
clases derivadas sin conocerlas
del sistema

Barbara Liskov
Definición basica
Si S es un subtipo de T, entonces los objetos de tipo T en un programa pueden ser
reemplazados con objetos de tipo S sin alterar ninguna de las propiedades naturales de
un programa.

clientMethod(SomeClass sc) {

sc.someMethod();

}
Cuando es LSP

- Solo cuando las clases derivadas pueden sustituir


completamente a las clases base, y estas clases base pueden
ser utilizadas impunemente, a la vez que las clases derivadas
pueden cambiar impunemente
- Está alineado con el principio de Diseño por Contrato
- No viola el principio de Open/Closed
O
Open/Closed
Principle
Principio de
Apertura y cierre
OCP indica que nueva funcionalidad debe ser
agregada mediante nuevo código (clases,
métodos, o propiedades) en lugar de modificar
Los elementos de un
los elementos ya existentes y probados. Software (Clases,
La abstracción de los componentes y el uso de módulos, funciones)
polimorfismo (herencia e interfaces) es vital para deben ser Abiertos para
lograr cumplir con este principio.
la extensión y deben ser
Beneficios del OCP: Cerrados para ser
Modificados
1) Nuestro software será robusto porque no
modificamos las clases ya probadas..
2) Flexible porque fácilmente podemos Bertnard Meyer
acomodarnos a nuevos requerimientos.
3) Fácil de probar ya que los cambios son
atómicos (SRP).
● No debe violar SRP, LSP
OCP - Open

Abierto: Un módulo está abierto si es que está


disponible para ser extendido. Ejemplo: Se pueden
agregar campos a las estructuras de datos, o nuevos
elementos a las funciones que tiene.
OCP - Closed

Cerrado: Un módulo está cerrado si es que está


disponible para ser usado por otros módulos. Se
asume que el módulo ha sido dotado de un bien
definida y estable descripción. (Las interfaces son
un buen ejemplo)
OCP - Clase

Clase OCP: La clase es cerrada desde que fue construida,


almacenada en un a librería y es usada por clases cliente. Pero
está abierta ya que cualquier otra clase la puede utilizar como
base (padre) agregando nuevas características (Decorator),
cuando la nueva clase es implementada, no requiere cambiar la
original ni afectar a las clases usuario.
Ejemplo: Figuras geométricas

- Se cuenta con un software que calcula el área de un


rectángulo
- Se desea incorporar nueva funcionalidad para que calcule el
área de un círculo
- En el futuro se incluirán a un mas figuras.
- En un futuro aún más lejano se pretende utilizar el software
para calcular extensiones territoriales.
D
Dependency
Inversion Principle
Principio de
Invertir dependencias
Deberíamos soldar la lámpara
directamente a la toma de
corriente?
Módulos de nivel superior no deben depender
de modules de nivel inferior. Ambos deben Todo debe depender de
depender de abstracciones.
abstracciones
Abstracciones no deben depender de los
detalles, los detalles deben depender de
abstracciones.
Robert C. Martin
S
Single Responsibility
Principle
Principio de
Responsabilidad Simple
(atómica o unitaria)
"We have tried to demonstrate by these
examples that it is almost always incorrect to
begin the decomposition of a system into
modules on the basis of a flowchart. We propose
instead that one begins with a list of difficult
On the role of scientific
design decisions or design decisions which are thought
likely to change. Each module is then designed “The Separation of
to hide such a decision from the others"
Concerns”
Desacoplar módulos/lógica - al menos en
su mayoría - basados en la dinámico de su Parnas (1972)
naturaleza.
Agrupar y encapsular todo aquello que
cambia
SRP Principle

Cada módulo del software debería tener


una y simplemente una razón para cambiar
¿Qué es una razón
para cambiar?

Responsabilidad del programador

- Bugfix?
- Refactoring?

Responsabilidad del programa, razón de cambiar el programa ¿?


Análisis

La empresa X cuenta con los siguientes roles: Gerente general, Gerente de finanzas,
Gerente Recursos Humanos y Gerente de Tecnología.

Se cuenta con el siguiente módulo:

public class Employee {


public Money calculatePay();
public void save();
public String reportHours();
}
Taller: “The Duck Game”

Simulador de patos.

Este juego tiene como objetivo el de simular distintos tipos de patos y su


comportamiento.

La primera versión del juego cuenta con dos tipos de patos, pero la competencia es
cada vez mas fuerte así que DEBEMOS mejorar la experiencia del usuario.
La aplicación fue diseñada y
desarrollada inicialmente para que los
App 2: patos en el juego puedan nadar
(swin), emitir un sonido (quack) y
Juego simulador de acciones con puedan ser visibles
Patos
The Duck:
Diseño inicial
Los patos
deben volar
Solución inmediata. ¿Tengo un buen diseño?
The Duck:
Día del DEMO Bicho 1:

Los patos de plástico (Juguetes) no


deberían volar
Solución inmediata. ¿Tengo un buen diseño?
Opciones visibles
Interfaces

Catalogar quienes pueden volar y quienes pueden


hacer sonidos.

¿Efectos secundarios?
Herencia
Sobrescribir todos los
método necesarios.

¿Efectos secundarios?
Interfaces
Catalogar quienes pueden volar y quienes pueden
hacer sonidos.

¿Efectos secundarios?
Aplicación del principio
Aplicación del
principio
Aplicación del
principio

You might also like