Обект Калистеника за класове за отслабване Говорещият бит

Блог за програмиране, предимно 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 .