Search
Write a publication
Pull to refresh
79
0
Vladimir @vkhorikov

User

Send message
LazyLoad нельзя использовать, чтобы избежать этого?

LazyLoad приводит к ошибкам доступа в случае если к коллекции идет обращение когда сессия уже закрыта. Получить на клиенте количество ордеров таким образом не получится
Как правило, Value Object-ы (так же как и Entities) не используются для передачи данных между приложениями. В целом, в простых случаях (как например в вашем) Value Object-ы действительно можно использовать как DTO, но опять же — это до тех пор, пока в них не скопилось достаточно логики.

Хорошей практикой считается изолировать домен приложения. На практике это означает, что доменные классы (Entities and Value Objects) не должны знать о том, как они сериализуются. В более-менее сложных случаях этого трудно достичь если сериализовывать их напрямую.
Мнение, которое вы высказали, и послужило причиной написания этой статьи.
Value Object — иммутабельные объекты
Это верно.
Они как бы строительные кирпичики для Entity
Это тоже верно.
Никакой логики в них быть не должно
Вот это уже неверно. Value Object-ы вполне себе могут содержать логику. Более того, Эванс и ко рекомендуют помещать доменную логику именно в Value Object-ы там где это возможно, т.к. работать с ними проще из-за их неизменяемости. Хороший пример Value Object-а — DateTime в .NET. Неизменямый тип данных с большим количеством логики внутри.
POCO (POJO, PODS) — это принцип организации данных
POCO — это в первую очередь принцип, который говорит о том, что при моделировании предметной области следует использовать настолько простые классы, насколько возможно. Это понятие никак не связано с DTO (кроме того, что DTO тоже не следует наследовать от тяжеловесных компонент).
На самом деле

Что-то не вижу как сказанное вами противоречит тому, что написано в статье
Еще хотел добавить. Пожалуй главный плюс подхода с Maybe для меня в том, что он улучшает читаемость кода благодаря тому, что мы разделяем нулевые и ненулевые типы.
1. Согласен

Проверяются все входящие и выходящие значения. Т.е. в вашем примере NRE будет тут:

var customer = CustomerService.GetCustomer(); // будет NRE
Console.WriteLine(customer.Name);

Не совсем так. Проверка на нал действительно идет в ран-тайме, но мы получаем ошибку компилятора в случае если используем нулевую ссылку там где подразумевалась ненулевая.
Code annotations от решарпера мне не нравятся тем, что
1) Это всего лишь warning
2) Используется opt-in схема. Т.е. все типы по умолчанию нулевые. По-хорошему нам нужно обратное поведение — сделать все типы по умолчанию ненулевыми и затем opt-out в случае если какой-то из них нулевой.

Но вообще Code annotations и Code Contracts — тоже вполне себе хорошая альтернатива
Использовать исключения для валидации — плохая практика. Тут более подробно на эту тему: habrahabr.ru/post/263685
Запретить не получится. Но я бы поспорил с посылкой этого утверждения. Программисты-коллеги — друзья, а не враги, цель нового класса EmailStrong — не запретить им что-то делать, а подсказать, направить на правильный путь. Ну и плюс общение между коллегами должны быть intensive, чтобы все были в курсе нововведений.
А что мешает использовать методы со старыми сигнатурами?

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

… и теперь сломался ранее работавший маппинг.

Маппинг куда? Если речь про ORM, то они умеют памить на protected setter-ы. В EF это посложнее сделать, в NH — попроще.
Понять — по сигнатуре метода. Т.е. какие-то методы будут работать только с новыми имейлами, для других — мы оставляем как было.

лучше все-таки использовать сеттеры, а не методы

Здесь как раз пригодится сделать небольшие методы-сеттеры для обозначения новых инвариантов класса.
особенно учитывая, что где-то присваивать можно (мало ли, мы данные из системы в систему гоним). Опять-таки, в систему типов этот запрет присвоения уже не обернешь, снова боль.

Обернуть можно. Где-то метод принимает старый Email, а где-то — только новый EmailStrong, который является наследником старого Email.
Еще раз посмотрел на код. Да, вы правы.
Старался сделать примеры как можно проще, не хотел накручивать какую-то логику поверх обычного изменения имейла и нэйма.
По поводу ORM — обычная практика в таких случаях создавать интернал коллекцию для ORM и внешнюю read-only для клиентов класса
Good points.

1) По поводу ручного биндинга — вы правы, здесь теряется часть встроенного функционала, который есть в ASP.NET. Это вопрос взвешивания «за» и «против». Для меня плюсы более выразительной доменной модели перевешивают минусы необходимости писать подобный код вручную. Для более простых проектов вполне можно отказаться от этого подхода и делать по старинке.

Но при этом для других свойств (скажем, City и Country) такой проверки нет, и теперь программисту нужно помнить про два разных механизма. Не ужас, но неудобно.

Если у City и Country есть какие-то более-менее сложные инварианты, то их тоже стоит обернуть в классы-обертки.

2) По поводу невалидных данных в БД — отличный point. Есть два распространенных подхода к проблеме. Первый — вместе с ужесточением инвариантов писать скрипты для миграции данных в БД, чтобы они соответствовали новым инвариантам. Второй — создавать отдельный класс, к примеру EmailStrong для хранения имейлов, инварианты в которых были ужесточены и не давать присваивать кастомерам объекты старого Email, только нового. Со временем, когда БД придет в соответствие с новыми требованиями, старый Email удаляется, новый EmailStrong переименовывется в Email. Второй вариант сложнее, я как правило пользуюсь первым.
Отдельные методы-сеттеры сделаны для большей выразительности. Всю ту же логику можно написать и в сеттере свойства, безусловно, разницы в коде при этом не будет.
С ридонли полями примерно так же как и с private set пропертями в плане читаемости. Т.е. для того чтобы понять является ли класс изменяемым нам все равно нужно смотреть внутрь этого класса, по сигнатуре это непонятно. Тут бы помогло ключевое слово immutable.

>P.S. Почему статья не оформлена как перевод?
Я думаю свои статьи не очень правильно оформлять переводом, хотя тут не уверен насчет правил хабра.
Вы правы. Пост писался еще до 6го шарпа
Да, под предусловиями я имею ввиду именно предусловия контрактов. Я выделяю предусловия (и оставляюю за скобками инварианты и постусловия), т.к. предусловия обычно путают с валидацией приходящих извне данных, с постусловиями и инвариантами в этом плане проще.

Конкретно эту книгу Мейера я не читал, но вообще первоисточник моих знаних о контрактах именно Мейер, конкретно эта его книга: www.amazon.com/Object-Oriented-Software-Construction-CD-ROM-Edition/dp/0136291554
Это часть публичного API одного из классов доменной модели.

Information

Rating
Does not participate
Registered
Activity