Я всегда застрял между камнем и наковальней. В идеале ваша бизнес-логика не должна касаться проблем, связанных с базой данных или пользовательским интерфейсом.
Клавиши вызывают проблемы
Тем не менее, я нахожу такие вещи, как первичные и внешние ключи, вызывающие проблемы. Даже такие инструменты, как Entity Framework, не полностью устраняют эту проблему. Преобразование идентификаторов, переданных в виде данных POST, в их соответствующие объекты может быть крайне неэффективным, только чтобы передать их на бизнес-уровень, который затем передает их на уровень данных, чтобы их снова сократили.
Даже базы данных NoSQL поставляются с проблемами. Они, как правило, возвращают полные объектные модели, но обычно возвращают больше, чем вам нужно, и могут привести к проблемам, потому что вы предполагаете, что объектная модель не изменится. И ключи все еще находятся в базах данных NoSQL.
Повторное использование против накладных расходов
Существует также проблема повторного использования кода. Обычно слои данных возвращают полностью заполненные объекты, включая каждый столбец в этой конкретной таблице или таблицах. Тем не менее, часто бизнес-логика заботится только об ограниченном подмножестве этой информации. Он поддается специализированным объектам передачи данных, которые несут с собой только соответствующие данные. Конечно, вам нужно конвертировать между представлениями, поэтому вы создаете класс mapper. Затем, когда вы сохраняете, вам нужно каким-то образом преобразовать эти меньшие объекты обратно в полное представление базы данных или выполнить частичное ОБНОВЛЕНИЕ (что означает другую команду SQL).
Итак, я вижу, что многие классы бизнес-уровня принимают объекты, отображаемые непосредственно в таблицы базы данных (объекты передачи данных). Я также вижу много бизнес-уровней, принимающих необработанные значения пользовательского интерфейса (объекты презентации). Также нет ничего необычного в том, что бизнес-уровни обращаются к базе данных в середине вычислений для получения необходимых данных. Попытка получить его заранее, вероятно, будет неэффективной (подумайте о том, как и если оператор if может повлиять на извлекаемые данные), а отложенные загруженные значения приводят к множеству магических или непреднамеренных обращений к базе данных.
Сначала напишите свою логику
Недавно я пытался сначала написать «основной» код. Это код, который выполняет реальную бизнес-логику. Я не знаю о вас, но много раз, просматривая чужой код, я задаю вопрос: «Но где это [бизнес-правило]?» Зачастую бизнес-логика настолько переполнена заботами о сборе данных, их преобразовании и тому подобном, что я даже не вижу их (иголка в стоге сена). Итак, теперь я сначала реализую логику и, выясняя, какие данные мне нужны, я добавляю их в качестве параметра или добавляю их в объект параметра. Получение остальной части кода для соответствия этому новому интерфейсу обычно зависит от некоторого класса-посредника.
Однако, как я уже сказал, при написании бизнес-уровней необходимо учитывать многое, в том числе производительность. Подход выше был полезен в последнее время, потому что у меня еще нет прав на контроль версий или схему базы данных. Я работаю в темной комнате, и до сих пор только понимаю требования.
Пишите с тестированием в уме
Использование внедрения зависимостей может быть полезно для предварительного проектирования хорошей архитектуры. Попробуйте подумать о том, как вы будете тестировать свой код, не обращаясь к базе данных или другому сервису. Это также подходит для небольших, многократно используемых классов, которые могут работать в нескольких контекстах.
Заключение
Я пришел к выводу, что идеального бизнес-уровня на самом деле не существует. Даже в одном приложении могут быть случаи, когда один подход работает только 90% времени. Лучшее, что мы можем сделать, - это написать простейшую вещь, которая работает. Долгое время я избегал DTO и обернул ADO.NET DataRows объектами, чтобы обновления сразу записывались в базовый DataTable. Это была ОГРОМНАЯ ошибка, потому что я не мог копировать объекты, и ограничения вызывали исключения в странные времена. Я сделал это только для того, чтобы явно не задавать значения параметров.