Предупреждение: Данный пост пропах субъективной оценкой и холиварными суждениями.
Давайте поговорим про именование классов!
Делая код-ревью или просматривая чужой код я часто натыкаюсь на всевозможные классы с именами типа Parser, Decoder, Encoder.
Еще хлеще, когда в таком коде множество статических методов.
Как Вы думаете, насколько это валидно?
Лично у меня всегда возникает вопрос - “Почему колесо не называется катало?”
Хочется подискутировать на этот момент.
Вот проектируете вы новый супер-сервис, который парсит входящее откуда-то сообщение, расшифровывает его и складывает в БД, например.
Так, ну тут у нас будет определенно какой-то хендлер, куда сообщение это валится, из которого мы сначала прогоним это сообщение через Decoder, а затем Parser и остаток сложим в БД.
Логично? Ну все, пишем код.
Но не все так просто, как кажется.
Может измениться тип шифрования? Может. Сегодня тебе присылают сообщение в base64, завтра с битовым сдвигом и контрольной суммой.
И что будем делать в таком случае? Писать еще один метод в классе Decoder. Или создадим новый класс, например NewDecoder.
Может измениться структура сообщения? Может. Сегодня тебе шлют XML, завтра Yaml. Что делаем? Конечно же YamlParser.
А еще бывало такое, ну признайтесь себе, когда в какой-нибудь Parser было желание засунуть еще и валидатор и математику какую-нибудь. Бывало ведь?)
В итоге такой класс начинает и парсить, и валидировать, и за кофеём бегать и штаны гладить.
Вот таким образом мы заимеем кучу сущностей, не передающих намерения разработчика, но в которую, как в коробку скидывают всё подряд и засовывают под стол или в дальний шкаф.
Так как же быть? Связывайте классы с реальными вещами и называйте классы тем, чем они являются. Parser - не очень реальная сущность, а что-то абстрактное, что умеет парсить сообщение. А сообщение - это конкретный объект.
Валится вам на вход какое-то сообщение - назовите класс Message, задекларируйте методы - decode_base64/encode_base64/parse_to_dict.
Если сообщение XML - сделайте класс XmlMessage, в котором отнаследуетесь от Message и перезагрузите нужные методы. Может и нового добавите.
Если Yaml - YamlMessage.
“Но ведь ничего не изменилось? Мы также плодим кучу классов и сколько хотим методов - столько и пишем!”.
Еще как изменилось. Давайте приведу пример с классом Parser:
decoded_message = Decoder(msg).decode_message()
parsed_message = Parser(msg).parse_xml()
save_to_db(parsed_message)
А теперь приведу пример с классом Message:
message = XmlMessage(msg)
message.decode()
message.parse()
message.save_to_db()
Какие различия мы видим?
Во первых это интуитивно-понятное взаимодействие с классом.
Во вторых мы инкапсулируем логику - нам не нужно знать что парсить и как парсить.
А в третьих, это еще и красивей выглядит :)
То есть мы говорим “Колесо - катись. Колесо - остановись.”, вместо “О силы трения качения, используя свою великую мощь - дайте мне катящееся колесо”.
Давайте подискутируем про это.
Может я в корне не прав и надо плодить парсеры с декодерами, а колесо называть каталом?