Проектирование
Начало хорошего кода — это всегда проектирование. Программисты, которые не умеют утихомирить страсть к написанию кода, этим опуская проектирование, пишут обычно быстро, но не качественно. Я это знаю, так как сам имел ту же проблему. Проектирование дает возможность взглянуть на систему, которой еще фактически нету, продумать правильную структуру приложения и данных, увидеть тонкости, риски, подумать о производительности и безопасности. При этом проектирование это не только прерогатива начала проекта. Проектирование — это неотъемлемая часть, при разработке любой «Feature».
Начать проектировать можно очень легко. Всегда держите на рабочем месте блокнот и несколько цветов ручек. Прежде чем писать код, нарисуйте схему — как приложение будет работать в целом, UML-диаграмму классов (продумайте как можно с минимальным количеством классов, достигнуть максимального результата), структуру баз данных (оптимизируйте БД еще до ее создания, подумайте какие запросы у вас должны будут «бегать» к вашей БД, продумайте индексы, конечно же нормализируйте вашу модель данных).
Для тех же целей подойдет простая программа для проектирования starUML. Минус ее в том, что нельзя нормально устанавливать мощность отношений (кратность), но сам интерфейс очень удобный.
Проектировать нужно даже для того, чтобы потом не пришлось рефакторить структурные ошибки, а еще хуже переписывать вообще весь модуль.
Несколько принципов, которые точно нужно знать при проектировании классов вашей «Feature»:
1. SOLID (single responsibility, open-closed, Liskov substitution, interface segregation и dependency inversion)
Это основа основ в проектировании классов. Если вы еще не знакомы с SOLID, здесь можно ознакомиться.
2. DRY (do not repeat yourself)
Повторяющейся функционал делает приложение громоздким, а его поддержку более дорогостоящей и неудобной. Это относится как к модулям, так и к небольшим фрагментам кода.
К примеру:
— Вместо того, чтобы использовать три строчки кода в нескольких местах, можно поместить их в функцию и использовать всего лишь одну строку кода — вызов функции.
— Вместо использования функции progress50(), лучше применить более абстрактную progress($percent).
— Отдавать предпочтение внешним зависимостям между модулями, внутренним (DI), что делает модуль более гибким и позволяет его использовать в нескольких местах.
3. KISS (keep it simple, stup...)
Чем проще ваше решение для сложной задачи, тем более оно совершенно, так же это правило работает в обратную сторону. Чтобы научиться делать простые решения, нужно научиться разделять вашу задачу на очень маленькие подзадачи. Двигаясь от меньшего к большему. В последствии, мы получаем результат сложной задачи.
К примеру:
Вам нужно написать класс для генерации Excel отчета с вашей БД. Нужно весь отчет разделить на части: установка заголовков таблицы, вывод статистических данных в документ, вывод подвала документа, создание диаграммы. Некоторые части функционала можно вынести в отдельные классы, что даст возможность использовать их повторно.
Стиль кода
Рефакторинг стиля кода вообще не влияет на производительность приложения. Тем не менее, он дает преимущество для его читаемости и поддержки. Другой программист должен легко читать ваш код, без вникания в реализацию деталей, а это, конечно же, экономит время и деньги.
Стандарт стиля кода (и не только) PSR (PHP Standards Recommendations), здесь можно ознакомиться. Содержимое на английском языке, так как английский более ясно дает понять степень применения одного или другого правила («MUST», «MUST NOT», «REQUIRED», «SHALL», «SHALL NOT», «SHOULD», «SHOULD NOT», «RECOMMENDED», «MAY», and «OPTIONAL»).
Несколько замечаний, которые автор счел важными:
1. Ознакомьтесь с PHPDOC для написания комментариев к вашему коду.
2. Лучший комментарий — это правильно названный класс, метод, параметр или переменная.
3. Используйте утилиты PHPMD, PHPCS, их применение шире, чем только для определения несоответствий в стиле кода. Вот документация: PHPMD, PHPCS.
4. Используйте продвинутое IDE.
Рефакторинг в чистом виде
Очень простая аксиома — на продакшн должен попадать только код, прошедший рефакторинг. Иногда после разработки вы сами делаете рефакторинг, что очень даже не плохо (к примеру, разработка через тестирование вообще включает рефакторинг, как обязательный шаг, так как изначально пишется «работающий код», а потом уже «чистый»), но для того, чтобы код был по-настоящему качественным, он должен пройти проверку кода (code-review) другим программистом. Если проект позволяет выделить время на проверку кода, то на таком проекте ты будешь учиться писать код чище и чище, что в последствии приведет к автоматическому написанию качественного кода.
Я помню, как работал на одну компанию, и проверку кода у меня делал человек, который не всегда мог сдерживать свои эмоции, из-за чего о моем не чистом коде слышали все в open space. Поэтому мне приходилось учиться писать качественный код, очень быстро, чтобы избежать подобных случаев.
Вернемся к теме. В этой части статьи я бы хотел дать несколько практических подходов к рефакторингу, которыми пользуюсь сам.
1. Длинные методы (лучше разделить функционал на несколько методов).
2. Громоздкие классы (ваш класс должен исполнять одну функциональную задачу в вашей системе).
3. Неясная структура класса (методы в хаотическом порядке, конструктор в середине класса, вместо констант — магические значения в коде — класс должен легко отображать, что он делает в правильной последовательности).
4. Слишком много параметров в методе (некоторые расчеты можно сделать внутри метода, используя внутренние константы, значения полученные с атрибутов и геттеров).
5. Классы, содержащие одинаковые переменные и методы. Проблему можно решить через создание дополнительного класса).
6. Сложно читаемый IF (выражение можно вынести в отдельную переменную и разделить на логические части, которые также вынести в переменные, если много проверок на null, то лучше всего использовать NullObject — количество проверок значительно уменьшится).
7. Громоздкий SWITH (выносим в отдельный метод).
8. Использование наследования из-за одинаковых методов и свойств, в разных по своей сути сущностях (кошка и стул имеют ноги, но их нельзя группировать в категорию «животные»).
9. Слишком большое количество маленьких классов для выполнения одной задачи, которые в последствии сложнее поддерживать.
10. Слишком сложный функционал в одном классе, который можно разделить на несколько классов.
11. Класс делает слишком мало, чтобы его оставлять в системе.
12. «Мертвый код» — его следует удалить.
13. Не использованные структуры классов, которые вы проектировали на будущее, но они так и не пригодились — такие лучше удалить.
14. Методы класса больше используются в другом классе, а в своем вообще не используются или же реже (стоит перенести метод в тот класс, где он больше используется).
15. Слишком длинная цепочка вызовов ($a->b()->c()->d()->e()), в этом случае стоит создать дополнительные методы.
16. Класс, содержащий только один метод, который создает другой класс. (Такой класс нужно использовать с умом, к примеру, для паттерна «Прокси», в противном случае этот класс только увеличивает время и ресурс на поддержку проекта).
17. Слишком много действий в конструкторе. (Конструктор должен только устанавливать свойства класса, если же в конструкторе создаются другие классы, происходят какие-то расчеты, то это делает его сложным для понимания, приходится вникать в суть реализации. Чтобы создать объект и выполнить какие-то действия, добавьте статический метод create($param1, ...), который создаст экземпляр класса с дополнительными действия над ним, этот метод можно назвать более подходящим к тому, что он будет все же делать).
Список литературы
» Source Making
» PSR
» UML
Комментарии (61)
alexhott
15.08.2016 14:18-2А еще проектировать должен проектировщик, периодически консультируясь с постановщиком и кодером
Delphinum
15.08.2016 17:14Часто проектировщик и кодер (брр… не люблю это слово) это одно и то же лицо.
Fesor
15.08.2016 17:47+2проектировщик должен кодить, что бы адекватно все было. Если он только проектирует — это бесполезная трата времени и ресурсов.
ilnuribat
15.08.2016 18:21+1Такая модель практиковалась на моей прошлой работе — это действительно идеальный вариант.
Проектировщик — программист со стажем более 20 лет, который досконально знает все подводные камни, просто «рисует», как должно быть, а также может и ТЗ составить. Конечный программист реализует тело функции, у которого уже есть имя, входные-выходные параметры и что она должна делать.
Так вот, этот человек на моей старой работе, сам никакого когда не пишет — только дает указания, как сделать то или иное, а также и советуется с программистами.
Так что, в хороших компаниях всё построено именно так, как Вы говоритеDelphinum
15.08.2016 18:30+1Конечный программист реализует тело функции, у которого уже есть имя, входные-выходные параметры и что она должна делать
Называйте вещи своими именами, не «конечный программист», а «печатная машинка».
SamDark
15.08.2016 15:03+2Ещё стоит упомянуть принцип разделения контекстов, из которого следует, что не всё то DRY, что на DRY похоже.
AndreyRubankov
15.08.2016 15:06оптимизируйте БД еще до ее создания, подумайте какие запросы у вас должны будут «бегать» к вашей БД, продумайте индексы, конечно же нормализируйте вашу модель данных
Совет правильный — ко всему нужно подходить с умом. Но тут нужно быть осторожными, т.к. очень легко свалиться в Преждевременную оптимизацию. А от этого в перспективе вреда будет на много больше, чем пользы.
Например, хорошо нормализованная база данных на старте проекта в перспективе выльется в большое количество запросов или в сложный запрос с множеством джоинов, чтобы вытянуть одно поле.samizdam
15.08.2016 20:59Совет содержит взаимоисключающие параграфы.
>>> оптимизируйте БД еще до ее создания… конечно же нормализируйте вашу модель данных
преждевременная оптимизация, имхо зло. А вот совершенно нормализованная структура, ну никак не сможет быть оптимальной, с точки зрения производительности.
К базе данных применимы свои методики рефакторинга, описанные кстати как в литературе и так и интернет статьях.
А, так, после труда Фаулера, и упомянутого в комментариях Макконнелла, сложно что-либо добавить к теме. Для себя нового не почерпнул, но считаю, подобные статьи всё же на правильную мельницу воду льют: глядишь, кто-то с сотой статьи всерьёз для себя вопросом задумается, и до первоисточников дойдёт.
ErickSkrauch
15.08.2016 15:26Я бы ещё добавил про максимальное использование phpdoc блоков для прописывания типов переменных, получаемых, скажем, из того же DI, что в последствии значительно упростит статический анализ в «продвинутой IDE».
samizdam
21.08.2016 14:03С php 7 это уже мало актуально.
ErickSkrauch
21.08.2016 20:54Нет. Возможно, это актуально в том случае, когда ты внутри (условно) модели выносишь получение объекта из DI в метод. Ок, можно поставить возвращаемый тип как интерфейс этого объекта. Но что ты будешь делать в пободном кейсе (пример на Yii2):
$someResult = Yii::$app->myContainer->myMethod();
В таком случае уместно решить эту проблему 2-мя путями: использовать этот метод или же писать так:
/** @var MyContainerClass $myContainer */ $myContainer = Yii::$app->myContainer; $someResult = $myContainer->myMethod();
samizdam
21.08.2016 21:04Да, по поводу DI Вы правы, «этот метод» мы используем с Yii до сих пор, и после перехода на 7.
В тоже время можно писать в переопределённом Application геттеры для всех компонентов и статически типизировать возвращаемые значения. Приняв такое соглашение, можно вовсе обойтись без док-блоков.Fesor
21.08.2016 22:37Да, по поводу DI Вы правы
это не DI, это сервис локатор, в этом то и проблема.
Delphinum
22.08.2016 00:39Это как вы определили паттерн по вызову метода у переменной приложения? Или я что то упустил?
Fesor
22.08.2016 02:07+1ну вот смотрите. Это сервис локатор:
$myContainer = Yii::$app->myContainer;
То есть все динамичненько, и мы понятия не имеем какой тип у объекта хранящегося в
myContainer
.
А вот dependency injection:
class SomeClass { public function __construct(MyContainer $container) { // ... } }
То есть все зависимости и их типы декларируются явно и при таком раскладе никаких "проблем с автокомлитом" быть не может. Проблемы с определением типов могут быть только при использовании service locator.
Ну и в целом использование контейнера напрямую — моветон. Это можно делать только на уровне фреймворка.
Delphinum
22.08.2016 11:38-1Все равно не понял, что там ErickSkrauch дергал у контейнера и как вы узнали, что этот контейнер именно локатор. Ну да ладно, видимо это я дурак.
Fesor
22.08.2016 16:50Yii::$app->myContainer
вот это — сервис локатор. Что такое
myContainer
мне не известно. Как и статическому анализатору. Отсюда проблемы с автокомплитом. В случае инъекции зависимостей они декларируются как правило явно, и проблем быть не должно.Delphinum
22.08.2016 16:55$app это локатор? Может myContainer это локатор?
Fesor
22.08.2016 16:58в Yii вы к зависимостям обращаетесь как?
Yii::app->someComponent
илиYii::app->myContainer->get(SomeComponent::class)
?Delphinum
22.08.2016 17:25в Yii вы к зависимостям обращаетесь как?
Я хз, Yii не пользовался, потому и интересуюсь.Fesor
22.08.2016 17:36в любом случае. Если у вас есть что угодно, будь это
Yii::app->
или же$container->get
— это все сервис локатор. И возвращаемые типы можно узнать только в рантайме (или при помощи кастылей и плагинов к IDE).
В случае dependency injection получение зависимостей происходит сверху, а не по требованию. А стало быть зависимости и их типы прописаны явно. Мой комментарий относился преимущественно к этой фразе:
Возможно, это актуально в том случае, когда ты внутри (условно) модели выносишь получение объекта из DI в метод
и я пытаюсь объяснить что это никакого отношения к dependency injection не имеет. А сервис локатор и так признанный антипаттерн.
Delphinum
22.08.2016 17:38-1и я пытаюсь объяснить что это никакого отношения к dependency injection не имеет
Понятненько. Не увидел просто там ни SL, ни DI, вот и поинтересовался.
А сервис локатор и так признанный антипаттерн
А поделитесь ссылочкой.Fesor
22.08.2016 18:08+1Не увидел просто там ни SL
как жеж? когда мы просим какой-то объект (
Yii::$app
в нашем случае) дать нам зависимость — это service locator. Точно так же как ларавелевскиеCache::get
, симфоневый$controller->get('cache')
и тд.
А поделитесь ссылочкой.
и тут более подробнее по проблемам которые привносит хреново реализованный (а это 99% реализаций) сервис локатор:
http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/
- http://martinfowler.com/articles/injection.html#UsingAServiceLocator
В частности там описан "правильный" сервис локатор который решает большую часть проблем.
Справедливости ради, есть кейсы где сервис локатор норм. например в контроллерах: http://davedevelopment.co.uk/2016/06/01/service-locators-have-their-place.html
Delphinum
22.08.2016 18:12когда мы просим какой-то объект (Yii::$app в нашем случае) дать нам зависимость
Если мы просим какой то объект дать нам нашу зависимость, то да.
и тут более подробнее по проблемам которые привносит хреново реализованный...
Так проблема скорее не в SL, а в том, что он используется субъектами напрямую (агрегируется в субъектах). Разве нет?Fesor
22.08.2016 22:08а в том, что он используется субъектами напрямую (агрегируется в субъектах). Разве нет?
ну не только. В плане тестируемости самый удобный вариант это все же Dependency Injection. У DI есть свои недостатки, например необходимость делать прокси для лэйзи инициализации (что бы по мелочи не тянуть весь граф зависимостей а только по требованию). Это существенно усложняет реализацию. Но зато если использовать готовый контейнер — все мегаудобно.
SL банально проще.
Delphinum
22.08.2016 22:43Тот же Zend советует использовать качественно сконфигурированный SL, вместо DI, ибо:
* Проще отлавливать ошибки
* Проще сконфигурировать
* Быстрее работает
Тем более не так давно они добавили в свой SL фабрику для создания proxy для lazy load сервисов на базе стороннего пакета.
Delphinum
15.08.2016 17:12Можно так же добавить, что unit-тесты являются лакмусовой бумажкой для кода проекта, а проект поддерживающий unit-тесты как правило куда более чистый, нежели проект, его не поддерживающий.
Fesor
15.08.2016 17:49-1только если unit-тесты были написаны до кода. Тогда это мощный интерфейс проектирования и выявления ошибок проектирования (когда тесты тяжело писать становится или неудобно). Не говоря уже о том что мы перед тем как что-то написать должны будем подумать что оно будет делать.
Delphinum
15.08.2016 17:50только если unit-тесты были написаны до кода
Не обязательно. Если тесты пишутся после и их становится сложно писать, то становится понятно — проблема в коде и его пора рефакторить. Лакмусовая бумажка же.Fesor
15.08.2016 21:20Итого мы имеем следующие расходы времени:
- Программист потратил время на продумывание того что он хочет сделать
- Программист потратил время на реализацию
- Программист потратил время на тестирование (ему ж как-то надо было проверить что все работает?)
- Программист потратил время на тесты и выявил необходимость рефакторинга
- Программист потратил время на рефакторинг.
Как-то много впустую потраченного времени, вам так не кажется?
Delphinum
15.08.2016 21:40При чем тут потраченное в пустую время и мой комментарий про «unit-тест = лакмусовая бумажка»?
Fesor
16.08.2016 00:11-1Это я к тому что тесты это хорошо, но эффективность страдать не должна. Когда тесты пишутся до кода, оверхэд на это значительно меньше. Причем этот оверхэд слихвой окупается в долгосрочной перспективе (даже если рассматривать 3-4 месяца разработки).
Я не знаю кому нравится впустую тратить время.
nekrasov_dmytro
15.08.2016 21:50Расход времени это цена за качественный продукт, проектирование, тестирование и рефакторинг просто необходимы для того что бы ваш код имел ценность.
Я когда то работал на компанию где денег не было на нормальное проектирование, тестирование и рефакторинг соответственно. При этом начальство всегда было не довольно многими багами и даже на продакшене.
Для меня эта работа сильно опустила мой проф. уровень и я лично не советую работать на компанию где пишут плохой код, потому что заказчик считает что проектирование, тестирование это фигня и кстати, он ещё говорит что сам все протестируют.
Эти места работы портят программистов, делают с них кодеров из за чего в сети куча г. кода.
Представьте себе что инженеры бы не проектировали айфон, а вот сразу приступили к разработке… Было бы что то ужасное, типо та фигня которая с Китая к нам лезет. Мы тоже инженеры, только софта.
Надеюсь ответ был полным.Fesor
16.08.2016 00:30-1Расход времени это цена за качественный продукт
Есть масса способов получить качественный продукт без этих оверхэдов.
проектирование, тестирование и рефакторинг просто необходимы для того что бы ваш код имел ценность.
Я это не отрицаю. Я лишь говорю о нюансах влияющих на общую эффективность. То что тесты после кода (если это не автоматизация UI тестов какая) — это вэйстадж (в терминологии lean).
Я когда то работал на компанию где денег не было на нормальное проектирование, тестирование и рефакторинг соответственно.
У меня "тестирование/рефакторинг" отдельным пунктом не билится. Это часть моей работы. Клиенту важен только результат а не как "его туда довезли".
Для меня эта работа сильно опустила мой проф. уровень и я лично не советую работать на компанию где пишут плохой код
Плохой код пишут люди. Вообще есть такая проблемка… многие разработчики могут лет 5 работать и так и не увидеть нормальный код. А есть несчем сравнивать — то и свой код кажется неплохим. Со временем все это приобритает привычку.
потому что заказчик считает что проектирование, тестирование это фигня и кстати, он ещё говорит что сам все протестируют.
Знаете, годика 4 назад я так же рассуждал. Что мол "ох уж эти клиенты, опять не захотели тестирование", и мне очень просто сказали "А зачем ты предлагал? Они ж не понимают зачем это нужно, просто включи это в оценку по проекту и радуйся себе."
В целом "нежелание клиента платить за непонятное для него" не должно влиять на те практики, которые конкретно вы применяете в работе. Например вы же не говорите ему "ну вот мой рейт на пару центов выше чем мог быть потому что мне надо оплачивать лицензию на PhpStorm" например.
Представьте себе что инженеры бы не проектировали айфон, а вот сразу приступили к разработке…
проектирование айфона и его разработка в глазах инженера это один и тот же процесс если что.
Да и айфон к слову является неплохим исключением из правил. Это пример того, как компания работает с клиентом, который знает чего он хочет. Просто потому что клиентом выступал Стив Джобс, чья уникальность в том и заключалась, что он умел видеть что нужно кастомерам еще до того как те осознают что им это нужно. Таких людей оооочень мало.
Подавляющее же количество людей понятия не имеет что они хотят. Как правило им нужно показывать результат что бы выяснить "попали или нет". А от того нужна итеративная разработка. Чуть-чуть попроектировали (возможно через тесты, TDD и BDD там всякие), чуть-чуть покодили, показали. И так по непрерывному кругу. И чем короче цикл обратной связи тем дешевле становится разработка, поскольку "неверные решения" будут выявлены раньше и не приведут к значительным расходам.
p.s. вы когда-нибудь сидели на дэйли митинге? Ну тот который стандап но настолько долгий что люди садятся? Прикидывали примерно сколько денег это стоит вашим клиентам? Или плэнинги бесполезные по 4 часа… Или проекты которые начинаются с разработки второстепенного функционала вроде регистрации?
nekrasov_dmytro
16.08.2016 09:11p.s. вы когда-нибудь сидели на дэйли митинге? Ну тот который стандап но настолько долгий что люди садятся? Прикидывали примерно сколько денег это стоит вашим клиентам? Или плэнинги бесполезные по 4 часа… Или проекты которые начинаются с разработки второстепенного функционала вроде регистрации?
Да, я знаю сколько обходиться это клиенту. И экономить деньги клиента это правильный подход, если можно исключить всякие бесполезности, то лучше это сделать.
Как раз за счёт проектирования, тестирования(того же tdd, bdd), рефакторинга, мы секономим время и деньги.
А так как мы говорили о рефакторинге, как раз код после рефакторинга дешевле поддерживать, — легче/быстрее изучать новому программисту, так как он без проблем читаеться, нету мусора (мертвого кода, избыточного кода, повторов, ...), все находиться на своих местах и т.д.
Я понял вашу позицию о бесполезности использования времени и ресурсов на то что можно в конкретной ситуации не делать, я с вами согласен. Делать что бы было, тоже не надо…Fesor
16.08.2016 12:33Как раз за счёт проектирования, тестирования(того же tdd, bdd)
интересный момент. TDD и BDD являются больше практиками проектирования а не тестирования. Тесты — это скорее побочный (и полезный) продукт этого вида деятельности.
AndreyRubankov
16.08.2016 10:15Для меня эта работа сильно опустила мой проф. уровень и я лично не советую работать на компанию где пишут плохой код
Это демотивирует, это угнетает, но такой опыт тоже полезен. Чтобы понять, что не все в мире идеально, чтобы понять, зачем все же нужны эти тесты, проектирование, и почему не стоит спешить накодить.
Да и в целом, чтобы понять, что ИТ мир полностью построен на костылях, на сколько грязных и коварных, что можно лишь удивляться, как это все еще работает.
nekrasov_dmytro
15.08.2016 19:38-1Да, tdd безусловно мощный инструмет, в любом случае до того как писать код(не имеет значение код теста или код самого класса), нужно проектировать структуру классов, связи между классами.
Насчёт tdd, эта штука действительно учит мозг мыслить правильно и писать код с учетом того что в результате должно быть.
ilnuribat
15.08.2016 18:25+1Каждый раз, когда читаю такие статьи, думаю — неужели никто не читает Совершенный Код?
Там ведь буква в букву написано то же самое
А тут на хабре каждый раз всё это заново поднимается — как правильно называть функции, как проектировать…
Все эти вопросы хорошо разобраны до 7 главы
По сути, эта книга — настольная книга каждого разработчикаDelphinum
15.08.2016 18:29А в какой главе «Совершенного кода» обсуждается рефакторинг проекта? Видимо я что то недочитал (
ilnuribat
15.08.2016 19:38Там говорится, что нужно изначально писать так, чтобы не было нужно делать рефакторинг, который описывает автор
В том числе там учитывается, что заказчик захочет поменять условия, задачи, и нужно делать архитектуру с неким запасом прочности, гибкости
В общем, первые 5-7 глав — для проектировщиков
остальные — для программистов
ЗЫ: я сам читаю главу 8Delphinum
15.08.2016 20:28Там говорится, что нужно изначально писать так, чтобы не было нужно делать рефакторинг, который описывает автор
Ну теория часто далека от практики.
Fesor
16.08.2016 00:36+1У меня сложилось впечатление от этой книги что:
- Для людей которые и так это знают эта книга бесполезна
- Для людей которые этого НЕ знали, книга ничего так же не дает (из личного общения с разработчиками которые ее вроде и читали а по коду и не скажешь). Во всяком случае без перечитывания раз в пол года. И в этом ключе опять же непонятно зачем она нужна тогда.
p.s. Сам я от начала и до конца ее не читал, только отдельные главы. Потому мое мнение чисто субъективно и основано исключительно на общении людей, прочитавших эту книгу.
Delphinum
16.08.2016 11:12+1Периодически перечитываю эту книгу для повышения мотивации. Пока помогает.
ilnuribat
16.08.2016 11:15+1Хорошее замечание по поводу перечитывания
Ведь недаром я написал — «настольная книга», то есть, его нужно перечитывать. Там слишком много деталей, слишком много тонкостей. Пока читаешь одну главу, успеваешь забыть все предыдущие
Поэтому очень эффективным является применение всех знаний сразу после прочтения
LifeKILLED
18.08.2016 23:25Я читал то ли «Чистый код», то ли «Совершенный код», не помню, да и есть ли особая разница. Вещи банальные, но такому любителю, как я, открыли глаза. Как-то до этого я больше задумывался о лихости оптимизаций и хитрости алгоритмов, но когда прочёл, то понял, почему, когда я пытаюсь наваять что-то серьёзное, это тонет в багах и превращается в разлапистое Ктулху.
Хорошо, что у профессионалов слово «рефакторинг» — обыденное и ходовое. Но блин… заглядывал в код к людям, которые зарабатывают этим на жизнь, и возникает ощущение, что слова с делами частееенько расходятся :(Fesor
19.08.2016 12:39что слова с делами частееенько расходятся :(
тут зависит от ситуации. Возможно чуваку на самом деле пофигу. А есть еще такая тема как traidable quality.
nekrasov_dmytro
15.08.2016 19:57Одну штуку которую я реально опустил в рефакторинге это рефакторинг клонов классов.
Это очень распространённая проблема особенно когда проект переход из одной команды в другую или же приходит новый супер дев, в вашу команду, который не изучив структуру классов создаёт классы которые уже существуют или же классы функционал которых уже есть в других классах.
На мой взгляд именно эта проблема в конечном счете уничтожает проект и рефакторинг делать очень сложно так как в разных частях проекта для исполнения одних и тех же действий используются разные классы.
Так же не упомянул о важности разбираться с магическими циферками и буквочками в проекте, типа
if ($a * 5) {
Что значит 5 помнил программист который писал этот код, кстати помнил… но сам забыл…
Очень важно для таких создавать дополнительную переменную если циферка 5 используется только в конкретном методе и не несёт в себе смыл такой что бы её поместить в константу класса, если же несёт выносим, или несёт смысл для нескольких классов выносим в глобальную.
Я ещё много не написал я думаю вы сможете в коментах это сделать до меня и уже делаете, за что спасибо. Писал то что больше всего легло…
LifeKILLED
19.08.2016 00:22Придерусь к формулировкам, не более. Не ради критики или собственного ЧСВ, я не собираюсь спорить с автором… вы всё пишете правильно. Просто хочется помочь вам уточнить изложение мыслей в паре мест… сугубо по вашему желанию.
продумайте как можно с минимальным количеством классов, достигнуть максимального результата
Не совсем хорошо написано. Можно ведь вообще сделать один огромный неуклюжий класс, который никуда не сопроводишь и повторно нигде не используешь :) Понятно, что вы имели в виду именно более простую архитектуру, но не в числе классов ведь дело (поменять слово «класс» на «сущность»?). Тем более, далее по тексту у вас высказана противоположная мысль, показывающая, что вы как раз со мной согласны:
Некоторые части функционала можно вынести в отдельные классы, что даст возможность использовать их повторно
Вот-вот, всё же лучше будет больше классов, но лаконичных, типа вспомогательных или интерфейсов, но каждый из них будет независим и прост.
Слишком много параметров в методе (некоторые расчеты можно сделать внутри метода, используя внутренние константы, значения полученные с атрибутов и геттеров)
Как-то конкретно в коде PHP от этого не уйдёшь :( В итоге приходится передавать целые структуры данных в виде ассоциативных массивов, а конкретно — от backend во frontend. Но поскольку у всех элементов backend есть frontend, таких передач данных очень и очень много. Весь frontend на этом зиждется :(
Классы, содержащие одинаковые переменные и методы. Проблему можно решить через создание дополнительного класса)
Этого я вообще не понял, если честно :( Хотелось бы формулировку поточнее. Одинаковые переменные — внутри класса? Или одинаковые в том и в другом классе, и нужно вынести их и из первого, и из второго, в новый третий класс? Ну хоть убейте, не понял :(LifeKILLED
19.08.2016 00:48Может, это и в личку стоило послать, как багфикс, но уж слишком пространные у меня тут размышления, поэтому решил оставить у всех на виду. Может, кто-то будет со мной не согласен, предложит свои варианты. Статейка-то хорошая, коротко, по делу, и есть ссылки на более подробную инфу, но тем не менее не нужно недооценивать желание некоторых читателей вырывать из контекста слова, поэтому советую всё же присмотреться к упомянутым мной формулировкам, дабы до некоторых читателей лучше дошёл посыл :)
claygod
Предлагаю в статье упормянуть и принцип YAGNI,
хотя он именно с рефакторингом имеет некоторые противоречия.
nekrasov_dmytro
+