W którym momencie tabu ma pętle w pętli?

23

Po prostu ciekawy. Najbardziej, jakie kiedykolwiek miałem, to pętla for w pętli for, ponieważ po przeczytaniu tego z Linusa Torvaldsa:

Tabulatory mają 8 znaków, a zatem wcięcia również mają 8 znaków. Istnieją ruchy heretyckie, które próbują zagłębić wcięcia 4 (lub nawet 2!) Znaków, i to jest podobne do próby zdefiniowania wartości PI jako 3.

Uzasadnienie: Ideą wcięcia jest jasne określenie, gdzie zaczyna się i kończy blok kontroli. Zwłaszcza gdy patrzysz na ekran przez 20 prostych godzin, o wiele łatwiej jest zobaczyć, jak działa wcięcie, jeśli masz duże wcięcia.

Teraz niektórzy twierdzą, że 8-znakowe wcięcia powodują, że kod przesuwa się zbyt daleko w prawo i utrudnia czytanie na 80-znakowym ekranie terminala. Odpowiedź na to jest taka, że ​​jeśli potrzebujesz więcej niż 3 poziomów wcięcia, i tak jesteś wkręcony i powinieneś naprawić swój program.

https://www.kernel.org/doc/Documentation/CodingStyle

Uznałem, że to niedopuszczalna praktyka, aby przejść do trzeciej warstwy zapętlenia i zrestrukturyzować mój kod (głównie Qt).

Czy Linus żartował?

Czy to zależy od języka lub aplikacji?

Czy są jakieś rzeczy, które absolutnie wymagają trzech lub więcej poziomów zapętlenia?

Akiva
źródło
8
Jestem zdezorientowany, dlaczego przeskakujesz z wcięcia na poziomy zapętlania? Masz duży cytat omawiający wcięcia i nagle z tego wynika pytanie o zagnieżdżone pętle.
Pieter B
5
Linus prawdopodobnie nie żartuje (tylko) w tej sekcji, ale zauważ, że jest to tylko jeden przewodnik po stylach, a ten sam przewodnik po stylach podkreśla, że ​​„Styl kodowania jądra jest super prosty”, tj. Bardziej niż inne style.
5
@Akiva Nie możesz przejść przez 4-wymiarową macierz bez 4 zagnieżdżonych pętli. Uważam za szaleństwo, że ktoś ograniczy ilość zagnieżdżonych pętli, które możesz mieć. Linus był oczywiście bardzo ogólny i nie powinieneś brać wszystkiego, co czytasz, jako świętego pisma.
Alternatex,
9
@Alternatex To, że potrzebujesz 4 pętli, nie oznacza, że ​​muszą być one zagnieżdżone leksykalnie . Z cytatu wynika, że ​​mówimy o tym, jak zorganizować kod, a nie o jego wykonaniu.
4
@delnan Nie mówię, że 4 zagnieżdżone pętle są przyjemne wizualnie i wiem, że istnieją inne sposoby, aby to zrobić, ale uważam, że to głupie, jak OP tak dosłownie potraktował słowa Linusa. 4. poziom wcięcia = koniec świata. Daj mi spokój.
Alternatex,

Odpowiedzi:

19

Jądro zdecydowanie preferuje proste algorytmy

Podczas gdy różne algorytmy mogą wymagać głęboko zagnieżdżonych pętli w pętlach, w kontekście jądra Linuksa (w którym wspomniano cytat) zazwyczaj potrzebujesz szybkich odpowiedzi w czasie rzeczywistym. W tym kontekście głębokie zagnieżdżanie jest zapachem, który może wskazywać, że przepływ kodu jest zbyt skomplikowany dla tej domeny i może wymagać zmiany ze względu na jego właściwości wykonawcze, a nie problemy z czytelnością lub wcięciem.

Co więcej, jądro Linuksa różni się od większości kodu aplikacji pod względem wymagań dotyczących kontroli i testowania - i dlatego wolałby nie mieć zagnieżdżonego algorytmu na poziomie 4+ w jednej funkcji. Powinno być oczywiste, aby zobaczyć, co dokładnie robi każdy fragment kodu , w tym wszystkie możliwe przepływy sterowania i przypadki zbocza. Głęboko zagnieżdżony kod utrudnia to.

