Chciałem już nie pisać o CodeSkill, to lokalne spotkanie i nie ma potrzeby, aby wciąż je promować.
Ale o wczorajszym spotkaniu, szczególnie prelekcji Łukasza Sosnowskiego warto wspomnieć, ponieważ nawiązywała do PHP.
Łukasz przez prawie godzinę starał się pokazać, że każdy działający kod jest poprawny. Oczywiście kod może być „bardziej poprawny” lub mniej. I nie tylko chodzi o to, aby kod się uruchamiał i był zrozumiały. Bo powoli robi się to bardzo subiektywna opinia programisty.
A czy da się inaczej? Czy można skorzystać z jakiś metryk? Oczywiście, że tak. Łukasz wspomniał o złożoności cyklomatycznej (CC; liczba niezależnych ścieżek w programie) oraz mierze złożoności Halsteda (objętość, trudność napisania/zrozumienia kodu, utrzymanie kodu, szacunkowa ilość błędów). I nie są to subiektywne miary, ale miary z konkretnym uzasadnieniem matematycznym i merytorycznym (próba konstrukcji miar niezależnych od języka programowania).
Ogólna definicja mówi, że CC to liczba niezależnych ścieżek w grafie reprezentującym przepływ sterowania w metodzie. Istnieją dwa wzory określające tę wartość: pierwszy opiera się na liczbie wierzchołków i łuków w grafie, natomiast drugi – jedynie na liczbie węzłów decyzyjnych. (źródło)
Teorii było bardzo niewiele – słusznie, ponieważ można znaleźć ją w Internecie. Natomiast sporo było przykładów z życia. Były zaprezentowane 2-3 zadania z życia, i każde rozwiązane na kilka sposobów wraz z prezentacją ich metryk.
Jednym z nich było zadanie związane z napisaniem funkcji, która przyjmuje 3 parametry (ulica, miasto, kod) i na wyjściu powinien być string sformatowany w następujący sposób: Ulica, Miasto Kod . Pierwsze rozwiązanie (wariant) pojawił się bardzo szybko i wyglądał następująco:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function address(?string $street, ?string $city, ?string $zip): string { $fullAddress = !empty($street) ? $street : ''; if (empty($city) && empty($zip)) { return $fullAddress; } if (!empty($fullAddress)) { $fullAddress .= ', '; } if (!empty($zip)) { if (!empty($city)) { $fullAddress .= $city . ' '; } $fullAddress .= $zip; } else { $fullAddress .= $city; } return $fullAddress; } |
Ale w zespole, o którym mówił prowadzący nie wszystkim przypadła do gustu tak duża ilość warunków i ktoś szybko pokazał wariant drugi:
1 2 3 4 5 |
function address2(?string $street, ?string $city, ?string $zip): string { $zipPart = implode(' ', array_filter([$city, $zip])); return implode(', ', array_filter([$street, $zipPart])); } |
Niestety. Mimo, że jest to ładniejsze rozwiązanie to okazało się mało wydajne (0,35μs vs 0,53μs). Po długim czasie, zupełnie przypadkiem powstało rozwiązanie piąte, które wyglądało następująco:
1 2 3 4 5 6 7 |
function address5(?string $street, ?string $city, ?string $zip): string { return trim( $street . ", ". trim($city . " " . $zip), ", " ); } |
Metryki dla wszystkich 5 rozwiązań:
Bardzo praktyczna prelekcja z dużą elementów przykładów z własnego życia. Wszystkie zadania oraz ich metryki znajdziecie w prezentacji Łukasza. Gdybyście sami chcieli zbadać niektóre metryki w PHP pomocny okaże się PHP Metrics.
Slajdy Speakerdeck: Poprawny kod
joind.in: Poprawny kod