miércoles, 30 de julio de 2014

Principio de Responsabilidad Única (SRP - Single Responsability Principle)

Principio de Responsabilidad Única

(SRP Single Responsability Principle)


Este principio, desde mi punto de vista, es la base para lograr un buen diseño de tu software y la verdad es muy fácil de entender, la definición nos dice:
Tu clase solo deberá tener una razón para cambiar.
Esto también deberá llevarse a nivel de métodos, entendiendo que la razón principal se va descomponiendo en pequeños fragmentos de tareas para cumplir el objetivo inicial.

...ahora como yo lo veo….

Si tienes una clase que vas a actualizar porque se mejoró un cálculo y luego porque cambiaste de motor gráfico y después porque agregaste un nuevo reporte y quien sabe porque no funciona si no haces un cambio en ésta clase; bueno he aquí muchas razones por las cuales tu clase cambia, esto hace evidente que algo anda mal en el diseño de nuestro programa. Llego la hora de aplicar... ¡SRP is comming!.

Tratando de ayudar al entendimiento de este principio, expondré un ejemplo:

Caso de Uso: Una tienda tiene artículos a la venta, de estos artículos las principales características son la calidad y los días disponibles para venderlos, ambos valores se ven afectados conforme transcurren los días, aunque no para todos los artículos y no de la misma forma.

Un primer diseño de esta clase fue:

public class Item {
    private String name;
    private int sellIn;
    private int quality;
    private QualityUpdater qualityUpdater;
    private SellInUpdater sellInUpdater;


    public Item(String name, int sellIn, int quality) {
        this.name = name;
        this.sellIn = sellIn;
        this.quality = quality;
        selectUpdaters();
    }

    private void selectUpdaters() {
        this.sellInUpdater = DispacherUpdaters.getSellInUpdater(name);
        this.qualityUpdater = DispacherUpdaters.getQualityUpdater(name);
    }

    public String getters() {...}

    public void setters() {...}

    public void update(){
        updateSellIn();
        updateQuality();
    }

    private void updateQuality() {
        qualityUpdater.updateQuality(this);
    }

    private void updateSellIn(){
        sellInUpdater.updateSellIn(this);
    }
}

Con este primer diseño los artículos que no cambian deben tener un QualityUpdater y un SellInUpdater que no hagan nada. Esto quiere decir que los updaters no son necesarios para todos lo artículos y además ésta misma clase busca sus updaters que utilizará para actualizar la calidad y los días de venta; otra responsabilidad a parte de mantener su información. Una forma de aplicar SRP seria:

1. Separar la lógica de los articulos que cambian y los que no.
2. Inyectar, para los artículos que cambian, la forma en que estos cambian.

public class Item {
    public String name;
    public int sellIn;
    public int quality;

    public Item(String name, int sellIn, int quality) {
        this.name = name;
        this.sellIn = sellIn;
        this.quality = quality;
    }

    public String getters() {...}

    public void setters() {...}
}

public class ItemUpdateable extends Item implements Updateable{

    private QualityUpdater qualityUpdater;
    private SellInUpdater sellInUpdater;

    public ItemUpdateable(String name, int sellIn, int quality) {
        super(name, sellIn, quality);
    }

    public void setQualityUpdater(QualityUpdater qualityUpdater) {
        this.qualityUpdater = qualityUpdater;
    }

    public void setSellInUpdater(SellInUpdater sellInUpdater) {
        this.sellInUpdater = sellInUpdater;
    }

    @Override
    public void update() {
        sellInUpdater.updateSellIn(this);
        qualityUpdater.updateQuality(this);
    }
}

Con esta solución tenemos dos clases resultantes, así los artículos que no cambian utilizan la clase Item y los artículos que son variables utilizan ItemUpdateable y además la forma en que actualizan la calidad y los días para venta son inyectadas.

Aplicar SRP nos ayudará a tener un mejor diseño de nuestro software, será fácil de entender y de modificar…¡Suerte!