Ответ
Ответ не найден
Ответ 18+ 🔞
Слушай, вот сидишь ты такой, пишешь на Python, думаешь — ну всё, я ж бог ООП, щас накодирую архитектуру, от которой все ахнут. А потом, блядь, через полгода смотришь на свой же код и думаешь: «Что за хуйню я тут написал? Это ж пиздец, а не код».
Вот, например, берёшь ты класс User. Ну, казалось бы, что может быть проще? Пользователь, имя, почта, всё дела. А потом начинается: «А давайте добавим скидку для премиум-пользователей! А давайте ещё логин через соцсети! А давайте ещё историю заказов!» И твой красивый класс превращается в этого монстра:
class User:
def __init__(self, username, email, password, social_login_token=None, premium_status=False, discount_rate=0, order_history=[], last_login_ip=None, avatar_url=None, is_verified=False, two_factor_enabled=False, ...):
self.username = username
self.email = email
self.password = password # Который, ясное дело, хранится в открытом виде, потому что кому охота с хешами возиться?
# ... и ещё 40 полей, блядь
И ты уже сам не понимаешь, где тут логика, а где просто свалка для данных. Это ж пиздопроебина, а не класс! А потом вызываешь этот конструктор и нужно передать двадцать аргументов, половина из которых None. Удивление пиздец!
А всё почему? Потому что нарушен принцип единственной ответственности, ёпта! Класс должен делать что-то одно. Не тащи в него всё, что попадётся под руку. Сделай отдельный UserProfile, отдельный AuthCredentials, отдельный OrderHistory. Пусть каждый занимается своим делом, а не как эта мартышлюшка — и танцует, и поёт, и в уме числа перемножает.
Или вот ещё история: наследование. Ну, думаешь, о, сейчас я сделаю супер-пупер-базовый класс Vehicle, а от него унаследую Car, Bike, Spaceship. А потом выясняется, что у велосипеда нет двигателя, а метод start_engine() он всё равно наследует. И ты либо переопределяешь его, чтобы он выдавал raise NotImplementedError (что уже, блядь, криво), либо начинаешь городить хуй с винтом — промежуточные классы, миксины... В итоге получается иерархия, в которой разобраться может только тот, кто её писал, да и то через месяц уже ни хуя не помнит.
class Vehicle:
def start_engine(self):
print("Vroom vroom!")
class Bicycle(Vehicle):
def start_engine(self):
raise AttributeError("У меня нет двигателя, я ж велосипед, блядь!")
Вот это и есть классический пример «проблемы квадрата-прямоугольника». Кажется, что квадрат — это частный случай прямоугольника, но если у прямоугольника есть методы set_width и set_height, то для квадрата они ведут себя пиздец как странно. Наследование — не про «является», а про «может быть использован вместо». Если не уверен — лучше композицию, блядь. Чувствуешь подозрение, что наследование тут лишнее? Скорее всего, так и есть.
И главное — тестирование. Когда у тебя класс, который делает всё, протестировать его — это отдельный ад. Нужно mock'ить пол-вселенной, чтобы проверить один маленький метод. А если он разбит на маленькие, независимые модули, то и тесты пишутся за пять минут, и баги ловятся сразу. Волнение ебать, когда понимаешь, что из-за своей же поспешной архитектуры теперь нужно писать в десять раз больше тестового кода.
Короче, суть в чём: прежде чем нагородить очередной класс-бог, остановись и подумай, э, бошка, думай. «А действительно ли это одна ответственность? Не пытается ли этот объект жить за десятерых?» Спроси себя: «А что будет, если мне завтра нужно будет изменить вот эту часть? Придётся лезть в этот же класс?» Если ответ «да», то что-то пошло не так.
Помни, хорошая архитектура — это не когда нечего добавить, а когда нечего убрать. Всё должно быть на своих местах, как болты в двигателе. А не как в том анекдоте про чукчу и компьютер: «Хорошая вещь. И гвозди забивать можно, и как пресс использовать». Вот так и с классами-богами — вроде всё умеет, но нахуй никому не нужно. Чих-пых тебя в сраку с такой архитектурой!