<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sadel Fortunato</title>
    <description>The latest articles on Forem by Sadel Fortunato (@sadel_fortunato_00791b587).</description>
    <link>https://forem.com/sadel_fortunato_00791b587</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3547491%2F80691148-3914-41e0-ab63-fc1f7677cdfd.jpg</url>
      <title>Forem: Sadel Fortunato</title>
      <link>https://forem.com/sadel_fortunato_00791b587</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sadel_fortunato_00791b587"/>
    <language>en</language>
    <item>
      <title>Dia 8: 🧩 Abstract Factory Pattern en C#</title>
      <dc:creator>Sadel Fortunato</dc:creator>
      <pubDate>Fri, 24 Oct 2025 23:18:26 +0000</pubDate>
      <link>https://forem.com/sadel_fortunato_00791b587/dia-8-abstract-factory-pattern-en-c-1ln1</link>
      <guid>https://forem.com/sadel_fortunato_00791b587/dia-8-abstract-factory-pattern-en-c-1ln1</guid>
      <description>&lt;p&gt;¿QUÉ ES ABSTRACT FACTORY?&lt;br&gt;
Es un patron para construir familia de objetos relacionados, esto nos permite crear una interfaz completa con todos los componentes que necesitemos. No necesitamos especificar la clase concreta.&lt;/p&gt;

&lt;p&gt;Es un factory de factories&lt;/p&gt;

&lt;p&gt;Analogía del Restaurant&lt;br&gt;
Factory Method:&lt;br&gt;
Restaurant → Crea solo HAMBURGUESAS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hamburguesa clásica&lt;/li&gt;
&lt;li&gt;Hamburguesa vegetariana&lt;/li&gt;
&lt;li&gt;Hamburguesa premium
Abstract Factory:
Restaurant → Crea COMIDAS COMPLETAS&lt;/li&gt;
&lt;li&gt;Entrada + Plato Principal + Postre (Menú Italiano)&lt;/li&gt;
&lt;li&gt;Entrada + Plato Principal + Postre (Menú Mexicano)&lt;/li&gt;
&lt;li&gt;Entrada + Plato Principal + Postre (Menú Japonés)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FACTORY METHOD (Un producto)&lt;br&gt;
┌─────────────────────┐&lt;br&gt;
│  TransporteFactory  │&lt;br&gt;
└─────────────────────┘&lt;br&gt;
         │&lt;br&gt;
         ├─ Camión&lt;br&gt;
         ├─ Barco&lt;br&gt;
         └─ Avión&lt;/p&gt;

&lt;p&gt;ABSTRACT FACTORY (Familia de productos)&lt;br&gt;
┌─────────────────────┐&lt;br&gt;
│   UIFactory         │&lt;br&gt;
└─────────────────────┘&lt;br&gt;
         │&lt;br&gt;
         ├─ WindowsFactory&lt;br&gt;
         │   ├─ Button&lt;br&gt;
         │   ├─ Window&lt;br&gt;
         │   └─ Checkbox&lt;br&gt;
         │&lt;br&gt;
         ├─ MacFactory&lt;br&gt;
         │   ├─ Button&lt;br&gt;
         │   ├─ Window&lt;br&gt;
         │   └─ Checkbox&lt;br&gt;
         │&lt;br&gt;
         └─ LinuxFactory&lt;br&gt;
             ├─ Button&lt;br&gt;
             ├─ Window&lt;br&gt;
             └─ Checkbox&lt;/p&gt;

&lt;p&gt;ESTRUCTURA DEL PATRÓN&lt;br&gt;
Componentes:&lt;/p&gt;

&lt;p&gt;AbstractFactory - Interfaz para crear familias de productos&lt;br&gt;
ConcreteFactory - Implementación específica (ej: WindowsFactory)&lt;br&gt;
AbstractProduct - Interfaz para un tipo de producto (ej: IButton)&lt;br&gt;
ConcreteProduct - Implementación específica (ej: WindowsButton)&lt;br&gt;
Client - Usa solo abstracciones, no clases concretas&lt;/p&gt;

&lt;p&gt;Paso 1: Definir AbstractProducts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;csharp// Productos abstractos (interfaces)
public interface IButton
{
    void Render();
    void Click();
}

public interface IWindow
{
    void Open();
    void Close();
    void Maximize();
}

public interface ICheckbox
{
    void Render();
    void Check();
    void Uncheck();
}

Paso 2: Crear ConcreteProducts para cada familia
csharp// ========== FAMILIA WINDOWS ==========
public class WindowsButton : IButton
{
    public void Render()
    {
        Console.WriteLine(" Renderizando botón estilo Windows");
    }

    public void Click()
    {
        Console.WriteLine(" Click en botón Windows");
    }
}

public class WindowsWindow : IWindow
{
    public void Open()
    {
        Console.WriteLine("🪟 Abriendo ventana Windows");
    }

    public void Close()
    {
        Console.WriteLine(" Cerrando ventana Windows");
    }

    public void Maximize()
    {
        Console.WriteLine(" Maximizando ventana Windows");
    }
}

public class WindowsCheckbox : ICheckbox
{
    public void Render()
    {
        Console.WriteLine(" Renderizando checkbox Windows");
    }

    public void Check()
    {
        Console.WriteLine(" Checkbox marcado");
    }

    public void Uncheck()
    {
        Console.WriteLine(" Checkbox desmarcado");
    }
}

// ========== FAMILIA MAC ==========
public class MacButton : IButton
{
    public void Render()
    {
        Console.WriteLine(" Renderizando botón estilo Mac");
    }

    public void Click()
    {
        Console.WriteLine(" Click en botón Mac");
    }
}

public class MacWindow : IWindow
{
    public void Open()
    {
        Console.WriteLine("🪟 Abriendo ventana Mac");
    }

    public void Close()
    {
        Console.WriteLine(" Cerrando ventana Mac");
    }

    public void Maximize()
    {
        Console.WriteLine(" Maximizando ventana Mac");
    }
}

public class MacCheckbox : ICheckbox
{
    public void Render()
    {
        Console.WriteLine(" Renderizando checkbox Mac");
    }

    public void Check()
    {
        Console.WriteLine(" Checkbox marcado (estilo Mac)");
    }

    public void Uncheck()
    {
        Console.WriteLine(" Checkbox desmarcado (estilo Mac)");
    }
}

Paso 3: Definir AbstractFactory
csharp// Factory abstracta
public interface IUIFactory
{
    IButton CreateButton();
    IWindow CreateWindow();
    ICheckbox CreateCheckbox();
}
Paso 4: Crear ConcreteFactories
csharp// Factory concreta para Windows
public class WindowsFactory : IUIFactory
{
    public IButton CreateButton()
    {
        return new WindowsButton();
    }

