Основная идея ООП состоит в том, что данные и поведение (на основе этих данных) неразделимы, и они связаны идеей объекта класса. У объекта есть данные и методы, которые работают с этим (и другими данными). Очевидно, что по принципам ООП объекты, представляющие собой просто данные (например, структуры 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класс мертвым, без поведения, как структурный класс.