Piotr jest
źródło
Czy więc uważasz, że w przypadku języków niższego poziomu, takich jak C, głęboko zagnieżdżone pętle to na ogół więcej becauseprojektów tabu wykorzystujących języki niższego poziomu, które korzystają ze stylu kodowania, który koncentruje się na prostszych algorytmach?
Akiva,
4
@Akiva Nie powiązałbym go z językami niższego poziomu lub C jako takimi, ale raczej z domeną kodu. Myślę, że podobne wytyczne będą miały zastosowanie do każdego języka podczas pisania kodu, który musi być solidny, skoncentrowany na bezpieczeństwie i możliwy do skontrolowania kosztem innych rzeczy. Np. Biblioteka szyfrująca napisana w Javie lub Haskell powinna być również napisana w stylu, który upraszcza wszystko tak prosto, jak to możliwe, ogranicza zagnieżdżanie i próbuje rozdzielić wszystko na części, które można łatwo przeanalizować ze wszystkimi możliwymi konsekwencjami.
Peteris,
Bardzo wnikliwy i użyteczny komentarz / odpowiedź. Po prostu ciekawy; jaki rodzaj projektu wykonanego dzisiaj, który wykorzystuje język niskiego poziomu, nie koncentrowałby się na solidności, kontroli i bezpieczeństwie?
Akiva,
7
@Akiva na przykład kod uczenia maszynowego, w którym możesz chcieć używać C tylko ze względu na wydajność, ale nie przejmuj się solidnością ani bezpieczeństwem, ponieważ będzie uruchamiany wewnętrznie w kontrolowanych warunkach. Ponadto wdrażanie prostych funkcji biznesowych na małych wbudowanych mikrokontrolerach - w praktyce często koncentruje się na funkcjach i szybkości rozwoju kosztem jakości i bezpieczeństwa, ale używa języków niskiego poziomu.
Peteris,
49

Do pewnego stopnia przestałem poważnie traktować ten cytat w „Tabs to 8 znaków” . Cały sens tabulatorów polega na tym, że nie są one stałą liczbą znaków (jeśli w ogóle, karta to jeden znak). Co za ładunek. Podobnie, nie jestem do końca przekonany, że ustalenie twardej i szybkiej reguły „trzech poziomów wcięcia” jest rozsądne (podobnie jak ustalenie twardej i szybkiej reguły dla wszystkiego jest rozsądne).

Jednak ograniczenie poziomów wcięć jest ogólnie rozsądną sugestią, a nie taką, która powinna cię zaskoczyć.

Ostatecznie, jeśli twój program potrzebuje trzech poziomów iteracji, tego właśnie potrzebuje Twój program . Duch cytatu nie polega na magicznym złagodzeniu tego wymogu w projekcie, ale na podziale logiki na funkcje i typy, dzięki czemu kod jest bardziej przejrzysty i bardziej wyrazisty.

To po prostu opiera się na tej samej wytycznej podanej powyżej, dotyczącej poziomów wcięć. Chodzi o to, jak ustrukturyzujesz swój kod i zapewnisz jego czytelność, łatwość w utrzymaniu i przyjemne modyfikowanie przez wiele lat.

