@Qualifier e principio di inversione delle dipendenze

1

Recentemente ho scoperto i principi SOLID e sto cercando di imparare come applicarli correttamente. Ho un'applicazione con un'interfaccia enorme:

public interface NotificationService {
  public void sendNewProjectRequestNotificationToDesigners(String projectId);
  public void sendNewProjectAcceptedNotificationToCustomer(String projectId);
  public void sendNewProjectRejectedNotificationToCustomer(String projectId);
  ...
  // and aboud 30 more methods like that
  // specifying the type of notification and who is going to be sent to
}

Questo chiaramente viola:

  • SRP: tanti tipi diversi di notifiche
  • OCP: ogni nuova notifica ho appena modificato la classe
  • ISP: in ogni singola classe che inietta un NotificationService, vorrà solo 1 di tutti i metodi.
  • DIP: i client di questa classe devono essere consapevoli del metodo esatto da utilizzare.

quindi ho iniziato il mio refactoring e mi sono inventato:

public interface NotificationSender {
  public void sendNotification(String projectId);
}

public class NewProjectRequestNotificationSender implements NotificationSender {
  public void sendNotification(String projectId) {
    ...
  }
}

// and many other classes, one for each method in the original interface

Ora per applicare Dependency Injection, ho dichiarato ogni classe che implementa NotificationSender come @Bean con un nome di qualificatore.

E le classi che richiedono un mittente di notifica specifico, la dipendenza viene iniettata con @Qualifier.

Domanda 1: Dovendo usare @Qualifier nei clases che richiedono un NotificationSender specifico, quindi questi clases sono ancora costretti a conoscere dettagli come il nome del qualificatore del dato NotificationSender, sto ancora violando il principio di inversione della dipendenza?

Domanda 2: Esiste un approccio migliore?

    
posta saljuama 06.06.2015 - 21:55
fonte

3 risposte

1

No, i qualificatori sono solo un suggerimento per il sistema di iniezione delle dipendenze. Sono più di configurazione di codice. Stai ancora accedendo ai bean solo tramite l'interfaccia NotificationSender , quindi il tuo codice non ne sa più sui dettagli di implementazione delle diverse istanze.

Immagina di essere stato un'unità testando un bean che ha utilizzato un'iniezione NotificationSender qualificata. Puoi passarlo qualsiasi NotificationSender che ti è piaciuto (un finto, forse). Al di fuori del framework DI, il tuo codice non potrebbe importare di meno di quale implementazione gli dai!

    
risposta data 06.10.2015 - 01:59
fonte
0

Potresti aggiungere un altro strato di riferimento indiretto usando una fabbrica e iniettando le classi concrete nella fabbrica, quindi iniettando la fabbrica dove hai bisogno delle classi concrete. La fabbrica potrebbe avere un metodo con cui viene passato il chiamante, e quindi la fabbrica potrebbe capire cosa restituire in base a ciò.

    
risposta data 07.06.2015 - 19:08
fonte
0

Hai considerato di ridefinire la tua interfaccia con qualcosa di simile:

public interface NotificationSender {
  public void sendNotification(NotificationEvent event);
}

public final class NotificationEvent {
    private final NotificationKind type;
    private final String projectId;

    ...
}

public enum NotificationKind {
    REQUESTED, ACCEPTED, REJECTED, ...;
}
    
risposta data 06.10.2015 - 08:11
fonte

Leggi altre domande sui tag