From STUPI 

to SO   ID code

Carlos Arboleda

https://carlosarboleda.co

GDG Cali

🤪

💪

  • Co-Fundador & CTO LaManicurista
  • Co-Fundador & CTO MobileLab
  • Co-Organizador del GDG Cali
  • Android Developer
  • Backend Developer (Java/Node Js)

GDG Cali

Carlos Fernando Arboleda Garcés

Costo total

Desarrollo inicial

Mantenimiento

Entenderlo

Cambiarlo

Probarlo

Liberarlo

Esquema de costos de Kent Beck

El costo total del software

GDG Cali

Costo total

Desarrollo

Probarlo

Liberarlo

Esquema de costos de Kent Beck

Mantenimiento

Entenderlo

Cambiarlo

El costo total del software

GDG Cali

  • Singlet​on: Patrón singleton
  • Tight Coupling: Alto acoplamiento
  • Untestability: Código no testeable
  • Premature optimization: Optimizaciones prematuras
  • Indescriptive Naming: Nombres poco descriptivos
  • Duplication: Duplicidad de código

Code smell - Algo huele mal!

GDG Cali

class Singleton {
  public var title: String;
  
  private constructor() {
    this.title = "my singleton";
    Singleton.instance = this;
  }
  
  companion object {
    private var instance: Singleton? = null;
    
    fun getInstance(): Singleton {
      if (Singleton.instance == null) {
        Singleton.instance = Singleton();
      }
      
      return Singleton.instance!!;
    }
  }
}

val mySingleton1 = Singleton(); // Error
val mySingleton1 = Singleton.getInstance();
val mySingleton2 = Singleton.getInstance();

println("Singleton 1: " + mySingleton1.title);
mySingleton1.title = "modified in instance 1"
println("Singleton 2: " + mySingleton2.title);

Problemas

  1. Perdida de control
  2. Difícil de probar
  3. Múltiple responsabilidad

GDG Cali

El "patrón" Singleton

STUPID

Imagen de Refactoring Guru

GDG Cali

Alto acoplamiento

UserController

StatusController

Cohesión

Acoplamiento

NotificationsController

Problemas

  1. Reducción de portabilidad
  2. Difícil de leer
  3. Baja cohesión

STUPID

GDG Cali

Código no testeable

Problemas

  1. No se inyectan las dependencias
  2. Estado dependiente de factores externos
  3. Alto acoplamiento

STUPID

GDG Cali

Optimización prematura

Donald Knuth decía que la optimización prematura es la raíz de todos los males.

  • No anticiparse a los requisitos
    • Complejidad esencial
    • Complejidad accidental
  • No hay una bala de plata

STUPID

GDG Cali

Nombres poco descriptivos

STUPID

Nombre pronunciables
// Mal
val yyyymmdstr: String = sdf.format(new Date(), "YYYY/MM/DD");
// Mejor
val currentDate: String = sdf.format(new Date(), "YYYY/MM/DD");


Lexico coherente
// Mal
getUserInfo();
getClientData();
getCustomerRecord();
// Mejor
getUser();


Nombre para arrays
// Mal
val fruit = listOf("manzana", "platano", "fresa");
val fruitList = listOf("manzana", "platano", "fresa");
val fruits = listOf("manzana", "platano", "fresa");
// Bien
val fruitNames = listOf("manzana", "platano", "fresa");

Problemas

  1. Dificultad al leer el código
  2. Dificultad al comunicarse con el equipo
  3. Necesidad de adicionar comentarios

GDG Cali

Duplicidad de código

  • No repetir
    • Duplicidad real
    • Duplicidad accidental

STUPID

DRY - Don't repeat yourselft

fun showReport(reportData: Data) {
  val reportFormatted = """
      Name: ${reportData.name}
      Created at: ${reportData.createdAt}
      Purchases: ${reportData.purchases}
      Conversion Rate: ${reportData.conversionRate}%
      """
  println("Showing report $reportFormatted")
}

fun saveReport(reportData: Data) {
  val reportFormatted = """
      Name: ${reportData.name}
      Created at: ${reportData.createdAt}
      Purchases: ${reportData.purchases}
      Conversion Rate: ${reportData.conversionRate}%
      """
  println("Saving report... $reportFormatted")
}
  • Single Responsability: Responsabilidad única
  • Open/Close: Abierto/cerrado
  • Lskov Sustitution: Sustitición de Liskov
  • Interface Segration: Segregación de interfaces
  • Dependency Inversion: Inversión de dependencias

Principios SOLID

GDG Cali

Principios SOLID

GDG Cali

Clean Code Architecture

GDG Cali

SRP - Principio de responsabilidad única

SOLID

