Обект Калистеника за класове за отслабване Говорещият бит
Блог за програмиране, предимно PHP, и може би други неща

Проект, поддържан от franiglesias, Хостван на GitHub Pages - Тема от mattgraham
от Фран Иглесиас
В тази статия представяме упражнение, което може да се използва за получаване на плавност при писането на по-компактни класове с по-изразителни и лесни за разбиране методи.
Обектните упражнения по калистика могат да ни помогнат да автоматизираме практиките, които ни позволяват да се доближим до най-добрите принципи на проектиране. По някакъв начин тя се състои в това да се научим да откриваме определени грешни модели в кода и да го трансформираме, така че да напредваме в целта да подобрим качеството на кода.
Идеята на тези упражнения е да наложат изкуствени ограничения за налагане на реакции, които ни принуждават да мислим отвъд конвенционалните решения.
В тази статия ще приложим следните ограничения:
- Единично ниво на отстъп
- Не използвайте друго
- Дръжте единиците малки
Ограниченията
Единично ниво на отстъп
Отстъпът е модел на кодова организация, който ни помага лесно да идентифицираме блокове с инструкции, които образуват клонове или пътища в софтуерния поток, както и блокове от свързани инструкции. В езици като Python отстъпът има значение и следователно е неизбежен. В PHP и много други езици обаче отстъпът е полезна конвенция. Можем да пишем програми без вдлъбнатини и те ще работят по същия начин, само че ще бъдат по-трудни за четене.
Вдлъбнатината е типична за контролните структури, като if/then:
И може да има няколко нива:
Предизвикателството, този път, ще бъде да намалим един нивата на отстъп във всеки метод на клас.
По същество това ни принуждава да обмислим какво прави всеки блок код и да го извлечем в свой собствен метод, обяснявайки какво прави от тяхно име.
Не използвайте друго
Структурата if/then/else може да обърка поради редица причини. Един от тях е именно ненужното използване на else, особено когато тогавашният крак предполага излизане от цикъла или основния метод.
Въведох това ограничение, защото то е доста свързано с предишното.
Дръжте единиците малки
В статията, цитирана в началото, говорим за обекти, но като се замисля, предпочетох да сложа единици, за да се отнася както за класове, така и за методи. В крайна сметка става въпрос за всяка единица, независимо от разделителната способност, която обработваме, да бъде възможно най-малка и управляема.
Това води до известно противоречие. Например, един клас може да заеме по-малко редове с един голям метод, отколкото ако го разделим на няколко по-малки въз основа на принципи като намаляване на нивата на отстъп. Очевидно това са решения, които включват компромиси. Балансът е в поддържането на четливостта и разбираемостта на класа и неговите методи.
Обучение
Преди време практикувах писането на класически алгоритми и структури от данни, използвайки TDD, и въпреки че те са относително малки класове, те имат някои структури, които биха могли да бъдат подобрени чрез прилагане на предложените ограничения, така че нека да видим някои примери и как можем да ги развием.
Като бележка от интерес да кажа, че ще направя повечето рефактори с инструментите, предоставени от IDE (PHPStorm).
Нека започнем с BubbleSort, най-простият и интуитивен алгоритъм за сортиране, макар и не много ефективен за много елементи:
Между другото, тестът е такъв и се прави с phpspec:
В този случай имаме три нива на вдлъбнатина и ограничението е, че всеки метод може да има само един най-много. За да направим това, ще извлечем вложеното за неговия собствен метод с помощта на IDE, като се уверим, че тестовете продължават да преминават:
Тестът преминава, така че не сме счупили нищо. Можем да видим някои подробности, които биха могли да бъдат подобрени при това извличане:
- Параметърът $ length е ненужен, тъй като тъй като можем лесно да го вземем от $ source, така че ще го пропуснем.
- Можехме да използваме структура на foreach вместо for .
- Възможно е да се предаде елементът на масива вместо неговия индекс.
Това е интересна точка: фактът, че извършваме извличането на метода, ни кара да разсъждаваме върху предишните ни решения и възможни подобрения в кода. Така че, преди да продължим, ще приложим някои.
В момента предаването на елемента, а не на индекса не изглежда жизнеспособно, но постигнахме някои подобрения, тъй като сега не е нужно изрично да изчисляваме дължината на $ source, което означава една по-малка линия и сме по-изрични в представянето на идея, че пресичаме масива. Продължаваме да поддържаме едно ниво на отстъп, което също има само един ред.
Сега имаме две нива на вдлъбнатина вътре в метода compareEveryElementWithCurrent, така че нека се отнасяме към тях по същия начин: извличане към метод.
Е, тук има няколко страхотни неща:
- Имаме само едно ниво на отстъп на всяко ниво.
- В името на метода правим препратка към текущ елемент, така че би било добре да го изразим в код, като променим името на променливата $ i на $ currentIndex или подобно, така че препратката да е изрична.
- Можем да приложим същото третиране на преобразуването на for във foreach и да запазим променливата $ length .