    public IWindow CreateWindow()
    {
        return new WindowsWindow();
    }

    public ICheckbox CreateCheckbox()
    {
        return new WindowsCheckbox();
    }
}

// Factory concreta para Mac
public class MacFactory : IUIFactory
{
    public IButton CreateButton()
    {
        return new MacButton();
    }

    public IWindow CreateWindow()
    {
        return new MacWindow();
    }

    public ICheckbox CreateCheckbox()
    {
        return new MacCheckbox();
    }
}

// Factory concreta para Linux
public class LinuxFactory : IUIFactory
{
    public IButton CreateButton()
    {
        return new LinuxButton();
    }

    public IWindow CreateWindow()
    {
        return new LinuxWindow();
    }

    public ICheckbox CreateCheckbox()
    {
        return new LinuxCheckbox();
    }
}
Paso 5: Cliente que usa la Factory
csharppublic class Aplicacion
{
    private IButton _button;
    private IWindow _window;
    private ICheckbox _checkbox;

    //  Cliente recibe factory, no sabe qué plataforma es
    public Aplicacion(IUIFactory factory)
    {
        _button = factory.CreateButton();
        _window = factory.CreateWindow();
        _checkbox = factory.CreateCheckbox();
    }

    public void Ejecutar()
    {
        _window.Open();
        _button.Render();
        _button.Click();
        _checkbox.Render();
        _checkbox.Check();
        _window.Maximize();
    }
}

// Uso
var platform = DetectarPlataforma(); // "Windows", "Mac", "Linux"

IUIFactory factory = platform switch
{
    "Windows" =&amp;gt; new WindowsFactory(),
    "Mac" =&amp;gt; new MacFactory(),
    "Linux" =&amp;gt; new LinuxFactory(),
    _ =&amp;gt; throw new PlatformNotSupportedException()
};

var app = new Aplicacion(factory);
app.Ejecutar();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PARTE 7: CUÁNDO USAR ABSTRACT FACTORY&lt;br&gt;
 Usa Abstract Factory cuando:&lt;/p&gt;

&lt;p&gt;Necesitas familias de objetos relacionados&lt;/p&gt;

&lt;p&gt;UI: Botón + Ventana + Menú para cada plataforma&lt;br&gt;
Temas: Colores + Fuentes + Iconos para cada tema&lt;/p&gt;

&lt;p&gt;Los objetos deben ser compatibles entre sí&lt;/p&gt;

&lt;p&gt;No puedes mezclar botón de Windows con ventana de Mac&lt;br&gt;
Todos deben ser de la misma familia&lt;/p&gt;

&lt;p&gt;Quieres ocultar las implementaciones concretas&lt;/p&gt;

&lt;p&gt;Cliente solo ve interfaces&lt;br&gt;
No conoce las clases concretas&lt;/p&gt;

&lt;p&gt;Quieres cambiar toda la familia fácilmente&lt;/p&gt;

&lt;p&gt;De tema claro a oscuro&lt;br&gt;
De MySQL a PostgreSQL&lt;/p&gt;

&lt;p&gt;Tienes múltiples variantes de múltiples productos&lt;/p&gt;

&lt;p&gt;3 plataformas × 5 componentes = 15 clases&lt;br&gt;
Necesitas organización&lt;/p&gt;

&lt;p&gt;NO uses Abstract Factory cuando:&lt;/p&gt;

&lt;p&gt;Solo tienes un tipo de producto&lt;/p&gt;

&lt;p&gt;Usa Factory Method&lt;/p&gt;

&lt;p&gt;Las familias no son compatibles entre sí&lt;/p&gt;

&lt;p&gt;Los objetos son independientes&lt;/p&gt;

&lt;p&gt;No hay variaciones de familias&lt;/p&gt;

&lt;p&gt;Solo una plataforma, un tema, etc.&lt;/p&gt;

&lt;p&gt;Agregarás nuevos productos frecuentemente&lt;/p&gt;

&lt;p&gt;Modificarás la interfaz abstracta constantemente&lt;/p&gt;

&lt;p&gt;PARTE 8: VENTAJAS Y DESVENTAJAS&lt;br&gt;
 Ventajas:&lt;/p&gt;

&lt;p&gt;Garantiza compatibilidad&lt;/p&gt;

&lt;p&gt;Todos los productos son de la misma familia&lt;/p&gt;

&lt;p&gt;Aislamiento de clases concretas&lt;/p&gt;

&lt;p&gt;Cliente usa interfaces&lt;/p&gt;

&lt;p&gt;Fácil cambiar familias&lt;/p&gt;

&lt;p&gt;Solo cambias el factory&lt;/p&gt;

&lt;p&gt;Single Responsibility&lt;/p&gt;

&lt;p&gt;Creación centralizada&lt;/p&gt;

&lt;p&gt;Open/Closed&lt;/p&gt;

&lt;p&gt;Nuevas familias sin modificar cliente&lt;/p&gt;

&lt;p&gt;Desventajas:&lt;/p&gt;

&lt;p&gt;Complejidad&lt;/p&gt;

&lt;p&gt;Muchas interfaces y clases&lt;/p&gt;

&lt;p&gt;Difícil agregar nuevos productos&lt;/p&gt;

&lt;p&gt;Debes modificar la interfaz AbstractFactory&lt;br&gt;
Todas las factories concretas&lt;/p&gt;

&lt;p&gt;Rigidez&lt;/p&gt;

&lt;p&gt;La estructura está definida desde el inicio&lt;/p&gt;

&lt;p&gt;Overkill para casos simples&lt;/p&gt;

&lt;p&gt;Factory Method puede ser suficiente&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>designpatterns</category>
      <category>architecture</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Dia 7: 🧩 Factory Method Pattern en C#</title>
      <dc:creator>Sadel Fortunato</dc:creator>
      <pubDate>Wed, 15 Oct 2025 09:59:49 +0000</pubDate>
      <link>https://forem.com/sadel_fortunato_00791b587/dia-7-factory-method-pattern-en-c-3dd7</link>
      <guid>https://forem.com/sadel_fortunato_00791b587/dia-7-factory-method-pattern-en-c-3dd7</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Patrón Factory Method&lt;/strong&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Definición&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;El &lt;strong&gt;Factory Method&lt;/strong&gt; es un patrón de diseño creacional que permite &lt;strong&gt;crear objetos sin conocer su clase concreta&lt;/strong&gt;. En lugar de instanciar directamente un objeto con &lt;code&gt;new&lt;/code&gt;, el patrón delega la responsabilidad de creación a un método especializado (el &lt;em&gt;factory&lt;/em&gt;), el cual decide qué tipo de objeto instanciar según el contexto o las necesidades del cliente.&lt;/p&gt;

