The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
Принцип единственной ответственности, согласно книге «Чистый код» Роберта Мартина, означает, что «класс должен изменяться только по одной причине». Давайте попробуем расшифровать это довольно неопределенное утверждение и посмотрим, как оно поможет нам создавать лучшее объектно-ориентированное программное обеспечение. Если, конечно, поможет.
Я уже упоминал принцип единственной ответственности в своей статье о SOLID, говоря, что он на самом деле не помогает программистам понять хорошо знакомую концепцию “высокой связности”, которую ввел Ларри Константин еще в 1974 году. Теперь давайте рассмотрим это на примере и проанализируем, как мы можем улучшить класс с учетом этого принципа единственной ответственности и станет ли он более объектно-ориентированным.
Давайте рассмотрим класс AwsOcket
из jcabi-s3 (я упростил код):
Поправьте меня, если я не прав, но согласно SRP этот класс отвечает за слишком много вещей: 1) проверку существования объекта в AWS S3, 2) чтение его содержимого и 3) изменение его содержимого. Верно? Это плохой дизайн и его нужно изменить.
Чтобы изменить его и сделать ответственным только за одну вещь, мы должны ввести геттер, который будет возвращать клиента AWS, а затем создать три новых класса: ExistenceChecker
(ПроверяльщикСуществования), ContentReader
(ЧитальщикСодержимого) и ContentWriter
(ЗаписальщикСодержимого). Они будут проверять, читать и записывать. Сейчас, чтобы прочитать содержимое и вывести его в консоль, я в настоящее время делаю это:
Завтра, если я проведу рефакторинг класса, я буду делать следующее:
Помимо того факта, что эти проверяющие, читатели и писатели на самом деле не являются классами, а чистыми хранилищами процедур, использование этого ocket
превращается в кошмар. Мы больше не можем знать, что произойдет с ним, когда мы передадим его куда-то. Мы не можем, например, гарантировать, что содержимое, которое поступает из него, будет расшифровано или декодировано на лету. Мы просто не можем его декорировать. Он больше не является объектом, а является хранилищем клиента AWS, который используется некоторыми другими классами где-то.
Да, теперь он отвечает только за одну вещь: инкапсуляцию ссылки на клиента AWS. Это прекрасный класс с точки зрения принципа SRP. Но он больше не является объектом.
То же самое произойдет с любым классом, если применить принцип SRP в полной мере: он станет хранилищем данных или других объектов с набором сеттеров и геттеров. Может быть, с одним дополнительным методом помимо них.
Мой поинт в том, что SRP - неправильная идея.
Создание маленьких и связных классов - это хорошая идея, но сделать их ответственными “за одну вещь” - это обманчивое упрощение понятия “высокой связности”. Это только превращает их в глупых перевозчиков чего-то другого, вместо того, чтобы быть инкапсуляторами и декораторами более мелких сущностей для создания более крупных.
В нашей борьбе за эту фальшивую идею SRP мы теряем гораздо более важный принцип, который на самом деле связан с истинным объектно-ориентированным программированием и мышлением: инкапсуляцию. Гораздо важнее то, за сколько вещей отвечает объект, чем то, насколько тесно он защищает инкапсулированные сущности. Монструозный объект с сотней методов гораздо меньшая проблема, чем DTO с пятью парами геттеров и сеттеров! Это потому, что DTO распространяет проблему по всему коду, где мы даже не можем ее найти, в то время как монструозный объект всегда перед нами и мы всегда можем его рефакторить на более мелкие части.
Инкапсуляция идет впереди, размер идет следующим, если вообще.
Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-17 at 16:48