Удаление связи уровня доступа к данным из пользовательского интерфейса
В настоящее время уровень пользовательского интерфейса моего приложения связан с моей библиотекой DAL. Dal инициализируется так:
//Initialize Data Access for AS400
Dal = JDE8Dal.Instance;
Dal.conString = Properties.Settings.Default.conAS400;
DAL обозначается как синглтон. Я думал, что заставить приложение иметь один экземпляр - это хорошая идея.
DAL:
public class JDE8Dal
{
public string conString { get; set; }
private static readonly JDE8Dal _instance = new JDE8Dal();
private JDE8Dal()
{
}
public static JDE8Dal Instance
{
get { return _instance; }
}
// Methods
}
Мой BLL будет выглядеть примерно так:
namespace YLA.Barcode
{
public static class YlaBarcodeUtil
{
public static string LotStripZeroes(string str)
{
var ret = str;
if (str.Trim().StartsWith("00"))
{
ret = YlaGeneralUtilities.StripLeadingNumofChars(str, 2);
}
return ret;
}
}
public class BarcodeBLL
{
//DAL INIT HERE?
}
}
Теперь, когда мне нужно создать больше приложений, мне нужно перейти на трехуровневую архитектуру и начать читать DDD.
1) Как переместить обработку DAL в BLL? Просто добавить инициализацию в моем разделе BLL?
2) Должен ли я сохранить свой дизайн DAL как синглтон или нет?
3 ответа
Вы должны использовать шаблон Inversion of Control, чтобы уменьшить зависимость между вашими слоями. В вашем случае я бы использовал внедрение конструктора, поскольку ваш класс требует контекст данных:
public class BarcodeBLL
{
private JDE8Dal _context;
public BarcodeBLL(JDE8Dal context)
{
_context = context;
}
}
Контекст данных должен быть недолговечными объектами. Если вы разрабатываете веб-приложение, вы должны создавать один контекст данных для каждого запроса. Я также рекомендовал бы использовать ORM (Entity Framework / NHibernate).
1: Обычно у вас есть инфраструктурный слой, который создает композицию.
2: НЕТ ВСЕМИ СРЕДСТВАМИ. Это граничит с "изучением программирования". Используйте контейнер МОК.
//Initialize Data Access for AS400
Dal = JDE8Dal.Instance;
Dal.conString = Properties.Settings.Default.conAS400;
Этот комментарий вводит в заблуждение. Этот код на самом деле не инициализирует доступ к данным, а только устанавливает строку подключения к базе данных. Это должно быть сделано в самом DAL, а не в пользовательском интерфейсе.
public class JDE8Dal
{
public string conString { get; set; }
private static readonly JDE8Dal _instance = new JDE8Dal();
private JDE8Dal()
{
}
public static JDE8Dal Instance
{
get { return _instance; }
}
// Methods
}
Слои обычно не определяются таким образом, DAL - это сборка / dll, а не класс. Когда вы это пишете, кажется, что вам нужен объект Бога, в котором определена вся логика постоянства. Классы на уровне доступа к данным гораздо более детализированы и специализированы: например, репозитории / DAO управляют сохранением одного конкретного объекта домена.
Кроме того, обычно не стоит прибегать к синглтону "просто потому, что он чувствует себя правильно, если у него только один экземпляр". И особенно не изменчивый синглтон. В вашем примере каждый может изменить Dal.Instance.conString
с потенциально драматическими последствиями для других потребителей синглтона. Среди других недостатков.
Даже если есть вероятность, что когда-нибудь будет одна реализация вашего DAL (как AS400), в проектах разумной сложности рекомендуется использовать внедрение зависимостей для целей модульного тестирования. DI позволяет вам легко заменить ваши конкретные реализации объекта DAL на поддельные объекты DAL, которые намного легче и полезнее в модульных тестах.
public class BarcodeBLL
{
//DAL INIT HERE?
}
Не, нет инициализации DAL здесь;)
Уровень бизнес-логики (уровень домена в DDD) не должен иметь ссылку на DAL, DAL должен иметь ссылку на BLL. Доменный объект не должен знать, как сохранить себя (принцип невосприимчивости к постоянству), потому что у него будет слишком много обязанностей (принцип единой ответственности), и это создаст тесную связь между BLL и DAL, что делает его очень неудобным для повторного использования и обслуживания BLL.