&lt;p&gt;En otras palabras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;En vez de crear objetos directamente (&lt;code&gt;new MiClase()&lt;/code&gt;), se utiliza un método &lt;em&gt;factory&lt;/em&gt; que se encarga de devolver la instancia apropiada.&lt;/li&gt;
&lt;li&gt;La lógica de creación queda centralizada y desacoplada del código cliente.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;El Problema que Resuelve&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Código acoplado:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// El cliente decide qué crear&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tipo&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"perro"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;animal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Perro&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tipo&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"gato"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;animal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Gato&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Código repetido en muchos lugares&lt;/span&gt;
&lt;span class="c1"&gt;// Difícil de mantener y extender&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este enfoque, la lógica de creación está dispersa en distintas partes del sistema. Si se desea agregar un nuevo tipo o cambiar la forma en que se crean los objetos, será necesario modificar el código en múltiples lugares.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solución con Factory Method:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// La fábrica decide qué crear&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;animal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AnimalFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Crear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Lógica de creación centralizada&lt;/span&gt;
&lt;span class="c1"&gt;// Fácil de mantener y extender&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Estructura del Patrón&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Componentes Principales
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Product (Producto):&lt;/strong&gt; Define la interfaz común para todos los objetos que la fábrica puede crear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteProduct (Producto Concreto):&lt;/strong&gt; Implementaciones específicas del producto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creator (Creador):&lt;/strong&gt; Declara el método fábrica que devolverá objetos del tipo producto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteCreator (Creador Concreto):&lt;/strong&gt; Implementa el método fábrica y determina qué producto concreto instanciar.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ejemplo Práctico
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Interfaz común (Product):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;INotificacion&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;mensaje&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Productos concretos:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificacionEmail&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INotificacion&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;mensaje&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Email enviado: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mensaje&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificacionSMS&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INotificacion&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;mensaje&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"SMS enviado: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mensaje&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificacionPush&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INotificacion&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;mensaje&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Push enviado: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mensaje&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Clase Factory:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificacionFactory&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;INotificacion&lt;/span&gt; &lt;span class="nf"&gt;Crear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificacionEmail&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s"&gt;"sms"&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificacionSMS&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s"&gt;"push"&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificacionPush&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Tipo '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' no soportado"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Uso del patrón:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;notificacionEmail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NotificacionFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Crear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;notificacionEmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"¡Hola Mundo!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;notificacionSMS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NotificacionFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Crear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sms"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;notificacionSMS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"¡Hola por SMS!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con este enfoque, el cliente no conoce las clases concretas de las notificaciones, sino que simplemente solicita al &lt;em&gt;factory&lt;/em&gt; el tipo que necesita.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Cuándo Usar Factory Method&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Úsalo cuando:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No sabes de antemano qué tipo exacto de objeto necesitas crear.&lt;/li&gt;
&lt;li&gt;La decisión depende de una configuración, entrada del usuario o datos externos.&lt;/li&gt;
&lt;li&gt;Deseas &lt;strong&gt;centralizar la lógica de creación&lt;/strong&gt; y evitar código duplicado.&lt;/li&gt;
&lt;li&gt;La creación de los objetos es &lt;strong&gt;compleja&lt;/strong&gt; (requiere validaciones, configuraciones o inicializaciones).&lt;/li&gt;
&lt;li&gt;Quieres &lt;strong&gt;desacoplar&lt;/strong&gt; el cliente de las clases concretas y cumplir con el principio &lt;strong&gt;OCP (Open/Closed)&lt;/strong&gt;, agregando nuevos tipos sin modificar el código existente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;No lo uses cuando:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;La creación del objeto es simple (un &lt;code&gt;new MiClase()&lt;/code&gt; es suficiente).&lt;/li&gt;
&lt;li&gt;Solo existe un tipo de objeto posible.&lt;/li&gt;
&lt;li&gt;El tipo no cambiará y no hay lógica condicional en su creación.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusión&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;El &lt;strong&gt;Factory Method&lt;/strong&gt; es un patrón muy útil para &lt;strong&gt;desacoplar la creación de objetos&lt;/strong&gt; y &lt;strong&gt;centralizar la lógica de instanciación&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Al aplicarlo, se cumplen varios principios &lt;strong&gt;SOLID&lt;/strong&gt;, especialmente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Responsibility (SRP):&lt;/strong&gt; La creación de objetos se delega a una clase especializada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open/Closed (OCP):&lt;/strong&gt; Se pueden agregar nuevos tipos sin modificar el código existente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Inversion (DIP):&lt;/strong&gt; Las dependencias se manejan a través de abstracciones y no de implementaciones concretas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En resumen, este patrón proporciona una forma flexible, escalable y mantenible de crear objetos, permitiendo que el sistema evolucione sin afectar su estabilidad.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>designpatterns</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Dia 6: 🧩 Principio de Inversión de Dependencias (DIP) en C#</title>
      <dc:creator>Sadel Fortunato</dc:creator>
      <pubDate>Tue, 14 Oct 2025 04:00:37 +0000</pubDate>
      <link>https://forem.com/sadel_fortunato_00791b587/dia-6-principio-de-inversion-de-dependencias-dip-en-c-5704</link>
      <guid>https://forem.com/sadel_fortunato_00791b587/dia-6-principio-de-inversion-de-dependencias-dip-en-c-5704</guid>
      <description>&lt;p&gt;Principio de Inversión de Dependencias (DIP)&lt;br&gt;
Definición&lt;/p&gt;

&lt;p&gt;El Principio de Inversión de Dependencias establece que:&lt;/p&gt;

&lt;p&gt;“Los módulos de alto nivel no deben depender de módulos de bajo nivel. Ambos deben depender de abstracciones.”&lt;br&gt;
“Las abstracciones no deben depender de los detalles. Los detalles deben depender de las abstracciones.”&lt;br&gt;
— Robert C. Martin (Uncle Bob)&lt;/p&gt;

&lt;p&gt;En términos simples:&lt;/p&gt;

&lt;p&gt;No dependas de clases concretas.&lt;/p&gt;

&lt;p&gt;Depende de interfaces o abstracciones.&lt;/p&gt;

&lt;p&gt;Inyecta las dependencias desde afuera.&lt;/p&gt;

&lt;p&gt;Invierte la dirección de las dependencias.&lt;/p&gt;

&lt;p&gt;Analogía del Enchufe&lt;br&gt;
Sin el Principio (acoplamiento directo)&lt;/p&gt;

