Czy prostota zawsze poprawia czytelność?

32

Niedawno opracowywałem zestaw standardów kodowania dla naszej firmy. (Jesteśmy nowym zespołem działającym w nowym języku dla firmy).

W pierwszym szkicu wyznaczyłem cel naszych standardów kodowania jako poprawę czytelności, łatwości konserwacji, niezawodności i wydajności. (Zignorowałem zapisywalność, przenośność, koszt, zgodność z poprzednimi standardami itp.)

Jednym z moich celów podczas pisania tego dokumentu było przeforsowanie idei prostoty kodu. Pomysł polegał na tym, że powinno być tylko jedno wywołanie funkcji lub operacja na linię. Miałem nadzieję, że zwiększy to czytelność. To pomysł, który przeniosłem z naszego poprzedniego języka.

Jednak zakwestionowałem założenie tego pchnięcia:

Czy prostota zawsze poprawia czytelność?

Czy istnieje przypadek, w którym pisanie prostszego kodu zmniejsza czytelność?

Powinno to być oczywiste, ale przez „prostsze” nie mam na myśli „łatwiej pisać”, ale mniej rzeczy dzieje się na linii.

Richard
źródło
16
Jeśli alternatywą jest „sprytny” kod, to tak…
Oded
2
tak - per Razam Razor - en.wikipedia.org/wiki/Occam%27s_razor
aggietech
17
Staraj się unikać używania sztywnych terminów jak zawsze i nigdy. Ma to na celu uniknięcie skupiania się na przypadkowych przypadkach, a zamiast tego skupienie się na najczęściej spotykanych problemach. Na tym polegają najlepsze praktyki.
P.Brian.Mackey,
właściwie potrzebujesz 2 funkcji / operacji na linię. a = bto jedna operacja, b + cto druga, co oznacza a = b + c2 operacje. Łączenie 2 funkcji / operatorów jest nadal czytelne: foo(bar())lub a = foo().
zzzzBov,
2
Nie martw się też zbytnio. Jeśli spróbujesz wyeliminować każdą subiektywność z twoich wyjaśnień, tak jak jeśli spróbujesz określić każdy możliwy szczegół stylu kodowania w milionie lub więcej reguł, twoje standardy będą nadmiernie złożone, nieczytelne, zignorowane, a zatem bezcelowe.
Steve314,

Odpowiedzi:

47

„Proste” to nadużywane słowo. „Czytelny” można z zyskiem zdefiniować jako „prosty do zrozumienia”, w którym to przypadku zwiększenie (ta miara) prostoty z definicji zwiększa czytelność, ale nie sądzę, że o to ci chodzi. Mam napisane o tym gdzie indziej , ale na ogół coś można nazwać „prostsze” albo będąc bardziej abstrakcyjne (w tym przypadku mniej koncepcje mogą wyrazić więcej zjawisk) lub będąc bardziej konkretne (w tym przypadku pojęcie nie wymaga tyle tle wiedza do zrozumienia przede wszystkim). Twierdzę, że w zależności od perspektywy bardziej abstrakcyjną koncepcję można rozsądnie nazwać prostszą niż koncepcja bardziej konkretna lub odwrotnie . To, mimo że „streszczenie” i „

Jako przykładu użyję kodu Haskell, który napisałem jakiś czas temu. I zadał pytanie na stackoverflow temat korzystania monady List do obliczenia licznika, w którym każda cyfra może mieć inną podstawę. Moje ostateczne rozwiązanie (niewiele wiedząc o Haskell) wyglądało następująco:

count :: [Integer] -> [[Integer]]
count [] = [[]]
count (x:xs) =
  -- get all possible sequences for the remaining digits
  let
    remDigits :: [[Integer]]
    remDigits = count xs
  in
  -- pull out a possible sequence for the remaining digits
  do nextDigits <- remDigits
     -- pull out all possible values for the current digit
     y <- [0..x]
     -- record that "current digit" : "remaining digits" is
     -- a valid output.
     return (y:nextDigits)

Jedna z odpowiedzi ograniczyła to do:

count = mapM (enumFromTo 0)

To, które z nich jest „prostsze” do zrozumienia (tj. Bardziej czytelne), zależy całkowicie od tego, jak wygodnie czytelnik stał się z (abstrakcyjnymi) operacjami monadycznymi (i, w tym przypadku, kodem bez punktów). Czytelnik, który jest bardzo obeznany z tymi abstrakcyjnymi pojęciami, woli przeczytać (krótszą) bardziej abstrakcyjną wersję, podczas gdy ten, który nie czuje się komfortowo z tymi operacjami, woli przeczytać (dłuższą) bardziej konkretną wersję. Nie ma jednej odpowiedzi na temat tego, która wersja jest bardziej czytelna, która pomieści wszystkich.

