Questo è un semplice esempio, ma riflette una tensione tra i principi SOLIDI con cui spesso mi trovo a dover lottare.
Un esempio popolare del Principio Aperto / Chiuso (es. [1] , [2] ) immagina di avere molte classi Shape e un metodo drawShape()
, ad esempio :
// Open-Close Principle - Bad example
class GraphicEditor {
public void drawShape(Shape s) {
if (s.m_type==1)
drawRectangle(s);
else if (s.m_type==2)
drawCircle(s);
}
public void drawCircle(Circle r) {....}
public void drawRectangle(Rectangle r) {....}
}
Usando l'Open / Closed Principle (OCP), osserviamo che questo codice dovrebbe essere modificato per ogni nuova forma che aggiungiamo; vogliamo chiudere la necessità di modifiche e consentire l'estensione come un modo migliore per aggiungere nuovi comportamenti.
Gli esempi offrono quindi quanto segue come soluzione conforme a OCP:
// Open-Close Principle - Good example
class GraphicEditor {
public void drawShape(Shape s) {
s.draw();
}
}
class Shape {
abstract void draw();
}
class Rectangle extends Shape {
public void draw() {
// draw the rectangle
}
}
Come dimostrazione dell'OCP in astratto, questo è un buon esempio. Tuttavia, questa soluzione mi sembra una palese violazione del Principio di Responsabilità Unica (SRP) . Abbiamo iniziato con la "responsabilità di disegno" separata nella sua classe e abbiamo risolto il nostro problema di OCP abbattendo quella "responsabilità di disegno" con la semplice definizione di una forma.
Ad esempio, se il disegno implica l'interazione con una GUI, questo esempio accoppia la definizione di una forma semplice con le operazioni della GUI! Sembra sbagliato.
Quale sarebbe una buona riprogettazione qui che sarebbe conforme a OCP e a SRP?