Lekkość Wyścigi z Moniką
źródło
6
Uważam, że „deklaracja”, że tabulatory składają się z 8 znaków, jest szczególnie związana z rozwojem jądra. Ten cytat pochodzi z wytycznych kodowania dla konkretnego projektu i nie ma być ogólną wytyczną użytkowania, a zatem oczekuje się, że będzie dość opiniotwórczy.
Lie Ryan,
6
@LieRyan: W takim razie jest jeszcze tosh - wytyczne kodowania czegokolwiek nie mają żadnego znaczenia, dyktując, jak szerokie są moje zakładki! Ale podejrzewam, że Linus to wie.
Wyścigi lekkości z Monicą
6
i oczywiście jest to zależne od języka - w c # często wcina się wewnątrz przestrzeni nazw, w klasie i w swojej metodzie. Jesteś już na 3 poziomach wcięcia, zanim nawet porozmawiasz o tym, że ciała instrukcji kontroli przepływu są zębaty.
PeterL,
3
@LightnessRacesinOrbit Interpretuję komentarz „Tabs to 8 znaków”, aby nie oznaczać, że musisz osobiście wyświetlać tabulatory w edytorze o szerokości 8 znaków, ale do celów innych reguł w przewodniku po stylach (takich jak „Limit długości linii ma 80 kolumn i jest to zdecydowanie preferowany limit. ”) tabulatory należy traktować jak 8 kolumn, ma to również znaczenie dla innych reguł dotyczących wyrównania argumentów w wywołaniach funkcji. Ponownie, nie sądzę, że intencja tego wiersza w ogóle zmusza cię do wyświetlania kart w ten sposób, wcześniej zrobiłem łatanie jądra z 4 szerokimi kartami i na końcu poprawiłem kod.
Vality
4
@underscore_d: Wygląda na to, że się mylę: Outside of comments, documentation and except in Kconfig, spaces are never used for indentation, and the above example is deliberately broken.- 6 akapitów poniżej cytatu w PO.
slebetman
16

Chodzi o to samo, co w przypadku dowolnych konstrukcji kontroli przepływu: jeśli kod jest trudny do zrozumienia, należy go przefiltrować. Jeśli wykonujesz prostą manipulację tablicą wielowymiarową, odpowiednie może być zagnieżdżenie pętli o głębokości pięciu lub sześciu, o ile logika w najbardziej wewnętrznej pętli jest prosta. Jeśli jednak przetwarzasz skomplikowaną logikę biznesową, a ciało pętli ma kilkanaście linii lub więcej, prawdopodobnie nie będziesz chciał zagnieżdżać tej głębokości więcej niż jednej pętli. Możesz spróbować obliczyć cykliczną złożoność kodu, ale tak naprawdę sprowadza się to do czytelności i łatwości konserwacji danego kodu.

TMN
źródło
11
Dokładnie. Zbyt łatwo jest zasugerować, że Torvalds jest wariatem. (Jest oczywiście.) Może być zbyt sztywny jak na twój gust, ale opisuje prawdziwą troskę o rozwój, która powoduje prawdziwe problemy. Nie musisz robić dokładnie tego, co mówi, ale powinieneś pomyśleć o tym, dlaczego to mówi.
Scant Roger
7
@ScantRoger W rzeczywistości cytat Torvaldsa brzmi zbyt sztywno, tylko jeśli nie masz poczucia humoru. Jak pamiętam, wcześniej w tym samym dokumencie sugeruje wydrukowanie kopii wytycznych dotyczących stylu kodowania GNU, tylko po to, aby je spalić podczas jakiejś ceremonii. Prawie nie weźmiesz tego na poważnie, prawda? W tym cytacie jego głównym celem jest zdefiniowanie wcięcia dla jądra Linuksa, które ma być ośmioma spacjami, niczym więcej i niczym innym, właśnie tym jest sztywny. Ostatnie zdanie ma jedynie podkreślić ten punkt, a nie powiedzieć, że nie wolno używać więcej poziomów wcięć - nie sugeruje się sztywności.
cmaster
1
@cmaster Dzięki za kontekst, zaraz! W odpowiedzi na twoje zapytanie nie biorę niczego poważnie. ;)
Scant Roger
2
@cmaster, a następnie odczytuje się jego odpowiedzi na żądania ściągania github i długość linii komunikatów zatwierdzania. Jest totalnym przypadkiem.
Gusdor,
3
Uroczyste spalanie wytycznych kodowania GNU może nie być w rzeczywistości konieczne, ale jest całkowicie w porządku w dowolnym momencie.
dmckee,
13

Czy Linus żartował?