Aidan Cully
źródło
11
Niektórzy programiści będą robić postępy, dopóki nie zrozumieją i nie preferują jednej linii. Trudno wyobrazić sobie programistę, który rozumie, że jedna linijka woli preferować długą wersję. Dlatego IMO jednowarstwowa jest wyraźnie lepsza.
kevin cline,
7
@kevincline - zakładając, że programista pracuje w izolacji, zgadzam się, że krótsza wersja jest (prawdopodobnie) lepsza. Jeśli pracuje jako część zespołu, a zespół nie znajduje się na poziomie, na którym rozumieją i wolą jednolinijkę, i wszyscy muszą być w stanie utrzymać kod, to długa wersja jest (prawdopodobnie) lepsza w takich okolicznościach .
Aidan Cully,
6
Jako kontrapunkt: biorąc pod uwagę, że jesteś doświadczonym Haskellerem, możesz przeczytać drugą wersję w skrócie. Z drugiej strony pierwsza wersja wymagałaby czytania i zrozumienia znacznie większej ilości kodu; nie można tego zrobić na pierwszy rzut oka. Myślę, że dzięki temu druga wersja jest prostsza.
Tikhon Jelvis
6
@ Steve314: mapMjest dość idiomatyczny i enumFromTorobi dokładnie to, co mówi na puszce. Ogólnie rzecz biorąc, uważam, że łatwiej jest popełniać błędy „jeden po drugim”, jeśli rozszerzysz kod - jest po prostu więcej kodu do popełnienia błędu. Jest to szczególnie widoczne w przypadku pętli w porównaniu z procedurami wyższego rzędu w innych językach , ale uważam, że jest to ogólna zasada.
Tikhon Jelvis,
1
@ Tikhon - ale to niekoniecznie oznacza odczytanie tak dużej ilości kodu, a kod jest właśnie tam. Oznacza to, że mogą wystąpić kompromisy. Zwykle bardzo jednostronny na rzecz korzystania z istniejących funkcji zamiast ponownego wynalezienia koła, ale są wyjątki. Staje się to bardzo oczywiste w C ++, z kilkoma bardziej trywialnymi „algorytmami” w standardowej bibliotece - używanie ich może czasami być bardziej szczegółowe i mniej jasne niż pisanie kodu bezpośrednio.
Steve314,
13

Jeśli twój standard kodowania dotyczy „Czytelności, łatwości konserwacji, niezawodności i wydajności”, po prostu to zaznacz .

Nie próbuj opisywać, jak osiągnąć te cele, ponieważ zawsze będą sytuacje, w których istnieje przeciwny przykład.

To, co musisz przepisać, to rzeczy, które spowodują uszkodzenie kodu, jeśli nie będą również przestrzegane. Cechy stylistyczne nie będą łamać kodu i powinny być sugestiami (o ile większość członków zespołu zgadza się, że to czytelność, reszta powinna być preferencją programisty (z recenzją kodu, aby presja rówieśników przypominała ludziom, że inne osoby muszą czytać kod)) .

Martin York
źródło
To był cel, do którego dążyłem i taki był deklarowany cel. Wydaje się, że prostota (a raczej jedna funkcja / operacja na linię) naturalnie wynika z tego celu. Próbuję ustalić, czy moje zrozumienie było nieprawidłowe. Kiedy budujesz standardy kodowania, ustalenie zestawu zasad i wytycznych jest celem całego ćwiczenia. Zbyt ogólne ustalanie zasad i wytycznych jest bezużyteczne. W związku z tym ta odpowiedź naprawdę nie pomaga.
Richard
5
Moim argumentem jest to, że ustalanie zbyt surowych reguł jest gorsze niż bezużyteczne i jest w rzeczywistości szkodliwe. Ustawianie reguł, takich jak jedna instrukcja na wiersz, jest stylistyczne. Jest to rzecz, która zdecydowanie NIE powinna znajdować się w wytycznych do kodu. Nie zapewnia rzeczywistych korzyści i może być szkodliwy dla czytelności i konserwacji, jeśli zastosuje się go bez namysłu.
Martin York,
3
+1 (ponieważ nie mogę +10) Częstym błędem, który widzę w przypadku nowych menedżerów programowania, jest to, że próbują skodyfikować każdy ostatni szczegół. Najlepsze standardy kodowania bardziej przypominają ciasteczka z wróżbą niż przepisy.
JohnFx,
„Style i standardy kodowania” to nazwa dokumentu. Oczywiście nie jest to standard (jak w „Nigdy nie używaj GoTo” lub „Nigdy nie używaj krótkich int”), ale styl. Styl ujednolicenia jest ważny dla czytelności i łatwości konserwacji.
Richard
1
Przewodnik po stylach: „Ten projekt używa tabulatorów / spacji (wybierz jeden). Ten projekt używa stylu nawiasu klamrowego K & R / Allman / BSD / GNU (wybierz jeden). Nie dodawaj pustych spacji na końcu linii. Zachowaj swój kod czysty i czytelny. Wszystko zostanie poddane przeglądowi przez dwóch członków zespołu i przez ciebie: w celu zapewnienia czytelności / konserwacji potrzebujesz większości 2/3, aby sprawdzić kod, dla niezawodności i wydajności potrzebujesz 3/3 (proszę przedstawić odpowiednie testy, aby udowodnić ). Więcej reguł zostanie dodanych, jeśli zostaną naruszone :-) „Gotowe.
Martin York,
7

