Zastosowanie zasad Clean Code do języków funkcjonalnych

16

Obecnie czytam Clean Code Roberta Martina . Myślę, że to świetnie, a kiedy piszę kod OO, biorę jego lekcje do serca. W szczególności myślę, że jego rada dotycząca używania małych funkcji o znaczących nazwach sprawia, że ​​mój kod płynie znacznie płynniej. Najlepiej podsumowuje ten cytat:

[W] Chcemy móc czytać program tak, jakby to był zestaw akapitów TO, z których każdy opisuje aktualny poziom abstrakcji i odwołuje się do kolejnych akapitów TO na następnym poziomie w dół.

( Czysty kod , strona 37: „akapit TO” to akapit rozpoczynający się od zdania wyrażonego w bezokoliczniku. „Aby wykonać X, wykonujemy kroki Y i Z.„ „Aby wykonać Y, my ...” itd. ) Na przykład:

TO RenderPageWithSetupsAndTeardowns, sprawdzamy, czy strona jest stroną testową, a jeśli tak, uwzględniamy konfiguracje i rozłączenia. W obu przypadkach renderujemy stronę w formacie HTML

Piszę również kod funkcjonalny do mojej pracy. Przykłady Martina w książce na pewno czytają tak, jakby były zbiorem akapitów i są bardzo jasne - ale nie jestem pewien, czy „czyta się jak zbiór akapitów” jest pożądaną cechą, aby kod funkcjonalny miał .

Biorąc przykład ze standardowej biblioteki Haskell :

maximumBy               :: (a -> a -> Ordering) -> [a] -> a
maximumBy _ []          =  error "List.maximumBy: empty list"
maximumBy cmp xs        =  foldl1 maxBy xs
                        where
                           maxBy x y = case cmp x y of
                                       GT -> x
                                       _  -> y

To jest tak daleko, jak tylko możesz uzyskać od porady Martina, ale to zwięzłe, idiomatyczne Haskell. W przeciwieństwie do przykładów Javy w jego książce, nie wyobrażam sobie żadnego sposobu, aby to przeformułować na coś, co ma taki rytm, o jaki prosi. Podejrzewam, że Haskell napisany zgodnie ze standardem Czystego Kodu byłby tak rozwlekły i nienaturalny.

Czy mylę się, biorąc pod uwagę (przynajmniej niektóre) Czysty kod sprzeczny z najlepszymi praktykami programowania funkcjonalnego? Czy jest rozsądny sposób na reinterpretację tego, co mówi w innym paradygmacie?

Patrick Collins
źródło
1
Funkcjonalni programiści mają tendencję do pisania zbyt zwięzłego kodu, to prawda. Jednak nawet w takim środowisku nie uznałbym tego za najlepszą praktykę.
Telastyn
Wybacz ignorancję, ale co to jest akapit TO?
Shashank Gupta
4
Jak wspomniano ostatnio w innym pytaniu, Dijkstra napisał o głupocie „programowania w języku naturalnym” i zgadzam się z nim, że kod, który brzmi jak proza, jest marzeniem z fajki. Myślę, że jest to szczególnie prawdziwe w przypadku Haskell, który będąc czystym, symbolicznie wyraża równość między wartościami, a nie sekwencje kroków w celu uzyskania efektów. Myślę, że ważne jest to, że cytowany kod jest idiomatyczny. Np. xsJest to zła nazwa, ale jest tak powszechna w językach funkcjonalnych, jak w iprzypadku zmiennych pętli.
Doval
@ShashankGupta Zredagowałem pytanie, podając link do konkretnej strony w książce, a także własne rozumienie tego, co napisał wujek Bob.
@ShashankGupta Podaje kilka przykładów, ale chodzi o to, że powinno to brzmieć jak proza. „Aby znaleźć maksimum listy, sprawdzasz każdy element ...”
Patrick Collins

Odpowiedzi:

11

Clean Code to przede wszystkim podręcznik stylu. Strunk and White nie ma zastosowania, gdy piszesz w Klingon. Chodzi o to, że chcesz być jasny dla programistów, którzy prawdopodobnie przeczytają Twój kod. Chcesz mieć modułowy i łatwy do zrestrukturyzowania kod. Istnieją sposoby, aby to zrobić w Haskell, tak jak istnieją sposoby, aby to zrobić w dowolnym innym języku, ale dokładne szczegóły będą się różnić.

