Approccio generale a un'interfaccia che risolverà una dipendenza in una libreria di database

2

Sfondo

Spesso scrivo software per sistemi che sono responsabili della verifica di prodotti fabbricati. Per ogni prodotto che viene testato, dobbiamo generare un rapporto per i risultati del test. Il modo in cui lo facciamo ora è che creiamo un file .txt con i risultati del test e lo scriviamo in qualche cartella sulla nostra unità di rete. In definitiva, sto cercando di passare a una soluzione di database come SQL.

Poiché so che alla fine ci stiamo muovendo verso una soluzione di database, vorrei separare la funzionalità corrente (scrivendo il file .txt sull'unità di rete) tramite un'interfaccia. Alla fine sarò in grado di scrivere una libreria per controllare la registrazione dei risultati del test in qualche database. Quando ciò accade, vorrei semplicemente implementare la stessa interfaccia che verrà utilizzata dalla soluzione di registrazione dei risultati dei test correnti.

Per quanto riguarda l'interfaccia, stavo pensando di avere alcuni metodi semplici che so di cui avrò bisogno come:

LogResults(string operator, string product, string serialNumber, string Results)
Connect(string pathToDriveLocation)

L'unica cosa è che non ho mai fatto un database prima e non sono sicuro di poter adattare i due diversi modi di eseguire la registrazione alla stessa interfaccia.

Domanda

Sto pensando a questo correttamente? Questo sembra un approccio sonoro, o ha bisogno di un po 'di lavoro?

    
posta Snoop 06.10.2016 - 19:01
fonte

2 risposte

0

Mi piacerebbe prendere la risposta di @ TulainsCordova un ulteriore passo avanti.

Innanzitutto, definisci l'interfaccia come il comportamento minimo richiesto per eseguire la registrazione (userò C # come esempio):

public interface ILogger
{
    void LogResults(string operatorName, string product, string serialNumber, string Results);
}

Questo è tutto ciò di cui hai bisogno è un modo per registrare le cose. Qualcosa in più e la tua interfaccia viene inquinata con i dettagli di implementazione. Qualsiasi informazione specifica per l'implementazione deve essere gestita come argomento del costruttore per la classe concreta che implementa questa interfaccia. Ad esempio, TextFileLogger:

public class TextFileLogger : ILogger
{
    public TextFileLogger(string fileName)
    {
        this.fileName = fileName;
    }

    private string fileName;

    public void LogResults(string operatorName, string product, string serialNumber, string Results)
    {
        string message = "...";

        File.WriteAllText(fileName, message, Encoding.UTF8);
    }
}

In seguito decidi di accedere a un database, così puoi aggiungere un'altra classe:

public class SqlServerDatabaseLogger : ILogger
{
    public SqlServerDatabaseLogger(string connectionString)
    {
        this.connectionString = connectionString;
    }

    public void LogResults(string operatorName, string product, string serialNumber, string Results)
    {
        string message = "...";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            // INSERT into database
        }
    }
}

Nel resto della tua applicazione può essere disaccoppiato dal tipo di logger utilizzando una classe factory (e l'enumerazione che accompagna il tipo di logger):

public enum LoggerType
{
    TextFile = 0,
    SqlServer = 1
}

public class LoggerFactory
{
    public LoggerFactory(LoggerType loggerType)
    {
        this.loggerType = loggerType;
    }

    private ILogger logger;
    private LoggerType loggerType;

    public ILogger Logger
    {
        get
        {
            if (logger == null)
                logger = CreateLogger(loggerType);

            return logger;
        }
    }

    private static ILogger CreateLogger(LoggerType loggerType)
    {
        switch (loggerType)
        {
            case LoggerType.TextFile:
                return new TextFileLogger("path/to/filename");
            case LoggerType.SqlServer:
                return new SqlServerDatabaseLogger("connection string");
            default:
                throw new ArgumentOutOfRangeException("loggerType");
        }
    }
}

Quindi crea la fabbrica del logger una volta:

LoggerFactory factory = new LoggerFactory(LoggerType.TextFile);
ILogger logger = factory.Logger;

Passa il registratore o la fabbrica a un numero qualsiasi di altre classi. Quando passi a un nuovo tipo di registrazione, modifica semplicemente una singola riga di codice:

LoggerFactory factory = new LoggerFactory(LoggerType.SqlServer);

E il gioco è fatto.

    
risposta data 06.10.2016 - 19:51
fonte
0

Il tuo approccio è davvero buono. Non ci dovrebbero essere differenze concettuali (interfaccia-saggio) tra la registrazione in un file di testo, una tabella di database o una stampante (o schermo).

Nel metodo di connessione ti suggerisco di cambiare firma in qualcosa di più neutro, come:

openDevice(String deviceString);

Una stringa devide può essere un percorso per un file ...

connect("/var/logs/log001.txt");

o una stringa di connessione al database ...

connect("user/[email protected]:1021/database");

Nel caso di registri di file, è sufficiente verificare se il file esiste e se si dispone dell'autorizzazione.

Puoi scegliere tra aggiungere una "lancia CouldNotOpenDeviceException" o restituire un codice di errore.

void openDevice(String deviceString) throws CouldNotOpenDeviceException;

vs

int openDevice(String deviceString);
    
risposta data 06.10.2016 - 19:21
fonte