У нас есть список книг в объекте books
. Как мы можем удалить одну книгу из него, зная ее идентификатор? Мы можем использовать books.removeById(42)
. В качестве альтернативы, мы можем найти ее с помощью books.findById(42)
и затем вызвать b.remove()
. Какой вариант предпочтительнее, и почему? Второй вариант лучше. Не только потому, что он более объектно-ориентированный, но также из-за нескольких практических преимуществ.
Что, если мы хотим расширить алгоритм удаления? Например, предположим, что мы хотим выводить сообщение в журнал каждый раз, когда книга удаляется.
Если мы следуем принципу открытости-закрытости, мы должны избегать изменения существующих классов Book
или Books
. Вместо этого мы хотим либо расширить, либо декорировать их. Декоратор - идеальный выбор, если мы хотим избежать реализации наследования.
Если мы используем removeById()
, мы должны декорировать объект books
. Если мы используем remove()
, мы можем декорировать отдельную книгу, полученную через findById()
. Последний подход может быть более связанным, поскольку его декорируемый объект, вероятно, меньше и сосредоточен:
Handling Missing or Non-Deletable Books
Что, если книга не найдена или не может быть удалена? Подход removeById()
не очень хорошо поддерживает шаблон Null Object. Он заставляет нас бросать исключение - или, что еще хуже, возвращать false
, что противоречит принципу CQRS.
С другой стороны, возврат объекта, даже null или фиктивного объекта, предлагает более гибкое обработку ошибок. Например, мы можем безопасно получить доступ к title()
, зная, что книга была успешно найдена - или перехватить и повторно вызвать исключения с более подробным контекстом:
Decoupling Retrieval and Deletion
Что, если извлечение и удаление объекта происходят в коде далеко друг от друга?
Если books
знает, как найти, и book
знает, как удалить, мы хорошо разделяем ответственности. Это также позволяет книге быть неизменяемой и инкапсулировать свой собственный идентификатор, уменьшая утечку внутренних данных:
Как только идентификатор обернут внутри книги с помощью findById()
, он больше никогда не должен просочиться наружу. Это снижает количество обнаженных данных, к которым имеют доступ части кода, которым это не требуется.
Чем меньше данных видно, тем лучше дизайн — по крайней мере, с точки зрения ООП.
Таким образом, использование findById()
, за которым следует remove()
, более полно принимает во внимание объектно-ориентированные принципы. Это позволяет более чистое расширение, лучшую обработку ошибок и более плотную инкапсуляцию.
Translated by ChatGPT gpt-3.5-turbo/42 on 2025-06-22 at 14:22