To powiedziawszy, istnieje wiele wskazówek dotyczących stylu dla Haskell. Przepełnienie stosu ma również dość obszerny przewodnik . Utrzymywanie logiki kodowania w sposób prosty i zwięzły wydaje się dość stałe. Podkreślono również uogólnienie funkcji, ponieważ prowadzi ono do modułowości. Kod DRY jest również obciążony, podobnie jak w przypadku Clean Code.

Ostatecznie, Clean Code i wytyczne Haskell dotyczące kodowania dążą do tego samego, ale ostatecznie podążają własnymi ścieżkami, aby się tam dostać.

Inżynier świata
źródło
1
Wydaje mi się, że ta odpowiedź pomniejsza zasady nauczane przez Clean Code, które są bardzo przydatne we wszystkich językach i jest to podstawa zadanego pytania. Rozumiem, dlaczego ludzie myślą o Clean Code jako podręczniku stylu, i myślę, że jest to częściowo prawda, ale niewystarczająca, aby odrzucić całą książkę jako jedną.
Allan
Nie uważam książki Martina za Clean Code za podręcznik stylu. Uważam, że nauki zawarte w książce rzeczywiście mieszczą się gdzieś pomiędzy przewodnikiem po stylu a wzorami projektowymi.
Michael R
15

Nie jestem pewien, czy podążam za twoim przykładem. Akapity, jak je opisuje, nie wymagają rozwlekłości. Nie ma na myśli, że kod powinien brzmieć jak angielski. Ważną częścią jest pogrupowanie funkcjonalności na tym samym poziomie abstrakcji, w logicznym rozwoju. To teoretyczna koncepcja strukturalna, która wykracza poza paradygmaty programowania.

Wyrażony w formacie „TO akapit” Boba Martina czytam twój przykład jako:

  • Aby obliczyć maximumBy, potrzebujesz funkcji porządkowania i listy, a wynikiem jest element tej listy.
  • Obliczenie maximumBypustej listy i dowolnej funkcji porządkowania jest błędem.
  • Aby obliczyć maximumBylistę xs, należy ją złożyć za pomocą maxByfunkcji.
  • Aby obliczyć maxBydwa elementy listy, porównaj je za pomocą podanej funkcji porządkowania. Jeśli pierwszy element jest większy, wybierz go. W przeciwnym razie wybierz drugi.

Zaczynasz od najbardziej ogólnych pojęć i przechodzisz do bardziej szczegółowych, tak jak w przykładach bezwzględnych. Idea „akapitów TO” polega na tym, że możesz przestać czytać w pewnym momencie, gdy masz wystarczająco dużo szczegółów, bez konieczności przeskakiwania w górę i w dół strony. Z pewnością tak jest w tym przypadku.

Kilka nazw może być może lepszych, ale są one powszechnymi konwencjami języka, szczególnie podczas pisania ogólnych funkcji wyższego rzędu. Nazwy funkcji wyższego rzędu również nie przekładają się dobrze na frazy czasowników rozkazujących, takie jak przykłady w książce, ponieważ bardziej opisują relacje między czasownikami.

Istnieją sposoby realizacji tego, które nie są zgodne z wytycznymi „akapit TO”. Pozostawienie wyraźnego podpisu typu pomijałoby zdanie „przeglądowe” wyższego poziomu. Możesz użyć wyrażenia if do obsługi błędów zamiast dopasowywania wzorca, co niewłaściwie zamieniłoby to w inny poziom abstrakcji. Można wstawić maxByjako funkcję anonimową zamiast nadawać jej nazwę, którą można opisać bardziej szczegółowo.

W rzeczywistości, myślę, że konstrukcje takie jak wherefaktycznie są lepsze dopasowanie do formatu akapitu, ponieważ można z nich korzystać, aby nadać nazwę głębszym szczegółowo w sposób, który jest blisko, jak możemy wyrazić w języku angielskim, podobnie ograniczyć jej zakres w A jasna droga do kontekstu „akapitu”.

Karl Bielefeldt
źródło