Detectar violaciones del SRP

  • Nombre demasiado genérico (God Object)
  • Los cambios suelen afectar a esta clase.

  • La clase involucra múltiples capas de la arquitectura.

  • Número alto de imports.

  • Cantidad elevada de métodos públicos.

  • Excesivo número de líneas de código.

Nunca debería haber más de un motivo por el cual cambiar una clase o un módulo. – Robert C. Martin

  • Una clase o módulo solo debe tener un motivo para cambiar
  • Única responsabilidad  Un solo método.

GDG Cali

OCP - Principio abierto/cerrado

Todas las entidades software deberían estar abiertas a extensión, pero cerradas a modificación. - Bertrand Meyer

SOLID

  • Abierto para extender la funcionalidad creando nuevas clases
  • Cerrado para modificación de la clase actual

Detectar violaciones del OCP

  • Si violamos el principio SRP
  • Los cambios suelen afectar a esta clase.
  • La clase involucra múltiples capas de la arquitectura.

GDG Cali

OCP - Principio abierto/cerrado

SOLID

class SMSSender {
  sendMessage(
    msg: String, providerName: String
  ) {
    swhitch(providerName) {
      case Provders.INFOBIP:
        sendMessageInfobip(msg);
      break;
      case Provders.HABLAME:
        sendMessageHablame(msg);
      break;
    }
  }
  
  fun sendMessageInfobip(msg: String) {
    // ...
  }
  
  fun sendMessageHablame(msg: String) {
    // ...
  }
}
class SMSSender {
  // ...
  fun sendMessage(
    msg: String, providerName: String
  ) {
    IProvider provider = providerFactory
    	.get(providerName);
    provider.sendMessage(msg);
  }
}

interface IProvider {
  fun sendMessage(msg: String);
}

class InfobipProvider : IProvider {
  fun sendMessage(msg: String) {
    // ...
  }
}

class HablameProvider : IProvider {
  fun sendMessage(msg: String) {
    // ...
  }
}

Mal

Bien

GDG Cali

LSP - Principio de sustitución de Liskov

Las funciones que utilicen punteros o referencias a clases base deben ser capaces de usar objetos de clases derivadas sin saberlo. - Robert C. Martin

  • Respetar el comportamiento de las clases padres en las clases hijas

SOLID

Detectar violaciones del LSP

  • Si cambiamos el comportamiento de un método heredado de la clase padre.
  • Si existe métodos sobre escritos y sin implementación.
  • Si los métodos sobre escritos lanzan excepciones no definidas en la clase padre

GDG Cali

LSP - Principio de sustitución de Liskov

SOLID

GDG Cali

LSP - Principio de sustitución de Liskov

SOLID

GDG Cali

ISP - Principio de segregación de interfaces

SOLID

Los clientes no deberían estar obligados a depender de interfaces que no utilicen. – Robert C. Martin

  • No se debe depender de lo que no se necesita

Detectar violaciones del ISP

  • Si violamos los principios SRP y LSP.
  • Si hay métodos sin implementación en las clases clientes

GDG Cali

ISP - Principio de segregación de interfaces

SOLID

interface ButtonListener {
  fun onClick(button: Button);
  fun onLongClick(button: Button);
}

class Screen1 : ButtonListener {
  fun onClick(button: Button) {
    // ...
  }
  
  fun onLongClick(button: Button) {
    throw new Exception("Unsupported operation");
  }
}

class Screen2 : ButtonListener {
  fun onClick(button: Button) {
    throw new Exception("Unsupported operation");
  }
  
  fun onLongClick(button: Button) {
    // ...
  }
}
interface ButtonClickListener {
  fun onClick(button: Button);
}

interface ButtonLongClickListener {
  fun onLongClick(button: Button);
}

class Screen1 : ButtonClickListener {
  fun onClick(button: Button) {
     // ...
  }
}

class Screen2 : ButtonLongClickListener {
  fun  onLongClick(button: Button) {
     // ...
  }
}

Mal

Bien

GDG Cali

DIP - Principio de inversión de dependencias

SOLID

Los módulos de alto nivel no deben depender de módulos de bajo nivel. Ambos deben depender de abstracciones. – Robert C. Martin

Detectar violaciones del ISP

  • Si violamos el principio OCP
  • Si dentro de las clases de dominio se instancian otras clases
  • Si hay dependencias con librerías de terceros
  • Si hay dependencias directas 

GDG Cali

DIP - Principio de inversión de dependencias

SOLID

SMSSender

InfobipApi

- infobipApi

+ sendMessage()

- sendMessageInfobip()

+ sendMessage

Mal

SMSSender

InfobipApi

IProvider

+ sendMessage

+ sendMessage

+ sendMessage

Bien

GDG Cali

Referencias

https://softwarecrafters.io

GDG Cali

Referencias

@cfarboleda

Made with Slides.com