Mniej „rzeczy w wierszu”, prostota i czytelność to nie to samo. Można wziąć niezwykle skomplikowany, nieudokumentowany algorytm i kodować go za pomocą 1 instrukcji na linię zamiast 2, i nie będzie on o wiele bardziej czytelny.

Mniej „ilości na linię” może również wymagać dostarczenia programistom wielkich, dużych monitorów, aby zobaczyć, jak bloki kodu rozkładają się teraz bardziej pionowo. Lub powodować zmęczenie oczu podczas czytania czcionek o mniejszej grubości.

Czytelność to bardzo własna metryka, która często wymaga kompromisu między kilkoma innymi, łatwiejszymi do zmierzenia metrykami. Wstępnie ogranicz wszystkie inne metryki, a kompromis nie będzie już możliwy, co spowoduje, że kod będzie mniej czytelny.

hotpaw2
źródło
5

Zawsze? - NIE

Jak na ironię, osiągnięcie odpowiedniego poziomu prostoty może być złożonym przedsięwzięciem. Myślę, że klucz jest z umiarem. Prostota może być również w oku patrzącego, więc jeśli okaże się, że się nad tym zastanawiasz - po prostu zostaw to w spokoju lub wróć do niego później.

Osobiście, kiedy próbuję wrócić i uprościć coś, co napisałem, koncentruję się na obszarach, w których zmieniłem zdanie lub próbowałem kilku rzeczy, aby uzyskać to, czego chciałem. Te obszary można zwykle wygładzić. Następnie wykonaj kilka przejść przez kod, aby uczynić go bardziej czytelnym, bez rozrzucania rzeczy tak bardzo, że przeskakujesz po całym miejscu, aby dowiedzieć się, co dzieje się podczas debugowania.

DKnight
źródło
5

Jeśli pójdę dla uproszczenia, mogę napisać taki kod:

10000000000000000000000000000000000000000000

Ale jeśli pójdę na czytelność, wolę to:

1e43

Z drugiej strony 1000jest o wiele bardziej czytelny i prosty niż, 1e3chyba że cały czas pracujesz z liczbami w notacji naukowej.

Jest to zdegenerowany przykład znacznie bardziej ogólnego wzorca, który można znaleźć prawie wszędzie - budowanie czegoś z bardzo prostych bloków może szybko stać się nieczytelne / nieefektywne / złe na wiele różnych sposobów. Z drugiej strony uogólnianie i ponowne wykorzystywanie jest na początku trudniejsze („wtf jest e?! Czy oni chcieli pisać 1343?”, Ktoś mógłby powiedzieć), ale na dłuższą metę może bardzo pomóc.

Rotsor
źródło
Twój punkt, w którym „1e3” jest mniej czytelny niż „100”, jest dobrze sformułowany. W rzeczywistości jest to doskonały przykład wpływu obciążenia poznawczego na czytelność. „1e3” wymaga odczytania 3 znaków ORAZ przetłumaczenia potęgowania. Odczyt „100” wymaga odczytania 3 znaków i bez dalszej oceny.
Stephen Gross
Stephen, właściwie podczas odczytywania trzycyfrowej liczby, takiej jak 100musisz wykonać dwa mnożenia i dwa dodawania ( 0+10*(0+10*1)). Jednak przyzwyczajając się do tego zapisu, nawet tego nie zauważasz. To ponownie pokazuje, jak subiektywne może być pojęcie prostoty.
Rotsor,
Ciekawy. Ściśle mówiąc, „100” wymaga 2 mnożenia (1 * 100, 0 * 10) i 2 operacji dodawania. „1e3” wymaga jednej operacji mnożenia. Zatem bez kontekstu poznawczego „100” jest trudniejszy do odczytania niż „1e3”. Ale! Jeśli uwzględnisz obciążenie poznawcze z przełączaniem kontekstu, obliczenia będą inne. Ponieważ zwykle odczytujemy liczby całkowite w formie nienaukowej, łatwiejsze jest „100”. Ale jeśli piszemy aplikację inżynierską, w której wszystkie liczby są wyrażone w notacji naukowej, forma „1e3” jest łatwiejsza!
Stephen Gross
2

