Как создать общий интерфейс для различных реализаций? - PullRequest
0 голосов
/ 22 июня 2019

Я делаю небольшой проект упражнений, чтобы больше практиковаться в программировании в целом.Проект представляет собой программу, которая берет содержимое файла CSV и помещает его в некоторую базу данных.Я начал с создания интерфейса доступа к базе данных IDatabaseClient, что заставило меня задуматься о нескольких вещах:

  1. Как должен выглядеть мой метод Connect(...)?Различные базы данных могут иметь различный набор учетных данных, необходимых для подключения, т. Е. Одной может потребоваться строка соединения, другой может потребоваться: URL, имя пользователя, пароль и т. Д. Одним из способов решения этой проблемы может быть использование метода Connect, подобного этому:

Task Connect (учетные данные IConnectionCredentials);

IConnectionCredentials интерфейс будет пустым, и каждая база данных будет иметь свою собственную реализацию, например, так:

public class DatabaseNo1Credentials : IConnectionCredentials
{
    public Uri Uri { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

Что мне не нравится в таком решении, так это то, что пользователь реализации IDatabaseClient не имеет никакой информации о том, какой класс учетных данных следует использовать.Код выдаст исключение, если указан неверный класс учетных данных.Есть ли лучшее решение?

Мои файлы CSV могут содержать данные для разных таблиц базы данных.Один CSV может содержать данные об автомобилях, другой может содержать данные о людях и т. Д. Как сделать мои данные IDatabaseClient пригодными для использования многими детьми?

Я мог бы сделать это:

public interface IDatabaseClient
{
    Task Connect(IConnectionCredentials credentials);
    Task WriteCars(string model, int productionYear);
    Task WritePeople(string firstName, string lastName, int age);
}

Однако, что если однажды я захочу записать данные в таблицу телефонов или любую другую таблицу?

1 Ответ

3 голосов
/ 22 июня 2019

Ваш интерфейс слишком специфичен с точки зрения методов и особенно с точки зрения параметров методов.У вас не должно быть метода Connect с параметрами, скорее вы должны сделать что-то вроде этого:

interface IDatabaseClient
{
    Task ConnectAsync();

    Task AddDataAsync<T>(string databaseName, T data);
}

class DatabaseClient1 : IDatabaseClient
{
    public DatabaseClient1(string username, string password)
    {
        Username = username;
        Password = password;
    }

    public string Username { get;  }

    public string Password { get;  }

    public async Task ConnectAsync()
    {
        // connect using Username and Password
    }

    public async Task AddDataAsync<T>(string databaseName, T data)
    {
        // Not sure if you can work with a generic method for inserting data
        // into your database, but given that you didn't specify your 
        // requirements further, I'm just going to go with this
    }
}

Наличие нескольких операций, специфичных для таблиц базы данных, в одном интерфейсе, по моему мнению, лишает цели иметь интерфейс, поэтомуВы должны делегировать конкретную работу другим классам, которые зависят только от IDatabaseClient:

class CarManager
{
    public CarManager(IDatabaseClient databaseClient)
    {
        _databaseClient = databaseClient;
    }

    public async Task AddCarAsync(string model, int productionYear)
    {
        var car = new Car(model, productionYear);

        _databaseClient.AddDataAsync("cars", car);
    }

    private readonly IDatabaseClient _databaseClient;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...