&lt;p&gt;Imagina una laptop cuyo cable de corriente está soldado internamente:&lt;/p&gt;

&lt;p&gt;Si el cable se daña, debe reemplazarse toda la laptop.&lt;/p&gt;

&lt;p&gt;No permite usar diferentes voltajes.&lt;/p&gt;

&lt;p&gt;Es difícil de adaptar para otros países.&lt;/p&gt;

&lt;p&gt;Con el Principio (desacoplamiento)&lt;/p&gt;

&lt;p&gt;Ahora imagina una laptop con un puerto estándar:&lt;/p&gt;

&lt;p&gt;Permite conectar diferentes cables.&lt;/p&gt;

&lt;p&gt;Cambiar el cable no afecta a la laptop.&lt;/p&gt;

&lt;p&gt;Puede funcionar en cualquier país usando un adaptador adecuado.&lt;/p&gt;

&lt;p&gt;Conclusión:&lt;br&gt;
El puerto representa la abstracción y los cables son las implementaciones. La laptop no depende de un cable específico, sino de un estándar.&lt;/p&gt;

&lt;p&gt;El Problema: Dependencia Directa&lt;br&gt;
Ejemplo&lt;br&gt;
// Clase de bajo nivel (detalle concreto)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class EmailService
{
    public void EnviarEmail(string mensaje)
    {
        Console.WriteLine($"Enviando email: {mensaje}");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;// Clase de alto nivel dependiente de una clase concreta&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class NotificacionService
{
    private EmailService _emailService = new EmailService();

    public void Notificar(string mensaje)
    {
        _emailService.EnviarEmail(mensaje);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;// Uso del sistema&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var notificador = new NotificacionService();
notificador.Notificar("Hola mundo"); // Solo puede enviar emails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problemas&lt;/p&gt;

&lt;p&gt;Acoplamiento fuerte: NotificacionService depende directamente de EmailService.&lt;/p&gt;

&lt;p&gt;Difícil de extender: No puede usarse SMS u otro canal sin modificar la clase.&lt;/p&gt;

&lt;p&gt;Difícil de testear: No se pueden simular dependencias fácilmente.&lt;/p&gt;

&lt;p&gt;Viola el Principio Abierto/Cerrado: No está cerrada a modificaciones.&lt;/p&gt;

&lt;p&gt;La Solución: Inversión de Dependencias&lt;br&gt;
Paso 1: Crear una Abstracción&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface INotificacion
{
    void Enviar(string mensaje);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paso 2: Implementar las Clases Concretas&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class EmailService : INotificacion
{
    public void Enviar(string mensaje)
    {
        Console.WriteLine($"Email enviado: {mensaje}");
    }
}

public class SMSService : INotificacion
{
    public void Enviar(string mensaje)
    {
        Console.WriteLine($"SMS enviado: {mensaje}");
    }
}

public class WhatsAppService : INotificacion
{
    public void Enviar(string mensaje)
    {
        Console.WriteLine($"WhatsApp enviado: {mensaje}");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paso 3: Inyectar la Dependencia&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class NotificacionService
{
    private readonly INotificacion _canal;

    // Inyección de dependencia por constructor
    public NotificacionService(INotificacion canal)
    {
        _canal = canal;
    }

    public void Notificar(string mensaje)
    {
        _canal.Enviar(mensaje);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paso 4: Uso del Sistema&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var notificadorEmail = new NotificacionService(new EmailService());
notificadorEmail.Notificar("Hola por Email");

var notificadorSMS = new NotificacionService(new SMSService());
notificadorSMS.Notificar("Hola por SMS");

var notificadorWhatsApp = new NotificacionService(new WhatsAppService());
notificadorWhatsApp.Notificar("Hola por WhatsApp");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ventaja principal:&lt;br&gt;
El comportamiento puede cambiarse sin modificar la clase NotificacionService. Solo se inyecta una nueva implementación de la interfaz.&lt;/p&gt;

&lt;p&gt;Tipos de Inyección de Dependencias&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inyección por Constructor (recomendada)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ServicioUsuario
{
    private readonly IRepositorio _repositorio;

    public ServicioUsuario(IRepositorio repositorio)
    {
        _repositorio = repositorio ?? throw new ArgumentNullException();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ventajas:&lt;/p&gt;

&lt;p&gt;Las dependencias son obligatorias desde la creación del objeto.&lt;/p&gt;

&lt;p&gt;Las propiedades pueden mantenerse inmutables (readonly).&lt;/p&gt;

&lt;p&gt;Facilita la realización de pruebas unitarias (mocking).&lt;/p&gt;

&lt;p&gt;Mejora la claridad del código al mostrar explícitamente qué necesita la clase.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>cleancode</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Dia 5: 🧩 Principio de Segregación de Interfaces (ISP) en C#</title>
      <dc:creator>Sadel Fortunato</dc:creator>
      <pubDate>Mon, 13 Oct 2025 03:24:18 +0000</pubDate>
      <link>https://forem.com/sadel_fortunato_00791b587/dia-5-principio-de-segregacion-de-interfaces-isp-en-c-41f1</link>
      <guid>https://forem.com/sadel_fortunato_00791b587/dia-5-principio-de-segregacion-de-interfaces-isp-en-c-41f1</guid>
      <description>&lt;h2&gt;
  
  
  Principio de Segregación de Interfaces (ISP)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué dice este principio?
&lt;/h3&gt;

&lt;p&gt;El &lt;strong&gt;Principio de Segregación de Interfaces (ISP)&lt;/strong&gt; establece que &lt;strong&gt;los clientes no deben estar obligados a depender de servicios que no utilizan&lt;/strong&gt;.&lt;br&gt;
En otras palabras, se debe dividir la funcionalidad en &lt;strong&gt;interfaces más específicas y coherentes&lt;/strong&gt;, de modo que cada cliente solo implemente o utilice los métodos que realmente necesita.&lt;/p&gt;


&lt;h3&gt;
  
  
  ¿En qué nos beneficia?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Creamos &lt;strong&gt;interfaces más específicas&lt;/strong&gt; y fáciles de entender.&lt;/li&gt;
&lt;li&gt;Evitamos que los clientes trabajen con &lt;strong&gt;recursos innecesarios&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Probamos únicamente lo necesario&lt;/strong&gt;, reduciendo complejidad en los tests.&lt;/li&gt;
&lt;li&gt;Ganamos &lt;strong&gt;flexibilidad y capacidad de reutilización&lt;/strong&gt; de métodos y componentes.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  ¿Qué problemas causa no aplicarlo?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Los clientes deben &lt;strong&gt;manejar o condicionar métodos que no usan&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Se crean &lt;strong&gt;controles innecesarios&lt;/strong&gt; dentro del código.&lt;/li&gt;
&lt;li&gt;Aumenta la cantidad de &lt;strong&gt;código repetido o sin propósito claro&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Se genera una &lt;strong&gt;interfaz demasiado grande y poco coherente&lt;/strong&gt;, difícil de mantener.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Analogía: el restaurante
&lt;/h3&gt;

&lt;p&gt;Imagina un restaurante donde &lt;strong&gt;un solo empleado&lt;/strong&gt; debe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cocinar&lt;/li&gt;
&lt;li&gt;Limpiar&lt;/li&gt;
&lt;li&gt;Atender a los clientes&lt;/li&gt;
&lt;li&gt;Servir las mesas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto genera problemas evidentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El chef no debería hacer entregas a domicilio.&lt;/li&gt;
&lt;li&gt;El mesero no debería cocinar.&lt;/li&gt;
&lt;li&gt;El cajero no necesita lavar platos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solución:&lt;/strong&gt;&lt;br&gt;
Dividir las responsabilidades según el rol de cada empleado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ICocinero&lt;/code&gt; para cocinar&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IConserje&lt;/code&gt; para limpiar&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ICajero&lt;/code&gt; para cobrar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;De esta forma, cada persona cumple su función sin verse obligada a realizar tareas innecesarias. Incluso podríamos tener un empleado multifuncional, como un aguatero que además pueda cobrar, simplemente implementando ambas interfaces según sea necesario.&lt;/p&gt;


&lt;h3&gt;
  
  
  El problema clásico: la impresora
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Escenario:&lt;/strong&gt;&lt;br&gt;
En una oficina existen distintos dispositivos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Una impresora simple (solo imprime)&lt;/li&gt;
&lt;li&gt;Una impresora multifuncional (imprime, escanea y envía fax)&lt;/li&gt;
&lt;li&gt;Una máquina de fax (solo envía fax)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Ejemplo incorrecto:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//  Interfaz demasiado grande: obliga a implementar todo&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IDispositivoOficina&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Imprimir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Escanear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EnviarFax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fotocopiar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//  ImpresoraSimple se ve OBLIGADA a implementar métodos que no usa&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImpresoraSimple&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDispositivoOficina&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Imprimir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Imprimiendo: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Implementaciones innecesarias o con errores&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Escanear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotSupportedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Esta impresora no escanea"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EnviarFax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotSupportedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Esta impresora no tiene fax"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fotocopiar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotSupportedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Esta impresora no fotocopia"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//  El cliente que solo necesita imprimir depende de toda la interfaz&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServicioImpresion&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IDispositivoOficina&lt;/span&gt; &lt;span class="n"&gt;_dispositivo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ServicioImpresion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDispositivoOficina&lt;/span&gt; &lt;span class="n"&gt;dispositivo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_dispositivo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dispositivo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ImprimirDocumento&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_dispositivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Imprimir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  ¿Por qué esto está mal?
&lt;/h4&gt;

&lt;p&gt;Solemos crear clases que abarcan más de lo necesario, pensando en cubrir todas las posibles funcionalidades desde el inicio. Sin embargo, cuando otros clientes tienen necesidades similares pero no idénticas, terminamos forzando implementaciones innecesarias o poco limpias para poder cumplir con el contrato.&lt;/p&gt;

&lt;p&gt;Problemas principales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La clase &lt;strong&gt;ImpresoraSimple&lt;/strong&gt; implementa métodos que no necesita.&lt;/li&gt;
&lt;li&gt;El cliente depende de métodos que &lt;strong&gt;nunca utilizará&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Se genera &lt;strong&gt;código frágil&lt;/strong&gt;, con excepciones innecesarias.&lt;/li&gt;
&lt;li&gt;Es &lt;strong&gt;difícil de mantener y extender&lt;/strong&gt; en el tiempo.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Solución correcta
&lt;/h3&gt;

&lt;p&gt;La solución es &lt;strong&gt;dividir la interfaz en varias más pequeñas y específicas&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IImpresora&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Imprimir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IEsc&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;ner&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Escanear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IFax&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EnviarFax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IFotocopiadora&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fotocopiar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//  Cada clase implementa solo lo que necesita&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImpresoraSimple&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IImpresora&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Imprimir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Imprimiendo: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImpresoraMultifuncional&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IImpresora&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IEsc&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;ner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IFax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IFotocopiadora&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Imprimir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Imprimiendo: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Escanear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Escaneando: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EnviarFax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Enviando fax: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fotocopiar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Fotocopiando: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;documento&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora cada cliente utiliza únicamente la interfaz que necesita, y el código es más claro, mantenible y escalable.&lt;/p&gt;




&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;El &lt;strong&gt;Principio de Segregación de Interfaces&lt;/strong&gt; es una herramienta poderosa para mantener un código limpio, modular y adaptable.&lt;br&gt;
Permite &lt;strong&gt;organizar mejor las implementaciones&lt;/strong&gt;, evitando dependencias innecesarias y mejorando la &lt;strong&gt;reutilización&lt;/strong&gt; de componentes.&lt;/p&gt;

&lt;p&gt;Aunque su impacto puede parecer mínimo en proyectos pequeños, en sistemas grandes y complejos su aplicación marca una diferencia significativa, haciendo el código &lt;strong&gt;más estable, flexible y fácil de evolucionar&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>Dia 4: 🧩 Principio de Sustitución de Liskov (LSP) en C#</title>
      <dc:creator>Sadel Fortunato</dc:creator>
      <pubDate>Sat, 11 Oct 2025 23:11:00 +0000</pubDate>
      <link>https://forem.com/sadel_fortunato_00791b587/dia-4-principio-de-sustitucion-de-liskov-lsp-en-c-16n4</link>
      <guid>https://forem.com/sadel_fortunato_00791b587/dia-4-principio-de-sustitucion-de-liskov-lsp-en-c-16n4</guid>
      <description>&lt;p&gt;Principio de Sustitución de Liskov (LSP)&lt;br&gt;
¿Qué explica este principio?&lt;/p&gt;

&lt;p&gt;El Principio de Sustitución de Liskov establece que una subclase debe poder reemplazar a su clase base sin afectar el correcto funcionamiento del programa.&lt;/p&gt;

&lt;p&gt;En otras palabras:&lt;br&gt;
Si tienes una clase llamada Ave y creas una subclase Pato, esta última debe poder ser utilizada en cualquier lugar donde se espere una Ave, sin alterar el comportamiento esperado del sistema.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Esto significa que las subclases deben cumplir con el contrato definido por la clase base.&lt;/li&gt;
&lt;li&gt;Las condiciones previas no deben hacerse más estrictas.&lt;/li&gt;
&lt;li&gt;Las condiciones posteriores no deben debilitarse.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Qué beneficios obtenemos al aplicarlo?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se logra un verdadero polimorfismo: las subclases pueden comportarse como la clase base sin problemas.&lt;/li&gt;
&lt;li&gt;El código se vuelve más fácil de probar y mantener.&lt;/li&gt;
&lt;li&gt;El desarrollo es más predecible y coherente respecto al contrato de la clase base.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Programación vs Matemáticas&lt;/p&gt;

&lt;p&gt;Un ejemplo sencillo pero fundamental para comprender este principio es el caso del cuadrado y el rectángulo.&lt;/p&gt;

&lt;p&gt;Ambas figuras comparten ciertos requisitos: tienen cuatro lados. Sin embargo, no cumplen las mismas condiciones geométricas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Un cuadrado requiere cuatro lados iguales.&lt;/li&gt;
&lt;li&gt;Un rectángulo necesita lados con diferente anchura y altura.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En la práctica, no es correcto heredar Square de Rectangle, porque estaríamos forzando comportamientos que rompen las reglas de una u otra figura. Si lo hacemos, estaremos sobrecargando la clase base y rompiendo el principio de Liskov.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Clase base: Rectángulo
public class Rectangle
{
    public virtual int Width { get; set; }
    public virtual int Height { get; set; }

    public int CalculateArea()
    {
        return Width * Height;
    }
}

// VIOLACIÓN LSP: Cuadrado hereda de Rectángulo
public class Square : Rectangle
{
    private int _side;

    public override int Width
    {
        get =&amp;gt; _side;
        set =&amp;gt; _side = value;
    }

    public override int Height
    {
        get =&amp;gt; _side;
        set =&amp;gt; _side = value;
    }
}

// PROBLEMA: Este código FALLA
public void TestRectangle(Rectangle rect)
{
    rect.Width = 5;
    rect.Height = 10;

    // Esperamos: 5 * 10 = 50
    // Con Rectangle: 50
    // Con Square: 100 (ambos lados cambian al último valor: 10)

    Console.WriteLine($"Área: {rect.CalculateArea()}");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problemas detectados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No deberíamos heredar de una clase que ya cumple una función solo porque parece “similar”.&lt;/li&gt;
&lt;li&gt;Tenemos que manipular propiedades para intentar obtener un resultado esperado.&lt;/li&gt;
&lt;li&gt;El cuadrado no puede adaptarse correctamente al comportamiento del rectángulo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Solución correcta&lt;/p&gt;

&lt;p&gt;En lugar de forzar una relación de herencia, debemos usar una interfaz común que defina el contrato general para todas las figuras:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Interfaz común
public interface IShape
{
    int CalculateArea();
    string GetDescription();
}

// Rectángulo implementa IShape
public class Rectangle : IShape
{
    public int Width { get; set; }
    public int Height { get; set; }

    public int CalculateArea() =&amp;gt; Width * Height;
    public string GetDescription() =&amp;gt; $"Rectángulo: {Width}x{Height}";
}

// Cuadrado implementa IShape (NO hereda de Rectangle)
public class Square : IShape
{
    public int Side { get; set; }

    public int CalculateArea() =&amp;gt; Side * Side;
    public string GetDescription() =&amp;gt; $"Cuadrado: {Side}x{Side}";
}

// FUNCIONA: Ambos son IShape pero sin herencia problemática
public void ProcessShape(IShape shape)
{
    Console.WriteLine(shape.GetDescription());
    Console.WriteLine($"Área: {shape.CalculateArea()}");
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Qué logramos?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Una interfaz flexible ante nuevos requerimientos.&lt;/li&gt;
&lt;li&gt;Se aplica el principio de responsabilidad única (SRP): cada clase representa correctamente su figura.&lt;/li&gt;
&lt;li&gt;La interfaz IShape está abierta a la extensión y cerrada a la modificación, cumpliendo también con el principio Open/Closed.&lt;/li&gt;
&lt;li&gt;Fácil de probar y extender con nuevas figuras en el futuro.&lt;/li&gt;
&lt;li&gt;No fortalecemos condiciones previas ni debilitamos las posteriores: mantenemos un contrato coherente y estable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conclusión&lt;/p&gt;

&lt;p&gt;El Principio de Sustitución de Liskov es esencial cuando se crean variantes de un objeto con comportamientos o reglas diferentes, pero que comparten un mismo propósito general.&lt;/p&gt;

&lt;p&gt;Por ejemplo, en un sistema de reportes, las operaciones de guardar, leer y exportar son comunes. Si queremos exportar diferentes tipos de documentos, lo ideal es definir una interfaz con estas funcionalidades y luego crear implementaciones específicas para cada tipo de reporte.&lt;/p&gt;

&lt;p&gt;Así logramos un diseño extensible, predecible y fácil de mantener, evitando la fragilidad de las herencias mal aplicadas y garantizando un verdadero polimorfismo.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>spanish</category>
      <category>csharp</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Dia 3: 🧩 Principio Abierto/Cerrado (Open/Closed Principle) en C#</title>
      <dc:creator>Sadel Fortunato</dc:creator>
      <pubDate>Fri, 10 Oct 2025 04:01:42 +0000</pubDate>
      <link>https://forem.com/sadel_fortunato_00791b587/dia-3-principio-abiertocerrado-openclosed-principle-en-c-1po</link>
      <guid>https://forem.com/sadel_fortunato_00791b587/dia-3-principio-abiertocerrado-openclosed-principle-en-c-1po</guid>
      <description>&lt;p&gt;&lt;strong&gt;¿Qué es el Principio Abierto/Cerrado?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El Principio Abierto/Cerrado (Open/Closed Principle) establece que:&lt;/p&gt;

&lt;p&gt;Las clases deben estar abiertas para su extensión, pero cerradas para su modificación.&lt;/p&gt;

&lt;p&gt;Esto significa que deberíamos poder agregar nuevas funcionalidades sin modificar el código existente.&lt;br&gt;
El objetivo es evitar romper el comportamiento actual del sistema cuando se introducen cambios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo de la vida real&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Piensa en un enchufe eléctrico.&lt;br&gt;
No cambiamos el enchufe de la pared cada vez que aparece un nuevo dispositivo.&lt;br&gt;
Simplemente los dispositivos se adaptan al enchufe.&lt;/p&gt;

&lt;p&gt;De igual forma, nuestro código debe estar diseñado para adaptar nuevas extensiones sin tocar el código ya probado y estable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo que viola el principio&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Veamos una clase Notificador que no cumple el principio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Notificador
{
    public void Enviar(string tipo, string mensaje)
    {
        if (tipo == "email")
        {
            Console.WriteLine($"Email: {mensaje}");
        }
        else if (tipo == "sms")
        {
            Console.WriteLine($"SMS: {mensaje}");
        }
        else if (tipo == "push") // ← MODIFICAMOS la clase
        {
            Console.WriteLine($"Push: {mensaje}");
        }
        else if (tipo == "slack") // ← MODIFICAMOS nuevamente
        {
            Console.WriteLine($"Slack: {mensaje}");
        }

        // ¿WhatsApp? ¿Discord? ¿Telegram?
        // ¡Seguiremos modificando esta clase!
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problemas con este enfoque&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cada vez que se agrega un nuevo tipo de notificación, tenemos que modificar la clase.&lt;/li&gt;
&lt;li&gt;Difícil de testear y mantener.&lt;/li&gt;
&lt;li&gt;Rompe el Principio de Responsabilidad Única (SRP).&lt;/li&gt;
&lt;li&gt;El código puede crecer fácilmente hasta tener cientos de líneas solo en un método.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solución aplicando el Principio Abierto/Cerrado&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Interfaz base (cerrada para modificación)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface INotificador
{
    void Enviar(string mensaje);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Implementaciones (abiertas para extensión)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class NotificadorEmail : INotificador
{
    public void Enviar(string mensaje)
    {
        Console.WriteLine($"Email: {mensaje}");
    }
}

public class NotificadorSMS : INotificador
{
    public void Enviar(string mensaje)
    {
        Console.WriteLine($"SMS: {mensaje}");
    }
}

public class NotificadorPush : INotificador
{
    public void Enviar(string mensaje)
    {
        Console.WriteLine($"Push: {mensaje}");
    }
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Agregar una nueva notificación (ejemplo: Slack)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class NotificadorSlack : INotificador
{
    public void Enviar(string mensaje)
    {
        Console.WriteLine($"Slack: {mensaje}");
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;*&lt;em&gt;Clase gestora que usa la interfaz *&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class GestorNotificaciones
{
    private readonly INotificador _notificador;

    public GestorNotificaciones(INotificador notificador)
    {
        _notificador = notificador;
    }

    public void Notificar(string mensaje)
    {
        _notificador.Enviar(mensaje);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Uso del código&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Program
{
    static void Main()
    {
        INotificador notificador = new NotificadorSlack();
        var gestor = new GestorNotificaciones(notificador);

        gestor.Notificar("¡Hola desde Slack!");
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;¿Qué logramos con esto?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ahora cada tipo de notificación es independiente.&lt;br&gt;
Si queremos agregar un nuevo canal, como WhatsApp o Telegram, solo creamos una nueva clase que implemente &lt;code&gt;INotificador&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No necesitamos modificar las clases existentes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beneficios&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Fácil de testear: cada clase puede probarse de forma aislada.&lt;/li&gt;
&lt;li&gt;  Cumple el Principio de Responsabilidad Única (SRP).&lt;/li&gt;
&lt;li&gt;  Código limpio, legible y mantenible.&lt;/li&gt;
&lt;li&gt;  Escalable: agregar nuevas notificaciones es sencillo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt;&lt;br&gt;
El Principio Abierto/Cerrado es una pieza fundamental de SOLID.&lt;br&gt;
Te permite construir software flexible, mantenible y escalable a largo plazo.&lt;/p&gt;

&lt;p&gt;Diseña tu código para extenderse, no para reescribirse.&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>architecture</category>
      <category>csharp</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>DIA 2: PRINCIPIO DE RESPONSABILIDAD UNICA</title>
      <dc:creator>Sadel Fortunato</dc:creator>
      <pubDate>Wed, 08 Oct 2025 17:08:59 +0000</pubDate>
      <link>https://forem.com/sadel_fortunato_00791b587/dia-2-principio-de-responsabilidad-unica-190o</link>
      <guid>https://forem.com/sadel_fortunato_00791b587/dia-2-principio-de-responsabilidad-unica-190o</guid>
      <description>&lt;p&gt;¿Qué es el Principio de Responsabilidad Única?&lt;/p&gt;

&lt;p&gt;"Una clase debe tener una sola razón para cambiar"&lt;/p&gt;

&lt;p&gt;-Robert C. Martin.&lt;/p&gt;

&lt;p&gt;De la forma sencilla se traduce como: cada clase o modulo debe tener una sola razón de ser u ocuparse de una sola cosa y hacerla bien.&lt;/p&gt;

&lt;p&gt;¿Qué significa "una razón para cambiar"?&lt;/p&gt;

&lt;p&gt;Una razón para cambiar significa que actores podrían solicitar campos, por ejemplo, Equipo de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ventas&lt;/li&gt;
&lt;li&gt;Finanzas&lt;/li&gt;
&lt;li&gt;Usuarios Finales&lt;/li&gt;
&lt;li&gt;Equipo de seguridad&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Una analogía del mundo real sería EL RESTAURANTE:&lt;/p&gt;

&lt;p&gt;Mesero que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Toma ordenes&lt;/li&gt;
&lt;li&gt;Sirve comida&lt;/li&gt;
&lt;li&gt;Cobra&lt;/li&gt;
&lt;li&gt;Limpia&lt;/li&gt;
&lt;li&gt;Gestiona inventario&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto destroza en su totalidad este principio, ya que sin muchas funciones delegas a una sola entidad.&lt;/p&gt;

&lt;p&gt;podríamos tener:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mesero: Solo toma órdenes y sirve&lt;/li&gt;
&lt;li&gt;Chef: Solo cocina&lt;/li&gt;
&lt;li&gt;Personal de limpieza: Limpia&lt;/li&gt;
&lt;li&gt;Cajero: solo cobra&lt;/li&gt;
&lt;li&gt;Gerente: Gestiona Inv.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto respeta totalmente el principio ya que cada actor o entidad está cumpliendo una única labor y está enfocada en cumplir bien esa labor&lt;/p&gt;

&lt;p&gt;Beneficios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Es más mantenible y gestionable&lt;/li&gt;
&lt;li&gt;Pequeñas actividades tienen menor margen de error&lt;/li&gt;
&lt;li&gt;La colaboración distribuida hace más reutilizable una entidad&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;`class Usuario:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self, nombre, email, contraseña):&lt;br&gt;
        self.nombre = nombre&lt;br&gt;
        self.email = email&lt;br&gt;
        self.contraseña = contraseña&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def validar_email(self):
    """Valida formato de email"""
    import re
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, self.email) is not None

def encriptar_contraseña(self):
    """Encripta la contraseña"""
    import hashlib
    return hashlib.sha256(self.contraseña.encode()).hexdigest()

def guardar_en_base_datos(self):
    """Guarda usuario en BD"""
    import sqlite3
    conn = sqlite3.connect('usuarios.db')
    cursor = conn.cursor()
    cursor.execute(
        "INSERT INTO usuarios VALUES (?, ?, ?)",
        (self.nombre, self.email, self.encriptar_contraseña())
    )
    conn.commit()
    conn.close()

def enviar_email_bienvenida(self):
    """Envía email de bienvenida"""
    import smtplib
    msg = f"Bienvenido {self.nombre}!"
    # código para enviar email...
    print(f"Email enviado a {self.email}")

def generar_reporte_pdf(self):
    """Genera reporte PDF del usuario"""
    from reportlab.pdfgen import canvas
    # código para generar PDF...
    print(f"PDF generado para {self.nombre}")`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;En este código tenemos la clase usuario que hace distintas actividades o mencionado en la analogía anterior del restaurante tenemos el actor usuario que está ejecutando distintas funciones, al igual que la primera representación del mesero.&lt;/p&gt;

&lt;p&gt;Aquí podemos identificar que nuestro mesero (clase usuario) &lt;br&gt;
tiene las siguientes actividades: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Gestionar datos del usuario&lt;/li&gt;
&lt;li&gt;Validar datos del usuario&lt;/li&gt;
&lt;li&gt;Manejar la contraseña del usuario&lt;/li&gt;
&lt;li&gt;Notificaciones&lt;/li&gt;
&lt;li&gt;Persistencia o Guardar en base de datos&lt;/li&gt;
&lt;li&gt;Reportes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Razones para cambiar (Actores):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Que se cambie el proceso de notificación&lt;/li&gt;
&lt;li&gt;Que modifiquemos el proveedor del email&lt;/li&gt;
&lt;li&gt;Que los reportes tengan formatos distintos&lt;/li&gt;
&lt;li&gt;Que cambiemos la encriptación de la contraseña&lt;/li&gt;
&lt;li&gt;Que migremos la base de datos de SQLite a PostgreSQL&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Clase Usuario: SOLO datos y lógica básica
&lt;/h1&gt;

&lt;p&gt;class Usuario:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self, nombre, email, contraseña):&lt;br&gt;
        self.nombre = nombre&lt;br&gt;
        self.email = email&lt;br&gt;
        self.contraseña = contraseña&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def get_datos(self):
    return {
        'nombre': self.nombre,
        'email': self.email
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  2. Validador: SOLO validación
&lt;/h1&gt;

&lt;p&gt;class ValidadorEmail:&lt;br&gt;
    @staticmethod&lt;br&gt;
    def validar(email):&lt;br&gt;
        import re&lt;br&gt;
        pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$'&lt;br&gt;
        return re.match(pattern, email) is not None&lt;/p&gt;
&lt;h1&gt;
  
  
  3. Servicio de Seguridad: SOLO encriptación
&lt;/h1&gt;

&lt;p&gt;class ServicioSeguridad:&lt;br&gt;
    @staticmethod&lt;br&gt;
    def encriptar_contraseña(contraseña):&lt;br&gt;
        import hashlib&lt;br&gt;
        return hashlib.sha256(contraseña.encode()).hexdigest()&lt;/p&gt;
&lt;h1&gt;
  
  
  4. Repositorio: SOLO persistencia
&lt;/h1&gt;

&lt;p&gt;class RepositorioUsuario:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self, conexion_bd):&lt;br&gt;
        self.conexion = conexion_bd&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def guardar(self, usuario):
    cursor = self.conexion.cursor()
    contraseña_hash = ServicioSeguridad.encriptar_contraseña(usuario.contraseña)
    cursor.execute(
        "INSERT INTO usuarios VALUES (?, ?, ?)",
        (usuario.nombre, usuario.email, contraseña_hash)
    )
    self.conexion.commit()

def buscar_por_email(self, email):
    cursor = self.conexion.cursor()
    cursor.execute("SELECT * FROM usuarios WHERE email = ?", (email,))
    return cursor.fetchone()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  5. Servicio de Email: SOLO notificaciones
&lt;/h1&gt;

&lt;p&gt;class ServicioEmail:&lt;br&gt;
    def &lt;strong&gt;init&lt;/strong&gt;(self, config_smtp):&lt;br&gt;
        self.config = config_smtp&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def enviar_bienvenida(self, usuario):
    mensaje = f"¡Bienvenido {usuario.nombre}!"
    # Código real de envío de email
    print(f"Email enviado a {usuario.email}: {mensaje}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  6. Generador de Reportes: SOLO PDFs
&lt;/h1&gt;

&lt;p&gt;class GeneradorReportesPDF:&lt;br&gt;
    def generar_reporte_usuario(self, usuario):&lt;br&gt;
        # Código para generar PDF&lt;br&gt;
        print(f"PDF generado para {usuario.nombre}")&lt;br&gt;
        return f"reporte_{usuario.nombre}.pdf"&lt;/p&gt;
&lt;h1&gt;
  
  
  USO:
&lt;/h1&gt;

&lt;p&gt;def registrar_usuario(nombre, email, contraseña):&lt;br&gt;
    # Validar&lt;br&gt;
    if not ValidadorEmail.validar(email):&lt;br&gt;
        raise ValueError("Email inválido")&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Crear usuario
usuario = Usuario(nombre, email, contraseña)

# Guardar
import sqlite3
conn = sqlite3.connect('usuarios.db')
repo = RepositorioUsuario(conn)
repo.guardar(usuario)

# Notificar
servicio_email = ServicioEmail(config_smtp={})
servicio_email.enviar_bienvenida(usuario)

# Generar reporte
generador = GeneradorReportesPDF()
generador.generar_reporte_usuario(usuario)

conn.close()
return usuario
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;`&lt;br&gt;
BENEFICIOS DE LA REFACTORIZACIÓN:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Usuarios: Solo se encarga de gestionar lo mínimo del usuario&lt;/li&gt;
&lt;li&gt;ValidadorEmail: puedes reutilizarse en otros contextos&lt;/li&gt;
&lt;li&gt;ServicioSeguridad:Fácil cambiar de SHA256 a bcrypt&lt;/li&gt;
&lt;li&gt;El repositorio de usuario es fácil moverlo de DB&lt;/li&gt;
&lt;li&gt;La reporteria puede ser reutilizable y flexible para cambiar de libreria&lt;/li&gt;
&lt;li&gt;Facil de cambiar el proveedor de email&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ahora cada clase tiene una sola razon para cambiar &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>spanish</category>
      <category>architecture</category>
      <category>designpatterns</category>
    </item>
  </channel>
</rss>