Niekoniecznie. Jeśli masz złożoną operację, ta złożoność musi gdzieś pójść. Zmniejszenie liczby „rzeczy” w jednej linii oznacza po prostu, że zajmie więcej linii, co może być szkodliwe dla czytelności kodu, jeśli sprawi, że twoja procedura będzie zbyt „wysoka”, aby zmieściła się na jednym ekranie.

Mason Wheeler
źródło
Złożoność nie jest nieredukowalna. Mamy „abstrakcję” i „dzielenie” oraz „organizację”, aby spróbować poradzić sobie ze złożonością. Myślę, że złożoną operację można opisać w kilku prostszych krokach. Działa w wielu rzeczywistych procesach fizycznych: streszczenia, przeglądy itp.
S.Lott
1
@ S.Lott: To prawda, ale wystarczająca ilość przewijania i klikania z wciśniętym klawiszem Ctrl może utrudnić wykonanie „uproszczonego” procesu. Widziałem to raz lub dwa razy (nie jest to powszechne, ale może być bardzo frustrujące, gdy idzie za daleko).
FrustratedWithFormsDesigner,
3
@ S.Lott - nadal istnieją granice, w jakim stopniu można zmniejszyć złożoność. Możesz wyeliminować niepotrzebną złożoność, ale możesz zarządzać tylko (a nie eliminować) niezbędną złożonością - złożonością związaną z wymaganiami. Prawdopodobnie mechanizmy zarządzania złożonością również zwiększają złożoność - pewna dodatkowa złożoność wiąże się z przesunięciem nieistotnej złożoności na bok, aby lepiej ujawnić istotne szczegóły dla konkretnego aspektu / problemu / konstrukcji.
Steve314,
1
@ S.Lott - Cóż, z pewnością prawdą jest, że możesz reprezentować dowolne wymagania za pomocą pliku źródłowego (całkowicie pustego) o zerowej złożoności. Ale ponieważ potrzebujesz bardzo konkretnego języka, aby spełnić swoje wymagania, wszystko, co robisz, to przeniesienie wymagań do specyfikacji języka.
Steve314,
1
@ S.Lott - jeśli twierdzisz, że możesz przewidzieć pozycję Jowisza w Boże Narodzenie za pomocą niczego G=0, myślę, że jesteś szalony. Jeśli nie, nie rozumiesz mnie. Z pewnością możesz wyodrębnić nieistotne szczegóły, ale nie jest to nieistotne, jeśli twoje wymagania mówią, że są istotne. Jeśli przeczytacie, nigdy nie twierdziłem, że cała złożoność jest konieczna - tylko że pewna złożoność jest nieodłączna od wymagań i nie można jej wyeliminować.
Steve314,
2

Klarowność + standardy + ponowne użycie kodu + dobre komentarze + dobry projekt może poprawić czytelność .

Prostota nie zawsze leży w gestii programisty, ponieważ natura algorytmów i złożoność struktury aplikacji w dzisiejszych czasach.

Weź proste strony internetowe, które wykonują proste zadania. Biorąc pod uwagę procedurę sortowania, nie można uprościć logiki, ale można ją wyjaśnić za pomocą komentarzy, używając znaczących nazw zmiennych, zapisując je w uporządkowany sposób itp.

Bez szans
źródło
2

Czy prostota zawsze poprawia czytelność?

Nie. Widziałem wiele przypadków, w których wykonywanie wielu prostszych rzeczy na jednej linii jest mniej skomplikowane niż posiadanie wielu linii.

Istnieje kompromis między mniejszym kodem a prostszym kodem.

Zasadniczo polecam wybranie prostszego kodu, chyba że na pewno wykonanie go w mniejszej liczbie wierszy jest lepsze. Wolałbym mieć „zbyt szczegółowy” kod nad „zbyt złożonym” kodem.

Tom Squires
źródło
1

„Spraw, aby rzeczy były jak najprostsze, ale nie prostsze” - często parafraza Alberta Einsteina

Prostota poprawia wszystko . Oczywiście dla różnych wartości prostoty. Czy to mniej linii kodu? Może. Czy jest to mniejszy plik wykonywalny? Możliwie. Czy Twój zespół musi się z tym zgodzić? Absolutnie .

Jesse C. Slicer
źródło
+1 za cytat, ale czy prostota poprawia czytelność?
Richard
„Spraw, aby rzeczy były tak proste, jak to możliwe, a następnie uprość je” to lepsza parafraza, ponieważ inżynierowie SW mają skłonność do nadmiernej inżynierii.
mattnz
1
Chciałbym, żeby ludzie przestali mówić „uprościć sprawy tak, jak to możliwe, ale nie prościej”. Czy nie możemy przynajmniej uogólnić na MakeAsGoodAsPossibleButNoMoreSo <Rzecz, atrybut>, gdy przechodzimy do niepotrzebnie ogólnej wskazówki inżynieryjnej? (Przepraszamy @Jesse C. Slicer, jesteś daleki od jedynej osoby, która to zacytowała, więc tak naprawdę nie zasługujesz na mini-rant bardziej niż ktokolwiek inny).
psr
1

