Почти во всех презентациях, в которых я объясняю свой взгляд на объектно-ориентированное программирование, есть кто-то, кто разделяет такой комментарий: «Если мы последуем вашему совету, у нас будет так много маленьких классов». И мой ответ всегда один и тот же: «Конечно, будем, и это здорово!» Я искренне верю, что даже если вы не можете считать «много классов» добродетелью, вы не можете назвать это недостатком действительно объектно-ориентированного кода. Однако может наступить момент, когда классы становятся проблемой; Давайте посмотрим, когда, как и что с этим делать.
Ранее упоминалось несколько «правил», которые, если они применяются, очевидно, приведут к большому числу классов, в том числе:
а) все публичные методы должны быть объявлены в интерфейсах;
б) объекты не должны иметь более четырех атрибутов (раздел 2.1 Элегантных объектов);
с) статические методы не допускаются;
d) конструкторы должны быть без кода;
e) объекты должны содержать менее пяти открытых методов
Типы в ООП составляют ваш словарный запас, который объясняет мир вокруг вашего кода.
Самой большой проблемой, конечно, является поддержка кода: «Если вместо 50 более длинных классов у нас будет 300 более коротких, то код станет менее читаемым». Это, безусловно так, если вы задумаете их неправильно.
Типы (или классы) в ООП составляют ваш словарный запас, который объясняет мир вокруг вашего кода - мир, в котором живет ваш код. Чем богаче лексика, тем мощнее ваш код. Чем больше типов вы имеете, тем лучше вы сможете понять и объяснить мир.
Если ваш словарный запас достаточно большой, вы скажете что-то вроде:
Прочитайте книгу, которая находится на столе.
С гораздо меньшей лексикой, такая же фраза будет звучать так:
Сделай это с тем, что на этой штуке.
Очевидно, что легче читать и понимать первую фразу. То же самое происходит с типами в ООП: чем больше их в вашем распоряжении, тем более выразительным, ярким и читаемым является ваш код.
К сожалению, Java и многие другие языки не разработаны с учетом этой концепции. Пакеты, модули и пространства имен не помогают, и обычно мы получаем имена типа:
AbstractCookieValueMethodArgumentResolver (Spring)
CombineFileRecordReaderWrapper (Hadoop).
Мы стараемся как можно больше упаковать семантику в имена классов, чтобы их пользователи не сомневались ни секунды. Затем мы пытаемся поместить как можно больше методов в один класс, чтобы облегчить жизнь пользователям; Они будут использовать подсказки IDE, чтобы найти правильный.
Это совсем не ООП.
Если ваш код объектно-ориентирован, ваши классы должны быть маленькими, их имена должны быть существительными, а имена их методов должны быть только одним словом. Вот что я делаю в своем коде, чтобы это произошло:
Интерфейсы - это существительные. Например, запрос, директива или домен. Исключения отсутствуют. Типы (также известные как интерфейсы в Java) являются ключевой частью моего словаря; Они должны быть существительными.
Классы имеют префикс. Мои классы всегда реализуют интерфейсы. Благодаря этому я могу сказать, что они всегда являются запросами, директивами или доменами. И я всегда хочу, чтобы их пользователи помнили об этом. Префиксы помогают. Например, RqBuffered является буферизованным запросом, RqSimple - это простой запрос, RqLive - это запрос, который представляет «живое» HTTP-соединение, а RqWithHeader - это запрос с дополнительным заголовком.
Альтернативный подход - использовать имя типа как центральную часть имени класса и добавить префикс, который объясняет детали реализации. Например, DyDomain - это домен, который сохраняет свои данные в DynamoDB. Когда вы знаете, для чего предназначен этот префикс Dy, вы можете легко понять, что такое DyUser и DyBase.
В приложении среднего размера или в библиотеке будет 10-15 префиксов, которые вам нужно запомнить, не более. Например, в Takes Framework имеется 24 000 строк кода, 410 файлов Java и 10 префиксов: Bc, Cc, Tk, Rq, Rs, Fb, Fk, Hm, Ps и Xe. Не так сложно запомнить, что они имеют в виду, верно?
Из всех 240 классов самым длинным именем является RqWithDefaultHeader.
Я нахожу такой подход к наименованию классов довольно удобным. Я использовал его в этих проектах с открытым исходным кодом (в GitHub): yegor256 / takes (10 префиксов), yegor256 / jare (5 префиксов), yegor256 / rultor (6 префиксов) и yegor256 / wring (5 префиксов).
Комментариев нет:
Отправить комментарий