Wie soll ich meinen Code modellieren, um die Wiederverwendung von Code in dieser speziellen Situation zu maximieren?

Updated: Am Ende der Frage erfahren Sie, wie ich die Lösung implementiert habe.

Sorry für die schlecht formulierte Frage, aber ich war mir nicht sicher, wie ich sie am besten stellen sollte. Ich bin nicht sicher, wie ich eine Lösung entwerfen soll, die wiederverwendet werden kann, wenn der größte Teil des Codes bei jeder Implementierung identisch ist. Ein Teil der Implementierung ändert sich jedoch jedes Mal, folgt jedoch ähnlichen Mustern. Ich versuche, das Kopieren und Einfügen von Code zu vermeiden.

Wir verfügen über ein internes Datenübertragungssystem zum Aktualisieren von Tabellen über Datenbanken auf verschiedenen Computern. Wir erweitern unseren Messaging-Service, um Daten an externe Anbieter zu senden, und ich möchte eine einfache Lösung codieren, die wiederverwendet werden kann, wenn wir Daten an mehr als einen Anbieter senden möchten. Der Code wird in eine EXE-Datei kompiliert und regelmäßig ausgeführt, um Nachrichten an den Datendienst des Anbieters zu senden.

Hier ist eine grobe Beschreibung der Funktionsweise des Codes:

public class OutboxManager 
{
    private List<OutboxMsg> _OutboxMsgs;

    public void DistributeOutboxMessages()
    {
        try {
            RetrieveMessages();
            SendMessagesToVendor();
            MarkMessagesAsProcessed();
        }
        catch Exception ex {
            LogErrorMessageInDb(ex);
        }
    }

    private void RetrieveMessages() 
    {
      //retrieve messages from the database; poplate _OutboxMsgs.
      //This code stays the same in each implementation.
    }

    private void SendMessagesToVendor()   // <== THIS CODE CHANGES EACH IMPLEMENTATION
    {
      //vendor-specific code goes here.
      //This code is specific to each implementation.
    }

    private void MarkMessagesAsProcessed()
    {
      //If SendMessageToVendor() worked, run this method to update this db.
      //This code stays the same in each implementation.
    }

    private void LogErrorMessageInDb(Exception ex)
    {
      //This code writes an error message to the database
      //This code stays the same in each implementation.
    }
}

Ich möchte diesen Code so schreiben, dass ich die Teile, die sich nicht ändern, wiederverwenden kann, ohne den Code für @ kopieren, einfügen und ausfüllen zu müsseSendMessagesToVendor(). Ich möchte, dass ein Entwickler ein @ verwenden kaOutboxManager und haben den gesamten Datenbankcode bereits geschrieben, müssen jedoch ihre eigene Implementierung zum Senden von Daten an den Anbieter bereitstellen.

Ich bin mir sicher, dass es gute objektorientierte Prinzipien gibt, die mir bei der Lösung dieses Problems helfen können, aber ich bin mir nicht sicher, welche am besten geeignet sind.

Dies ist die Lösung, mit der ich endete, inspiriert von Victors Antwort und Reeds Antwort (und Kommentare), um ein Schnittstellenmodell zu verwenden. Alle Methoden sind vorhanden, aber jetzt stecken sie in Schnittstellen, die der Consumer bei Bedarf aktualisieren kann.

Ich habe die Leistungsfähigkeit der Schnittstellenimplementierung erst erkannt, als mir klar wurde, dass der Konsument der Klasse seine eigenen Klassen für den Datenzugriff einbinden kann IOutboxMgrDataProvider) und Fehlerprotokollierung IErrorLogger). Obwohl ich immer noch Standardimplementierungen bereitstelle, da ich nicht erwarte, dass sich dieser Code ändert, ist es dem Konsumenten dennoch möglich, sie mit ihrem eigenen Code zu überschreiben. Bis auf das Ausschreiben mehrerer Konstruktoren (dieIch kann zu benannten und optionalen Parametern wechseln), es hat wirklich nicht viel Zeit gekostet, meine Implementierung zu ändern.

public class OutboxManager
{
    private IEnumerable<OutboxMsg> _OutboxMsgs;
    private IOutboxMgrDataProvider _OutboxMgrDataProvider;
    private IVendorMessenger _VendorMessenger;
    private IErrorLogger _ErrorLogger;

    //This is the default constructor, forcing the consumer to provide
    //the implementation of IVendorMessenger.
    public OutboxManager(IVendorMessenger messenger)
    {
         _VendorMessenger = messenger;
         _OutboxMgrDataProvider = new DefaultOutboxMgrDataProvider();
         _ErrorLogger = new DefaultErrorLogger();
    }

    //... Other constructors here that have parameters for DataProvider
    //    and ErrorLogger.

    public void DistributeOutboxMessages()
    {
         try {
              _OutboxMsgs = _OutboxMgrDataProvider.RetrieveMessages();
              foreach om in _OutboxMsgs
              {
                  if (_VendorMessenger.SendMessageToVendor(om))
                      _OutboxMgrDataProvider.MarkMessageAsProcessed(om)
              }
         }
         catch Exception ex {
             _ErrorLogger.LogErrorMessage(ex)
         }
    }

}

//...interface code: IVendorMessenger, IOutboxMgrDataProvider, IErrorLogger
//...default implementations: DefaultOutboxMgrDataProvider(),
//                            DefaultErrorLogger()

Antworten auf die Frage(14)

Ihre Antwort auf die Frage