Можно ли поместить вызов инициализации базы данных в конструктор C#?[закрыто]

StackOverflow https://stackoverflow.com/questions/159886

  •  03-07-2019
  •  | 
  •  

Вопрос

Я видел это в различных кодовых базах и хотел знать, осуждается ли это в целом или нет.

Например:

public class MyClass
{
   public int Id;

   public MyClass()
   {
      Id = new Database().GetIdFor(typeof(MyClass));
   }
}
Это было полезно?

Решение

Есть несколько причин, по которым такой дизайн обычно не считается хорошим, некоторые из них, например, затруднение модульного тестирования и сложность обработки ошибок, уже упоминались.

Основная причина, по которой я бы предпочел этого не делать, заключается в том, что ваш объект и уровень доступа к данным теперь очень тесно связаны, а это означает, что любое использование этого объекта за пределами его первоначального дизайна требует значительной доработки.В качестве примера, что, если вы столкнулись с экземпляром, в котором вам нужно было использовать этот объект без каких-либо присвоенных значений, например, для сохранения нового экземпляра этого класса?теперь вам придется либо перегрузить конструктор, а затем убедиться, что вся остальная логика обрабатывает этот новый случай, либо наследовать и переопределить.

Если бы объект и доступ к данным были разделены, вы могли бы создать экземпляр, а затем не увлажнять его.Или, если у вас есть другой проект, который использует те же объекты, но другой уровень персистентности, тогда объекты можно использовать повторно.

Сказав, что в прошлом я выбрал более простой путь объединения проектов :)

Другие советы

Хорошо..Я бы не стал.Но опять же, мой подход обычно предполагает, что класс НЕ отвечает за получение своих собственных данных.

Это также затруднит написание модульных тестов для класса, поскольку вы не сможете заставить класс использовать версию Mock/Stub класса db.Глянь сюда:http://en.wikipedia.org/wiki/Dependency_injection

Вы можете использовать одноразовый шаблон, если вы ссылаетесь на соединение с БД:

public class MyClass : IDisposable
{
    private Database db;
    private int? _id;

    public MyClass()
    {
        db = new Database();
    }

    public int Id
    {
        get
        {
            if (_id == null) _id = db.GetIdFor(typeof(MyClass));
            return _id.Value;
        }
    }

    public void Dispose()
    {
        db.Close();
    }
}

Использование:

using (var x = new MyClass()) 
{
    /* ... */

} //closes DB by calling IDisposable.Dispose() when going out of "using" scope

Да, вы МОЖЕТЕ это сделать, но это не лучший дизайн, а обработка ошибок в конструкторах не такая аккуратная, как где-либо еще.

Единственная проблема, которую я могу придумать при таком подходе, заключается в том, что любые ошибки инициализации БД будут распространяться как исключения из конструктора.

Зачем кому-то использовать фиктивный объект/заглушку вместо реальной вещи?Согласитесь ли вы с тем, что производители автомобилей должны использовать модели из опорной доски для CrashTests?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top