Utwór został napisany w zabawny styl, który sugeruje, że autor zna sposób, w jaki styl kodowania jest omawiany przez poważnych praktyków: wszyscy mamy swoje preferencje i bronimy ich wściekle, ale z językiem przynajmniej częściowo w policzek. Doskonale rozumiemy, że większość z nich to kwestia osobistego gustu. Mówi w wielu słowach "Coding style is very personal, and I won't _force_ my views on anybody"- przynajmniej poza kodem, który osobiście utrzymuje. Ale spójność stylu w danym projekcie to bardzo dobry pomysł. Wolę kodować do stylu, którego nie lubię, niż zajmować się wieloma stylami w danej funkcji.

Oto przykład wyraźnie zabawnego pisania:

However, there is one special case, namely functions: they have the
opening brace at the beginning of the next line, thus:

int function(int x)
{
    body of function
}

Heretic people all over the world have claimed that this inconsistency
is ...  well ...  inconsistent, but all right-thinking people know that
(a) K&R are _right_ and (b) K&R are right.  Besides, functions are
special anyway (you can't nest them in C).

Zabawny (1).

Prawdopodobnie jest to dobra rada, aby powstrzymać wcięcia przed wymknięciem się spod kontroli, chociaż trzypoziomowe maksimum może być hiperboliczne. Nie zamierzam grepować źródła jądra i liczyć sekwencji czterech znaków tabulatorów, ale założę się, że pieniądze można znaleźć co najmniej jeden napisany przez Torvaldsa.

Z drugiej strony, jeśli ktoś może napisać jądro Linuksa bez przekraczania trzech poziomów wcięcia, trzypoziomowy limit może być ćwiczeniem, które warto wypróbować przez chwilę we własnym kodzie, aby zobaczyć, dokąd cię zaprowadzi. Wiesz, to nie jest zmiana płci. To nie jest zobowiązanie na całe życie.

Jeśli natkniesz się na kogoś w Internecie, który myśli, że rozumie programowanie znacznie lepiej niż Torvalds (2), to wiesz, jak ludzie lubią rozmawiać w Internecie.

Z drugiej strony, on nie ma racji kryminalnej co do tabulatorów z ośmioma spacjami. To jest szaleństwo człowieka, który powinien być trzymany w ryzach i karmiony przez szczelinę. Cztery spacje są oczywiście poprawne.

(1) Zwróć jednak uwagę na to, jak błędnie stawia spację przed elipsami oraz dwie spacje za nimi i dwie spacje po kropce. ŹLE, ŹLE, ŹLE. A potem ma bezczelną żółć, by orzec heretyków. Heretyk to ty, Torvalds! TO TY!

(2) Jeśli chcesz porozmawiać o „ zrozumieniu, jak zaprojektować system kontroli źródła ”, może być miejsce na debatę.

Uwaga: Drogi przyjacielu, który wielokrotnie przesyłasz tę samą edycję: Formatowanie cytowanego materiału jest zachowywane dokładnie tak, jak chciał tego autor. To dlatego, że pochodzi z eseju na temat formatowania tekstu o stałej szerokości, napisanego w tekście o stałej szerokości, przez kogoś, kto dobrze przemyślał formatowanie tekstu o stałej szerokości. Formatowanie jest świadomą i celową częścią intencji autora i odnosi się do tematu.

Ponadto powróciłem do tego formatowania we własnym tekście. Jeśli wyjmiesz wstępne formatowanie, mój przypis (1) staje się bełkotem. Jeśli wstępne formatowanie zostanie usunięte, to powinien być tekst w moim przypisie (1) odnoszący się do par spacji po kropkach na końcach zdań. W każdym razie widzę uzasadnienie usunięcia tego przypisu, ponieważ jest on mniej zabawny niż się wydawało, kiedy go napisałem. Ale usunięcie formatowania bez usuwania przypisu jest nieprzydatne.

Ed Plunkett
źródło
3
Cudowna odpowiedź. Jeden z przypadków, który zasługuje na +2 ... (Uwaga: .W tym komentarzu nie ma złych spacji ;-))
cmaster
2
Wskazany przez ciebie akapit wprowadzający Linusa jest bardzo ważny, więc dziękuję za to! Myślę, że pierwsze zdanie jest również bardzo ważne dla kontekstu, preferred coding stylea takżebut this is what goes for anything that I have to be able to maintain
Chris Haas,
9

