2015-10-16 26 views
8

Przez kilka tygodni uczyłem się clojure, a ostatnio zacząłem czytać kod open source: clojure i kompilatory clojurescript oraz niektóre biblioteki takie jak om, boot, figwheel.Co z długimi plikami clojure?

Zauważyłem, że niektóre pliki clojure są bardzo długie, niektóre z nich mają ponad tysiąc LOC. Biorąc pod uwagę, że kod clojure jest bardzo zwięzły i niski, ten kod oznacza o wiele więcej kodu niż plik, który jest duży w niektórych innych językach.

Pochodzę z tła OO, gdzie zazwyczaj masz jedną klasę na plik i starasz się zachować krótkie lekcje (SRP) Stwierdziłem, że trochę dziwne.

Wiem, że kod clojure składa się głównie z czystych funkcji i jest o wiele łatwiejsze do zrozumienia niż jakaś zmienna klasa, w której należy zachować obecny stan w umyśle, i stwierdzam, że potrafię czytać i rozumieć większość z nich. funkcje jeden na raz. Ale większość z tych funkcji jest bardzo dobrze zaprojektowana, aby nie były od siebie zależne: nawet jeśli można używać (filter odd?), nie oznacza to, że są one powiązane. Ale kod "codziennie" (aplikacje LOB, aplikacje internetowe itp.) Bardzo utrudnia zachowanie funkcji jako takich (przynajmniej takie jest moje doświadczenie z programowaniem OO).

Widziałem także kilka demonstracji aplikacji clojurescript (om, odczynnik, itp.), W których deklarują wszystkie komponenty w tym samym pliku. Nie wiem, czy to dlatego, że jest to tylko wersja demonstracyjna, a w prawdziwej aplikacji, którą można uzyskać, to product.clj i category.clj lub po prostu sposób zachowania: mieć jeden plik na przestrzeń nazw/moduł/ograniczony kontekst.

myślę, że gdybym otworzyć folder i widzę product.clj, category.clj, order.clj, etc mogę dostać się pomysł na pierwszy rzut oka co to folder, o, lepiej niż tylko o components.clj lub core.clj.

Więc moje pytania to:

  1. Jest to wspólne dla „każdego dnia” kodu Clojure mieć te bardzo długie pliki? czy to tylko dlatego, że czytam kod bibliotek, a "normalny" kod jest bardziej "modułowy", mam na myśli: więcej plików i mniejszą długość.
  2. Czy posiadanie długich plików, takich jak te, sprawia, że ​​trudniej jest zrozumieć na pierwszy rzut oka, o co chodzi w tej aplikacji? podobnie jak mój przykład produktu/kategorii/zamówienia powyżej lub przez jakąś właściwość clojuresque, która nie jest problemem.
  3. W przypadku długich plików to "sposób kłamstwa", jak radzisz sobie z konfliktami, refaktoringami, programowaniem w zespole ... czy wszyscy dotykają tego samego pliku?

Odpowiedz

5

1: Spojrzałem na dość dużej non-biblioteki Clojure projekcie pracuję nad teraz i pobiegł tak:

