Hejterzy zawsze deptali po PHP z różnych powodów, ale jednym z najłatwiejszych celów jest to, jak brzydki może być kod. Niektórzy mogą się nie zgadzać, że czystość kodu i „ładność” mają znaczenie, ale jeśli chodzi o utrzymywanie baz kodu w dłuższej perspektywie, możesz zaoszczędzić swojemu zespołowi dużo czasu, mając kod, który jest łatwy do odczytania.
Pracując w Apple, opracowałem ekosystem aplikacji finansowych używanych przez wewnętrznych interesariuszy. Przez lata nieustannie wdrażałem nowych programistów do narzędzi, aby pomóc w ogólnej konserwacji lub ulepszeniach. Jednym z głównych wniosków z tego czasu jest to, jak ważne jest czytanie kodu za pomocą języka naturalnego.
Ciekawe jest to, że większość kodu jest napisana w taki sposób, że trzeba przeczytać znaczną jego część, a następnie wrócić do początku, aby w pełni zrozumieć, co się dzieje. Używanie bardziej ekspresyjnego języka lub interfejsów API podczas pisania kodu może znacznie skrócić czas wdrażania i rozruchu nowych programistów.
Tutaj właśnie błyszczą kolekcje. Kolekcje Laravel biorą kilka skomplikowanych przejść przez tablice i sprawiają, że są one niezwykle łatwe do odczytania i zrozumienia. Twój kod staje się łańcuchem poleceń, które można odczytać w następujący sposób: „Przefiltruj tę tablicę tylko do słów zaczynających się na a, następnie zmapuj kwotę kosztów do wiersza, a na końcu zredukuj to do sumy wszystkich kosztów”. Bardzo łatwo jest niedoceniać znaczenia pisania kodu przy użyciu bardziej ekspresyjnego języka, ale gdy już stanie się to nawykiem, trudno sobie wyobrazić, że cokolwiek innego jest akceptowalne.
Oczywiście czytelność nie może odbywać się kosztem wydajności, dlatego ważne jest, aby zawsze podejmować mądre decyzje i priorytetyzować czytelność tylko wtedy, gdy jest to właściwe. Zawsze powinniśmy rozumieć, co dzieje się za kulisami i być w pełni świadomi kompromisów, jakie napotykamy w sposobie, w jaki podchodzimy do naszych rozwiązań. Nie przynosi korzyści naszemu kodowi, jeśli jest czytelny, jeśli zajmuje to całą sekundę dłużej niż mniej czytelne rozwiązanie.
Przyjrzyjmy się bliżej tablicom PHP i kolekcjom oraz porównajmy ich wydajność.
Jedną z największych zalet korzystania z kolekcji Laravel jest ich płynna składnia, która umożliwia łączenie metod. Rezultatem jest czysty i czytelny kod, ponieważ można wykonywać wiele operacji w sekwencji bez potrzeby zmiennych tymczasowych lub złożonych zagnieżdżonych wywołań funkcji.
Porównajmy poniżej niektóre powszechnie używane funkcje do manipulowania tablicami, aby na bardzo prostym przykładzie porównać PHP z kolekcjami.
PHP
array_filter($data, function($row) { return substr($row, 0, 1) === "a"; });
Kolekcje
$data->filter(function($row) { return substr($row, 0, 1) === "a"; });
PHP
array_search(function($row) { return substr($row, 0, 1) === "a"; }, $data);
Kolekcje
$data->search(function($row) { return substr($row, 0, 1) === "a"; });
PHP
array_map(function($row) { return "test"; }, $data);
Kolekcje
$data->map(function($row) { return "test"; });
PHP
sort($data);
Kolekcje
$data->sort();
PHP
foreach($loop as $item) { $doSomething = true; }
Kolekcje
$data->each(function($row) { return "test"; });
PHP
array_reduce($data, function($carry, $row) { return $carry + strlen($row); });
Kolekcje
$data->reduce(function($carry, $row) { return $carry + strlen($row); });
PHP
array_splice($data, count($data)/2);
Kolekcje
$data->splice(count($data)/2);
Wszyscy razem (PHP)
$data = array_filter($data, function($row) { return substr($row, 0, 1) === "a"; }); $data = array_search(function($row) { return substr($row, 0, 1) === "a"; }, $data); $data = array_map(function($row) { return "test"; }, $data); sort($data); foreach($loop as $item) { $doSomething = true; } $sum = array_reduce($data, function($carry, $row) { return $carry + strlen($row); });
Wszyscy razem (Kolekcje)
$sum = $data->filter(function($row) { return substr($row, 0, 1) === "a"; })->search(function($row) { return substr($row, 0, 1) === "a"; })->map(function($row) { return "test"; })->sort() ->each(function($row) { return "test"; })->reduce(function($carry, $row) { return $carry + strlen($row); });
Porównanie
Przy tak prostym podejściu nie wydaje się, aby istniał duży kompromis w zakresie czytelności każdej pojedynczej funkcji, jednak gdy weźmiemy pod uwagę przykład, w którym wszystkie one muszą zostać zastosowane do jednej tablicy, wyraźnie widać, że bardziej zwięzłe i łatwiejsze do odczytania jest zastosowanie metod łańcuchowych w kolekcji.
Zamiast ciągłego nadpisywania zmiennej, a następnie ustawiania nowej zmiennej na wyjściu na końcu, możemy po prostu łączyć wszystkie polecenia, aż dotrzemy do pożądanego wyjścia. Kolekcje są zdecydowanie łatwiejsze do odczytania, im bardziej złożony staje się kod.
Na podstawie powyższych przykładów wygenerowałem dane testowe, aby spróbować określić, czy kolekcje są bardziej czy mniej wydajne niż standardowe funkcje PHP.
Każda tablica miała 100 000 losowych ciągów jako elementy, a każdą funkcję uruchomiłem 100 razy. Na koniec obliczyliśmy średnią wszystkich czasów odpowiedzi.
Poniżej przedstawiono wyniki końcowe:
========== Tests Complete (ms) ========== php filter: 5.07 collect filter: 6.49 ======================= php search: 0.79 collect search: 0 ======================= php map: 3.45 collect map: 4.18 ======================= php sort: 25.27 collect sort: 11.18 ======================= php each: 1.03 collect each: 6.96 ======================= php reduce: 2.78 collect reduce: 7.75 ======================= php splice: 1 collect splice: 0.74 =======================
Jak widać, mimo że kolekcje zapewniają nam dużą czytelność, wydajność w niektórych kluczowych obszarach ulega znacznej redukcji.
Filter , Map , Foreach i Reduce są szybsze ze standardowymi funkcjami PHP. Foreach i Reduce to w rzeczywistości niezwykle istotne różnice. Search , Sort i Splice wszystkie pokazują Collections jako zwycięzcę, a Sort to w rzeczywistości ogromna oszczędność czasu.
Ważne jest również, aby pamiętać, że każdą kolekcję trzeba utworzyć z gotowej tablicy, co wiąże się z niewielkim narzutem na początkowe konfigurowanie kolekcji. Jednak nawet przy tak niewielkiej ilości dodatkowej pracy i czasu, wyniki są całkiem jasne.
Moim zdaniem (i jest to tylko opinia oparta na tych wynikach), jeśli wydajność jest ogromnym problemem, z pewnością trzymałbym się standardowej funkcjonalności PHP dla pętli Foreach i prawdopodobnie tak samo dla wszelkich potrzeb Reduce . Jeśli musisz posortować duże zbiory danych, Collections jest zdecydowanie właściwą drogą. Pozostałe są tak zbliżone, że naprawdę wydaje się to kwestią osobistych preferencji.
W tym miejscu powiedziałbym, że zbiory są zawsze łatwiejsze do odczytania i utrzymania.
Oczywiście, powinieneś wziąć te informacje i podjąć własną świadomą decyzję, jednak jeśli jesteś taki jak ja, myślę, że znajdziesz się w sytuacji, w której będziesz wciskał kolekcje do wielu z tych funkcji powyżej. Ale myślę, że zmniejszę użycie →each
i →reduce
gdzie będzie to odpowiednie w przyszłości!