Czy prostota zawsze poprawia czytelność? Tak. Czy jedno zdanie na wiersz jest zawsze prostsze? Nie. Dość kilka języków ma operator trójskładnikowy, który po uchwyceniu jest prostszy i łatwiejszy do zrozumienia niż równoważne przypisania if / else.

W językach, w których można ustawić wiele zmiennych w jednym wierszu, jest to często prostsze i łatwiejsze do zrozumienia niż cokolwiek równoważnego.

Kolejny przykład: wyrażenia regularne robią dużo, zwykle w jednym wierszu, a odpowiednik bez wyrażenia regularnego jest często znacznie trudniejszy do odczytania. / \ d {3} [-] \ d {3} - \ d {4} / jest równoważne wywołaniu funkcji z co najmniej kilkoma komentarzami i jest łatwiejsze do zrozumienia niż odpowiednia treść funkcji.

jmoreno
źródło
1

Czytelność i prostota są terminami subiektywnymi, które w zależności od osoby i kontekstu zazwyczaj, ale nie zawsze, idą w parze.

Bardziej obiektywnym terminem jest zwięzłość - coś, co można z zasady policzyć, licząc postacie, choć są w tym pewne wady. Zwięzłość wydaje się sugerować prostotę i czytelność, ale są (przynajmniej moim zdaniem) wyjątki.

Dłuższy (i prawdopodobnie bardziej złożony) fragment kodu może być bardziej czytelny, jeśli lepiej wyraża zamiar. To, czy twoja definicja prostoty dba o intencje, jest kolejną subiektywną rzeczą - możesz zdefiniować złożoność pod względem struktury składniowej i entropii informacji-teorii, na przykład bez żadnego odniesienia do intencji.

Zatem dobrze wybrana dłuższa nazwa zmiennej może ...

  • Popraw czytelność, lepiej wyrażając intencje
  • Zmniejsz zwięzłość - w końcu jest dłuższa
  • Nie mają żadnego wpływu na prostotę składniową - struktura składniowa kodu pozostaje niezmieniona

Podobnie mogę pisać if (some_boolean == true). W porównaniu z równoważną alternatywą if (some_boolean)ten ...

  • Zmniejsza zwięzłość
  • Zmniejsza prostotę składniową, ale
  • Może poprawić czytelność poprzez lepsze wyrażanie intencji.

Oczywiście ten wywoła masowy protest - dla wielu ludzi zawsze szkodzi to również czytelności. Dla mnie to zależy w dużej mierze od źródła wartości logicznej - np. Nazwa zmiennej (lub nazwa metody lub cokolwiek) może nie wyrażać jasno, że wartość jest „wartością prawdy”. Jasne, ifmówi ci coś, ale wciąż pachnie. Ale wielu ludzi nazywa mnie idiotą za to, że w to wierzę.

Co jest oczywiście kolejnym dowodem ogólnej subiektywności.

Steve314
źródło
1

Wszystkim brakuje niektórych podstawowych definicji . Prosty, z root -sim-plex , oznacza jedną fałdę . Prosty oznacza robienie jednej rzeczy . Proste, z głównym problemów , środki leżą w pobliżu . Łatwy oznacza, że ​​jest pod ręką . Przykłady prostego kodu podane w innych odpowiedziach nie są dokładnie takie, jak się pojawiają.

Weźmy wyświetlacz rotsora o bardzo dużej wartości. Mówi, że to proste . Według mnie nie jest to proste. To łatwe. Pod ręką możesz wpisać liczbę wymaganych zer.

10000000000000000000000000000000000000000000

Czytelna wersja jest prosta. Robi jedną rzecz. Wyraża liczbę, opisując jej rozmiar w celu notacji zbudowanym dla tej funkcji.

1e43

Czy możesz opisać „prosty” fragment kodu Aidana jako robienie jednej rzeczy? Zawiera 10 linii kodu (nie licząc komentarzy) i co najmniej 7 bloków (jak bym je policzył). Jeśli podążysz za komentarzami, zobaczysz, że robi co najmniej 4 rzeczy!

count :: [Integer] -> [[Integer]]
count [] = [[]]
count (x:xs) =
  -- get all possible sequences for the remaining digits
  let
    remDigits :: [[Integer]]
    remDigits = count xs
  in
  -- pull out a possible sequence for the remaining digits
  do nextDigits <- remDigits
     -- pull out all possible values for the current digit
     y <- [0..x]
     -- record that "current digit" : "remaining digits" is
     -- a valid output.
     return (y:nextDigits)

Ale jednym z zaleceń przepisywania tego kodu była jedna instrukcja. Aidan twierdzi, że czytelnik musiałby zapoznać się z instrukcjami monadycznymi, kodem bez wskaźnika itp. W porządku. Pojęcia te są wyjątkowe i niezależne.

