Zanurkuj w Pythonie/Programowanie koncentrujące się na danych
W tym momencie zastanawiacie się zapewne, dlaczego takie podejście może być uznane za lepsze od podejścia, w którym używa się pętli i bezpośrednich wywołań funkcji. I to jest bardzo dobre pytanie. Przede wszystkim jest to kwestia przyjęcia pewnej optyki. Użycie funkcji map oraz filter zmusza do skoncentrowania się na przetwarzanych danych.
W tym przypadku zaczęliśmy od sytuacji, w której w ogóle nie było żadnych danych; pierwszą rzeczą, jaką zrobiliśmy, było uzyskanie ścieżki do katalogu, w którym znajdował się uruchomiony skrypt, a kolejną - uzyskanie na tej podstawie listy plików znajdujących się w tym katalogu. W ten sposób zaczęliśmy i dzięki tym krokom zdobyliśmy dane, na których mogliśmy dalej pracować: listę nazw plików.
Wiedzieliśmy jednak, że nie interesują nas wszystkie pliki, a jedynie te, które są zestawami testów. Mieliśmy zbyt dużo danych, a więc potrzebowaliśmy je jakoś przefiltrować. Skąd wiedzieliśmy, które dane zachować? Potrzebowaliśmy funkcji, która by to sprawdzała, a którą mogliśmy przekazać do funkcji filtrującej. W tym akurat przypadku użyliśmy wyrażenia regularnego, ale koncepcja jest wciąż taka sama, niezależnie od tego, w jaki sposób skonstruowana została funkcja sprawdzająca.
Po tym kroku posiadaliśmy już listę nazw plików będących zestawami testowymi (i tylko nimi, ponieważ wszystkie inne pliki zostały odfiltrowane), jednak w rzeczywistości potrzebowaliśmy jedynie listę nazw modułów. Mieliśmy wszystkie dane, jednak były one w złym formacie. Zdefiniowaliśmy więc funkcję, która przekształcała nazwę pliku w nazwę modułu i każdy element z listy nazw plików odwzorowaliśmy przy pomocy tej funkcji w nazwę modułu, uzyskując listę nazw modułów. Z każdej nazwy pliku powstała jedna nazwa modułu, a z listy nazw plików powstała lista nazw modułów.
Zamiast funkcji filter mogliśmy użyć pętli for z instrukcją if. Zamiast funkcji map mogliśmy użyć pętli for z wywołaniem funkcji. Jednak używanie pętli w ten sposób jest zajęciem czasochłonnym. W najlepszym przypadku stracimy niepotrzebnie czas, a w najgorszym wprowadzimy brzydkie błędy. Na przykład, odpowiadając na pytanie: "czy ten plik jest zestawem testów?" zastanawiamy się nad logiką specyficzną dla danego zastosowania i żaden język programowania nie wyrazi tego za nas. Jednak kiedy już wiemy, jak na takie pytanie odpowiedzieć, czy naprawdę potrzebujemy tego kłopotliwego tworzenia nowej, pustej listy, napisania pętli for i instrukcji if, a następnie ręcznego wywoływania funkcji append, aby dodać element, który przeszedł przez test w warunku if do tej listy, a dodatkowo jeszcze śledzenia, jaka zmienna przechowuje dane już przefiltrowane, a jaka te, które dopiero będą filtrowane? Dlaczego nie mielibyśmy po prostu zdefiniować odpowiedniego warunku, a całą resztę zrobi za nas Python?
Oczywiście, moglibyśmy być sprytni i nie tworzyć nowej listy, lecz usuwać niepotrzebne elementy z listy wejściowej. Ale już się na tym sparzyliśmy: próba modyfikowania listy, po której właśnie iterujemy, może powodować błędy. Usuwamy element, przechodzimy do następnego elementu, i tym samym przeskakujemy przez jakiś element. Czy Python to jeden z tych języków, w których usuwanie elementów działa w ten właśnie sposób? Ile czasu zajmie nam ustalenie tego faktu? Czy będziemy pamiętać, czy taka iteracja jest bezpieczna, czy nie, kiedy będziemy robić to ponownie? Programiści tracą zbyt wiele czasu i popełniają wiele błędów podczas zajmowania się takimi - czysto przecież technicznymi - kwestiami, co jest przecież bezcelowe. Nie posuwa to pracy nad programem ani o jotę, tylko niepotrzebnie zajmuje czas.
Kiedy uczyłem się języka Python po raz pierwszy, stroniłem od wyrażeń listowych, a od funkcji map i filter stroniłem jeszcze dłużej. Upierałem się, aby moje życie było bardziej skomplikowane, ponieważ przylgnąłem do znanego mi sposobu programowania zorientowanego na kod: używałem pętli for oraz instrukcji warunkowych. Moje programy przypominały programy pisane w języku Visual Basic, przedstawiały bowiem dokładnie każdy krok każdej operacji w każdej funkcji. W nich wszystkich pojawiały się też wciąż te same, małe problemy i brzydkie błędy. I nie miało to większego sensu.
Zapomnijmy o tym. Szczegółowe rozpisywanie kodu nie jest ważne. Ważne są dane. Dane nie są trudne, to tylko dane. Jeśli mamy ich za dużo, przefiltrujmy je. Jeśli nie są dokładnie takie, jakich sobie życzymy, użyjmy odwzorowania map. Skoncentrujmy się na danych, a niepotrzebną pracę zostawmy za sobą.