ls **/*.clj | xargs wc -l | awk '{print $1}' | head -n -1 > counts 

i otworzyłem drzwi i pobiegł do repl

user> (float (/ (reduce + counts) (count counts))) 
208.76471 

Widzę, że w projekcie z 17k LOC nasz przeciętny plik clojure zawiera 200 linii. Znalazłem jeden z 1K LOC.

2: Tak, zacznę zrywać tak długo, jak tylko będę miał wolny czas. niektóre bardzo długie, takie jak clojure.core, są bardzo długie z powodu jednokrotnego projektu clojure i potrzeby samo-ładowania. muszą zbudować możliwość posiadania wielu przestrzeni nazw, zanim będą mogli to zrobić.W przypadku innych wyszukanych bibliotek może się zdarzyć, że mają jakiś inny powód do projektowania dużego pliku, chociaż zwykle jest to przypadek "powitania z prośbą o pobranie" z mojego doświadczenia.

3: Pracuję w dużym zespole z kilkoma dużymi plikami, obsługujemy konflikty związane z git, ale ponieważ zmiany mają zazwyczaj tę funkcję, pojawiają się one, znacznie rzadziej niż w innych językach. Uważam, że to po prostu żaden problem.

1
  1. Zyskują na długo podczas ich rozwoju. Powiedzmy, że potrzebujesz funkcji foo do wykonywania procedur [ab ...] na bazie danych K. Najpierw (def) podpis funkcji i kontynuuj wdrażanie funkcji pomocniczych ab ... ponieważ są to prawdopodobnie wszystkie czyste funkcje i funkcjonalność potrzebujesz foo jest skomplikowana, przestrzeń nazw ma tendencję do wydłużania się.

  2. Czasami, ale replika jest naprawdę użytecznym narzędziem, aby zrozumieć nową główną funkcję biblioteki, często używam clojure.repl/source na funkcji i pracuję wstecz do jej funkcji pomocniczych. Uważam, że wiele razy dokumentacja bibliotek Clojure jest albo tajemnicza, albo nie istnieje, ale jak wiele osób w społeczności lubi mówić, że źródłem funkcji Clojure jest samo dokumentowanie.

  3. Nie mam doświadczenia w pracy w dużym zespole, ale Arthur Ulfeldt ma rację, większość zmian zachodzi w jednej funkcji. Zbieram ją z czytania różnic w żądaniach ściągnięcia z funkcją Github's Blame.

1
  1. To pragmatyczne (clojure lub nie), aby uniknąć zależności. Nazywanie i klasyfikowanie abstrakcyjnych rzeczy sprawia, że ​​nasz intelekt czuje się dobrze, ale w pewnym sensie poddaje się, gdy trzeba zszyć wszystkie części razem. Po co tworzyć trzy pliki, kiedy to zrobi?
  2. Co myślisz o tym, o czym jest aplikacja/lib, po prostu czytając kod? Jest "co" i jest "jak". Lepiej mieć o tym pierwszą wskazówkę, jeśli chcesz zagłębić się w to drugie. Jeśli czytasz kod, aby uzyskać wskazówkę co do celu aplikacji, nie jestem pewien, czy podzielenie go na więcej plików ułatwi to. Zastanów się dwa razy nad swoim przykładem, żadna z tych rzeczy nie może istnieć bez innych.
  3. Trudność z dużymi zespołami polega na dzieleniu się aktualną wiedzą, a nie plikami lub liniami, dzięki git. Może posiadanie wszystkich w tym samym pliku byłoby mimo wszystko cholernie dobrą rzeczą? Nie, duże pliki nie stanowią problemu w clj lub innych językach. Unit < -> plik jest całkowicie javart sztuczną koncepcją, która pomaga kompilatorom, a nie mężczyznom. Podziel bufor fg.
1

Oprócz odpowiedzi udzielonych przez innych, oto dwa kolejne.

  1. może się okazać, że niektóre pliki są długie, ponieważ w Clojure to najprostsza w użyciu jeden plik dla każdej przestrzeni nazw, tak, że jeśli chcesz wszystkie te definicje w tej samej przestrzeni nazw, łatwiej jest umieścić je w jednym pliku . Jednym z powodów, dla których definicje muszą znajdować się w tej samej przestrzeni nazw, podano w punkcie 2.

  2. Kompilator Clojure nie zezwala na pewne rodzaje cyklicznych zależności między przestrzeniami nazw (inne cykliczne zależności między przestrzeniami nazw są w porządku). Jednym ze sposobów uniknięcia nielegalnej cyklicznej zależności jest umieszczenie współzależnych definicji w tej samej przestrzeni nazw. Jeśli to zrobisz, może być sens, aby również inne definicje, które należą do problematycznych, również do pojedynczej przestrzeni nazw. Zobacz # 1 w dalszej części tej odpowiedzi.

(Mam swój własny smak jest na kilka mniejszych plików, choć nie tak małe jak wielu plików klas Java również:.. Kod nie jest zwykle jako samodokumentujące jak jego autor uważa ten może pomieścić nawet gdy autor i osoba czytająca kod później to ta sama osoba.)