Linus ma bardzo tępy styl mówienia i poczucie humoru, ale w tym przypadku nie żartował. Istnieją sytuacje, w których algorytm wymaga zagnieżdżenia głębszego niż dwa poziomy, ale można to zrobić przy użyciu innych środków niż wcięcie kodu. Przewodnik po stylach jądra Linuksa zdecydowanie preferuje te inne metody, ze względu na trudność w utrzymywaniu głęboko zagnieżdżonych pętli, i tak właśnie mówi Linus.

W przypadku niektórych przykładów alternatywnych metod można użyć rekurencji, podzielić wewnętrzne pętle na ich własne funkcje lub utworzyć pośrednie struktury danych.

Nadmierne zagnieżdżanie jest jednym z tych przypadków, które są łatwiejsze do napisania, ale trudniejsze do odczytania. Ustawienie dużej głębokości tabulatora jest sposobem Linusa na uczynienie pisania bardziej denerwującym.

Karl Bielefeldt
źródło
3

Istnieje wiele pytań, w których rada jest inna dla osoby zadającej pytanie niż dla osoby, która nie zadaje pytania. Jeśli zapytasz „Czy powinienem kiedykolwiek mieć pętle zagnieżdżone na głębokości większej niż dwa poziomy”, to dla ciebie, osoby zadającej to pytanie, odpowiedź brzmi NIE. Jeśli zapytasz, nie rób tego. Jeśli masz wystarczająco dużo doświadczenia, że ​​nie musisz pytać, to wiesz, jaka jest poprawna odpowiedź w każdym przypadku. I nie kłóc się, jeśli nie zgadzasz się z odpowiedzią, ponieważ odpowiedź nie jest dla ciebie.

gnasher729
źródło
1

Wydawałoby się, że jest to podręcznikowy podręcznik ogona machającego psem.

Jeśli masz 80 znaków, to oczywiście spróbujesz dopasować kod najlepiej, jak potrafisz, nawet jeśli nie tworzy on najlepszej struktury kodu .

Zajmij się resztą swoich punktów:

Uznałem, że to niedopuszczalna praktyka.

Myślę, że w to za dużo czytasz. Opieraj się pragnieniu przyjęcia wszystkiego, co czytasz jako ewangelii, bez właściwego zrozumienia kontekstu.

Czy on żartował?

Trudno ustalić kontekst, ale patrz mój pierwotny punkt powyżej.

Czy to zależy od języka lub aplikacji?

Bardzo tak. Weź dowolny język mainframe / średniotonowy, w którym prawdopodobnie będziesz kodować na terminalu (lub emulatorze terminala).

Czy są jakieś rzeczy, które absolutnie wymagają trzech lub więcej poziomów zapętlenia?

Tak, jest to bardzo powszechne w niektórych algorytmach brutalnej siły. Zobacz problem 31 na Project Euler. Jest to klasyczny przykład problemu, który można rozwiązać brutalną siłą za pomocą szeregu pętli (dokładnie 8).