count = mapM (enumFromTo 0)

Przekonasz się, że naprawdę prosty kod jest bardziej czytelny niż prosty, ponieważ robi tylko jedną rzecz. Może być konieczne odejście i nauczenie się więcej „jednej rzeczy”, aby zrozumieć prosty kod. Ale zawsze powinno być bardziej czytelne.

Anthony Mastrean
źródło
1

Czy prostota zawsze poprawia czytelność?

Powiedziałbym, może z odrobiną kontrowersji, absolutnie nie .

Możesz podać mi klasę z 200 funkcjami członka w interfejsie publicznym i może to być najbardziej czytelny dla ludzi interfejs publiczny. Może to być radość po prostu swobodnie czytając taki kod i jego dokumentację. Nie nazwałbym tego jednak „prostym”, ponieważ pomimo czytelności musiałbym się martwić, w jaki sposób wszystkie te funkcje współdziałają ze sobą, i potencjalnie uważać na skomplikowane przypadki krawędzi wynikające z niewłaściwego użycia.

Wolałbym klasę z 20 funkcjami składowymi, które nie były tak łatwe do odczytania, niż 200, ponieważ „czytelność” nie jest dla mnie najwyższym priorytetem pod względem zapobiegania błędom ludzkim i poprawiania możliwości utrzymania kodu (łatwości, z jaką możemy to zmienić, tj.).

Wszystko to będzie jednak zależeć od naszej osobistej definicji „prostoty”. „Czytelność” zazwyczaj nie różni się tak bardzo wśród nas, chyba że ktoś zdobył tak dużą wiedzę i biegłość, że uważają wyrażenia regularne za bardzo „czytelne”, np. Zapominając o reszcie z nas zwykłych śmiertelników.

Prostota

Dawno, dawno temu myślałem, że „prostota” oznacza „tak łatwy do odczytania, jak to możliwe”. Pisałbym więc kod C z wieloma wygodnymi funkcjami, starając się poprawić składnię i uczynić rzeczy tak łatwymi do odczytu i zapisu, jak to możliwe.

W rezultacie zaprojektowałem bardzo duże, bogate biblioteki wysokiego poziomu, próbując modelować funkcję dla każdej naturalnej ludzkiej myśli: pomocników na pomocników na pomocników, wszystko w celu ukształtowania kodu klienta do bardziej czytelnej składni. Kod, który wtedy napisałem, mógł być najbardziej „czytelny”, ale był również najbardziej „niemożliwy do utrzymania” i „złożony”.

Seplenienie

Jednak miałem krótką pasję do LISP w połowie lat 90. (późny). Zmieniło to moją ideę „prostoty”.

LISP nie jest najbardziej czytelnym językiem. Mam nadzieję, że nikt nie myśli, że wyodrębnianie CDR i CAR podczas wywoływania funkcji rekurencyjnej z mnóstwem zagnieżdżonych nawiasów jest bardzo „czytelne”.

Niemniej jednak, po tym, jak starałem się owinąć mózg dziwną składnią języka i całkowicie rekurencyjnymi sposobami robienia rzeczy, na stałe zmieniłem mój pomysł na prostotę.

Z kodu, który napisałem w LISP, znalazłem to, że nie popełniłem już subtelnych błędów, chociaż podstępność myślenia w ten sposób sprawiła, że ​​popełniłem więcej rażących błędów (ale są one łatwe do wykrycia i poprawienia). Nie pomyliłem się co do tego, co robi funkcja, i pominąłem subtelny, nieoczekiwany efekt uboczny. Po prostu łatwiej mi było wprowadzać zmiany i pisać poprawne programy.

Po LISPu prostota stała się dla mnie minimalizmem, symetrią, elastycznością, mniejszymi efektami ubocznymi, mniejszymi, ale bardziej elastycznymi funkcjami, które łączą się w nieskończenie różnorodny sposób.

Doceniłem sposób myślenia, że ​​najbardziej niezawodny kod ze wszystkich to kod, który nie istnieje. Chociaż jest to tylko prymitywna metryka, widzę potencjał zawodności kodu na podstawie jego ilości. Poszukiwanie jak największej wygody syntaktycznej i czytelności ma tendencję do zwiększania tej wielkości o duży czynnik.

Minimalizm

Z osadzonym we mnie sposobem myślenia LISP, wolałem minimalistyczne API. Wolałbym bibliotekę z mniejszą, ale bardziej niezawodną, ​​elastyczną funkcją, która jest mniej wygodna i potencjalnie trudniejsza do odczytania, niż ta, która oferuje mnóstwo „wygodnych” pomocników i takich, które mogą ułatwić „odczytanie” kodu, ale potencjalnie potkną się więcej problemów z zawodnością i niespodziankami, które wynikają z niezrozumienia, co robi jedna z tych tysięcy funkcji.

