Основная идея ООП состоит в том, что данные и поведение (на основе этих данных) неразделимы, и они связаны идеей объекта класса. У объекта есть данные и методы, которые работают с этим (и другими данными). Очевидно, что по принципам ООП объекты, представляющие собой просто данные (например, структуры C), считаются анти-паттернами.
Все идет нормально.
Проблема в том, что я заметил, что мой код в последнее время все больше и больше движется в направлении этого анти-паттерна. Мне кажется, что чем больше я пытаюсь добиться скрытия информации между классами и слабо связанными проектами, тем больше мои классы становятся смесью чистых данных без классов поведения и всего поведения без классов данных.
Я обычно проектирую классы таким образом, чтобы свести к минимуму их осведомленность о существовании других классов и свести к минимуму их знание интерфейсов других классов. Я особенно применяю это сверху вниз, классы более низкого уровня не знают о классах более высокого уровня. Например:
Предположим, у вас есть общий API для карточных игр. У вас есть класс Card
. Теперь этот Card
класс должен определить видимость для игроков.
Один из способов иметь boolean isVisible(Player p)
на Card
классе.
Другой должен иметь boolean isVisible(Card c)
в Player
классе.
Мне особенно не нравится первый подход, поскольку он предоставляет знания о Player
классе более высокого уровня классу более низкого уровня Card
.
Вместо этого я выбрал третий вариант, где у нас есть Viewport
класс, который, учитывая Player
и список карт, определяет, какие карты видны.
Однако этот подход лишает Card
и Player
классы возможной функции-члена. После того, как вы это делаете для других вещей , чем видимость карт, вы остались с Card
и Player
классами , которые содержат исключительно данные , как и все функциональные возможности реализованы в других классах, которые в основном классы, не содержащие данных, только методы, как Viewport
выше.
Это явно противоречит основной идее ООП.
Какой правильный путь? Как мне решить задачу минимизации взаимозависимостей классов и минимизации предполагаемых знаний и взаимосвязей, но без замыкания на странный дизайн, когда все низкоуровневые классы содержат только данные, а высокоуровневые классы содержат все методы? У кого-нибудь есть какое-то третье решение или взгляд на дизайн класса, который избегает всей проблемы?
PS Вот еще один пример:
Предположим, у вас есть класс, DocumentId
который является неизменным, имеет только одного BigDecimal id
члена и получателя для этого члена. Теперь вам нужно где-то иметь метод, который бы дал DocumentId
возврат Document
этого идентификатора из базы данных.
Вы:
- Добавьте
Document getDocument(SqlSession)
метод вDocumentId
класс, внезапно представив знания о вашем постоянстве ("we're using a database and this query is used to retrieve document by id"
), API, используемом для доступа к БД, и тому подобное. Также этот класс теперь требует JAR-файла персистентности только для компиляции. - Добавьте какой-то другой класс с методом
Document getDocument(DocumentId id)
, оставивDocumentId
класс мертвым, без поведения, как структурный класс.