Robbie Dee
źródło
1
Wygląda na to, że Problem 31 nie wymaga bruteforce i można go rozwiązać za pomocą algorytmu programowania dynamicznego (edycja: co oznacza, że ​​struktura kodu nie jest najlepsza, jeśli używasz algorytmu bruteforce). Ponadto Linus ma na myśli to, że jeśli twój kod wymaga wielu poziomów wcięć, prawdopodobnie nie jest to najlepsza struktura dla kodu.
Vincent Savard
2
@VincentSavard Nigdy nie powiedział, że wymaga brutalnej siły. Nie zgadzaj się z drugim punktem - czasami jest to najczystsze i najbardziej zwięzłe podejście, nie wspominając o najbardziej efektywnym w niektórych przypadkach.
Robbie Dee,
1
Przy tego rodzaju problemach zwykle nie wcina się pętli. Myślę, że miałem jeden przypadek z 20 zagnieżdżonymi pętlami, absolutnie trywialny do napisania i bez wcięć, dzięki czemu można było zobaczyć, że pętle były prawie identyczne.
gnasher729,
1
@RobbieDee: Chodzi mi o to, że twoim przykładem problemu rozwiązanego przez wiele pętli jest to, że twój algorytm nie jest tak wydajny jak rozwiązanie do programowania dynamicznego, które nie wymaga tak wielu poziomów wcięcia. Tak więc, jak powiedział Linus, twoje poziomy wcięcia można usunąć, używając lepszego rozwiązania. Źle zrozumiałeś moją drugą uwagę, ponieważ zgadzam się z tym, co powiedziałeś. Czasami jest to najlepsze rozwiązanie. Czasami nie jest często i jest mało prawdopodobne.
Vincent Savard,
1
Cytat Linusa dość wyraźnie mówi, że jeśli jakiś kod wymaga czegoś takiego jak brutalne zmaganie się z Problem-31, to i tak jesteś spieprzony - nie będzie to szybkie ani proste, a operacje jądra muszą być szybkie i proste. Włączenie do jądra dowolnego algorytmu O (n ^ 4) stanowi znaczne ryzyko problemów z wydajnością lub odmową usługi, dlatego w tym kontekście zalecenie po prostu ostrzega, że ​​jest to znak kodu, który może być zasadniczo niewłaściwy i pożądany w Linuksie.
Peteris,
0

Czy Linus żartował?

Nie, to są oficjalne wytyczne.

Czy to zależy od języka lub aplikacji?

Wskazówki dotyczące kodowania są generalnie zależne od języka i aplikacji, jednak głęboko zagnieżdżony kod zawsze obciąża czytelnika.

Problem z zagnieżdżonym kodem polega na tym, że ogólnie zwiększa on złożoność cykliczną: to znaczy, im bardziej zagnieżdżony jest kod, tym więcej potencjalnych ścieżek wykonania istnieje w funkcji. Kombinatoryczna eksplozja potencjalnych ścieżek wykonania utrudnia rozumowanie na temat kodu i dlatego należy go ogólnie unikać.

Dlaczego więc 3? Subiektywne wytyczne kodowania są zarówno trudne do wyegzekwowania, jak i niemożliwe do wyegzekwowania automatycznie. Ustanowienie obiektywnych wytycznych kodowania na maksymalnym poziomie wcięcia wymaga uzgodnienia liczby: w jądrze Linuksa wybrali 3.

Jest to dla nich arbitralne i najwyraźniej wystarczające.

Czy są jakieś rzeczy, które absolutnie wymagają trzech lub więcej poziomów zapętlenia?

Algorytmicznie, prawdopodobnie jednak w wystarczająco wyrazistych językach zawsze możesz przeformułować kod na mniejsze fragmenty (z funkcjami lub zamknięciami).

Możesz oczywiście napisać zaciemniony kod z niewielkim zagnieżdżeniem i wieloma małymi funkcjami, które wywołują się nawzajem bez zapisywania umowy ...

... jednak małe funkcje z wyraźnymi umowami są znacznie łatwiejsze do kontrolowania niż duże funkcje z wyraźnymi umowami w ogóle.

Matthieu M.
źródło
2
Chociaż może to być oficjalna wytyczna, znalezienie w kodzie jądra miejsc, w których nie jest egzekwowana, jest banalne.
MikeB
1
@MikeB: Im więcej powodów automatycznego egzekwowania wytycznych ...
Matthieu M.,
1
@MatthieuM. Czy na pewno rozumiesz różnicę między wytycznymi a obowiązkowymi wymaganiami? Jako ogólna „zasada praktyczna” (wytyczne, jeśli chcesz), wytyczne bardziej przypominają rekomendacje i nie są egzekwowane.
Brendan