Bezpieczeństwo

Kolejną rzeczą w LISP było bezpieczeństwo. Promował minimalne skutki uboczne i czyste funkcje, i wtedy już nie widziałem, że popełniam subtelne błędy, mimo że trudność w czytaniu i pisaniu w języku zwiększyła więcej rażących błędów, które mogłem zauważyć 10 sekund później.

Czyste funkcje i niezmienne stany stały się dla mnie lepsze, gdy tylko było mnie na to stać, nawet jeśli składnia:

sword = sharpen(sword)

... jest nieco mniej bezpośredni i oderwany od ludzkiego myślenia niż:

sharpen(sword)

Czytelność VS. Prostota

Po raz kolejny LISP nie jest najbardziej „czytelnym” językiem. Może spakować dużo logiki do małej sekcji kodu (być może więcej niż jednej ludzkiej myśli w wierszu). Idealnie wolę jedną myśl ludzką na wiersz dla „czytelności”, ale niekoniecznie dla „prostoty”.

Przy takiej definicji „prostej”, czasami „prosta” może w rzeczywistości konkurować z „czytelną”. Rozważa to więcej z punktu widzenia projektowania interfejsu.

Prosty interfejs oznacza, że ​​musisz nauczyć się znacznie mniej rzeczy do korzystania z niego, a potencjalnie ma większą niezawodność i mniej gotów dzięki minimalizmowi. Kompleksowa dokumentacja na ten temat może pasować do broszury, a nie do ogromnej ilości książek. Niemniej jednak może to wymagać nieco więcej pracy i uzyskania mniej czytelnego kodu.

„Prosty” dla mnie poprawia naszą zdolność do zrozumienia funkcjonalności naszego systemu na szerokim poziomie. „Czytelny” dla mnie poprawia naszą zdolność łączenia każdej małej linii kodu z naturalnym językiem i myślami i może przyspieszyć nasze rozumienie tego, co robi jedna linia kodu, szczególnie jeśli nie znamy tego języka.

Regex jest przykładem tego, co uważam za „wyjątkowo proste”. To „zbyt proste i zbyt nieczytelne” jak na mój osobisty gust. Pomiędzy tymi ekstremami jest dla mnie równowaga, ale regex ma taką prostotę jak LISP, jak ją definiuję: minimalizm, symetrię, niesamowitą elastyczność, niezawodność itp. Problem z regexem jest taki, że jest tak prosty, że stał się tak nieczytelny, że nie sądzę, żebym kiedykolwiek się nim posługiwał (mój mózg po prostu nie działa w ten sposób i zazdroszczę ludziom, którzy potrafią płynnie pisać kod wyrażenia regularnego).

W każdym razie taka jest moja definicja „prostoty” i jest ona całkowicie niezależna od „czytelności”, a czasami może nawet zakłócać inne, prowadząc do równowagi między bardziej „wygodną syntaktycznie” i czytelną, ale większą biblioteką lub „syntaktycznie” niewygodna ”, mniej czytelna, ale mniejsza biblioteka. Zawsze znajdowałem prawdziwe priorytety „wygody rozumienia” i prawdziwe „łatwości konserwacji”, aby dostosować się do tych ostatnich, z silną preferencją wobec minimalizmu, nawet przy pewnym koszcie czytelności i bardziej naturalnej ludzkiej składni (ale nie do regexu) . YMMV.


źródło
0

Zawsze? - TAK

Osiągnięcie odpowiedniego poziomu prostoty jest złożonym i trudnym przedsięwzięciem. Ale zawsze warto, ponieważ zawsze poprawia czytelność. Myślę, że kluczem jest głębokie zrozumienie. Prostota jest absolutem, mierzonym przez „nowe koncepcje” na „fragment” kodu. Kilka nowych koncepcji oznacza prostsze.

Skoncentruj się na obszarach, w których istnieje gęsta grupa pojęć, i znajdź sposoby na „fragment”, „podsumowanie” lub „streszczenie”. Wykonaj kilka przejść przez kod, aby był on prostszy i bardziej czytelny.

Dobra abstrakcja jest warta swojej wagi w złocie. Dobra abstrakcja sprawia, że ​​jest to prostsze - a zatem bardziej czytelne.

S.Lott
źródło
Nie mogę przestać myśleć, że są tam twoje przerażające cytaty, ponieważ zdajesz sobie sprawę, że „koncepcja” i „fragment” same w sobie są subiektywne. Pojedyncza koncepcja jednej osoby to połączenie różnych osób z trzema odrębnymi ideami. Trudno jest mieć absolutną i obiektywną miarę subiektywnych rzeczy.
Steve314,
@ Steve314: Przestraszyć cytaty? Nie. En.wikipedia.org/wiki/Portowanie wydaje się podobne, ponieważ opisują uproszczenie poprzez porcje. (Z wyjątkiem techniki gitarowej, która wydaje się inna.) Cytaty są tam, ponieważ istnieje tak wiele alternatywnych terminów dotyczących abstrakcji, dzielenia, podsumowywania itp. Jeśli wybiorę tylko jeden przedmiot, to abstrakcja nie jest tym samym, co dzielenie. Cytaty mają na celu podkreślenie, że jest to w jakiś sposób dyskusyjne. Jeszcze. Wyraźnie dzieje się to cały czas i wydaje się naturalną ludzką tendencją.
S.Lott
Czego nie zaprzeczam - dzielenie odbywa się cały czas i jest dobrym pomysłem. Czego zaprzeczam - że istnieje ostateczna obiektywna zasada określająca, gdzie powinny znajdować się granice między kawałkami. Moje argumenty mogą być bardziej pedantyczne niż pomocne, ale wciąż wątpię, że „zawsze” w „zawsze poprawia czytelność”.
Steve314,
@ Steve314: Zawsze streszczamy, dzielimy i podsumowujemy, aby pomóc sobie zrozumieć rzeczy. Zawsze. Tworzenie fragmentów, abstrakty, podsumowywanie („upraszczanie”) jest czymś, co zawsze robimy. Po prostu to robimy. W ten sposób nasze mózgi pojmują rzeczywistość. Uproszczenie zawsze poprawia czytelność i zawsze można to zrobić.
S.Lott,
tak. Nigdy nie powiedziałem inaczej.
Steve314,
-2

Pytania przypominają mi tę odpowiedź na temat Przepełnienia stosu, szczególnie ten cytat (zamień jakość na prostotę):

Jakość - wiesz, co to jest, ale nie wiesz, co to jest. Ale to jest wewnętrznie sprzeczne. Ale niektóre rzeczy są lepsze od innych, to znaczy mają lepszą jakość. Ale kiedy próbujesz powiedzieć, jaka jest jakość, oprócz rzeczy, które ją mają, wszystko się psuje! Nie ma o czym rozmawiać. Ale jeśli nie potrafisz powiedzieć, czym jest Jakość, skąd wiesz, co to jest lub skąd wiesz, że ona w ogóle istnieje? Jeśli nikt nie wie, co to jest, to dla wszystkich praktycznych celów w ogóle nie istnieje. Ale dla wszystkich praktycznych celów tak naprawdę istnieje. Na czym jeszcze oparte są oceny? Dlaczego ludzie mieliby płacić fortuny za niektóre rzeczy i wyrzucać inne na śmietnik? Oczywiście niektóre rzeczy są lepsze od innych - ale czym jest `` lepszość ''? - W kółko, idź, obracające się koła mentalne i nigdzie nie znajdzie się miejsca na przyczepność. Czym do cholery jest jakość? Co to jest?

Myślę, że ważne jest, aby pamiętać, że skodyfikowany standard kodowania dla wszystkich jego zalet nie zrobi dobrych programistów złymi. Słowo takie jak „prosty” może być różnie interpretowane przez różne osoby (patrz odpowiedź Aidana Cully'ego), ale może nie być takie złe. Młodsi programiści nadal będą musieli poddać przeglądowi swój kod starszym programistom i dowiedzieć się, dlaczego starsza programiści interpretują „proste” lepiej niż ich własne.

KaptajnKold
źródło
1
Dlatego w pytaniu zdefiniowałem prostotę.
Richard,
-2

Jedno wywołanie funkcji na linię jest prostsze? Spróbujmy przykładu!

=== One call per line ===
x = y.getThis()
a = x.getThat()
b = a.getSomethingElse()

=== Less "simple" version ===
b = y.getThis().getThat().getSomethingElse()

Co myślisz? Czy jedno połączenie na linię jest w rzeczywistości prostsze?

Stephen Gross
źródło
Tak. Jedno połączenie na linię jest dla mnie prostsze i łatwiejsze do odczytania. Jednak czytelność jest subiektywna. (Również to nie jest nawet bliskie odpowiedzi na pytanie.)
Richard
Cześć Stephen, czy możesz wyjaśnić, w jaki sposób uważasz, że to odpowiada na pytanie? Nie jest jasne, co próbujesz tutaj wskazać.
@MarkTrapp Nie ma problemu. W pierwotnym pytaniu zaproponowano podejście oparte na jednej funkcji na linię. W opublikowanym przeze mnie przykładzie pokazano te same dwa fragmenty kodu, jeden zaimplementowany jako pojedyncza funkcja na linię, a drugi jako wywołania metod łańcuchowych. Myślę, że połączenie łańcuchowe jest dużo łatwiejsze do odczytania: krótkie, pozbawione niepotrzebnych zmiennych tymczasowych i eleganckie.
Stephen Gross
Jeśli musisz połączyć łańcuchy pobierających, wówczas twój kod jest zaprojektowany wspólnie
Winter