Czytelne wyrażenia regularne bez utraty mocy?

77

Wielu programistów zna radość wymyślania szybkiego wyrażenia regularnego, obecnie często przy pomocy jakiegoś serwisu internetowego lub bardziej tradycyjnie w trybie interaktywnym, lub może pisząc mały skrypt, który ma opracowane wyrażenie regularne, oraz zbiór przypadków testowych . W obu przypadkach proces jest iteracyjny i dość szybki: hakuj tajemniczo wyglądający ciąg, aż dopasuje i uchwyci to, czego chcesz i odrzuci to, czego nie chcesz.

W prostym przypadku wynik może być mniej więcej taki, jak wyrażenie regularne Java:

Pattern re = Pattern.compile(
  "^\\s*(?:(?:([\\d]+)\\s*:\\s*)?(?:([\\d]+)\\s*:\\s*))?([\\d]+)(?:\\s*[.,]\\s*([0-9]+))?\\s*$"
);

Wielu programistów zna również potrzebę edytowania wyrażeń regularnych lub po prostu kodowania wokół wyrażeń regularnych w bazie kodu starszego typu. Przy odrobinie edycji w celu podzielenia go, powyższe wyrażenie regularne jest nadal bardzo łatwe do zrozumienia dla każdego, kto zna się na wyrażeniach regularnych, a weteran wyrażeń regularnych powinien od razu zobaczyć, co robi (odpowiedz na końcu postu, na wypadek, gdyby ktoś chciał wykonać ćwiczenie wymyślenia tego sami).

Jednak rzeczy nie muszą być znacznie bardziej skomplikowane, aby wyrażenie regularne stało się naprawdę tylko do zapisu, a nawet przy starannej dokumentacji (co wszyscy oczywiście robią dla wszystkich złożonych wyrażeń regularnych, które piszą ...), modyfikacja wyrażeń regularnych staje się trudne zadanie. Może to być bardzo niebezpieczne zadanie, jeśli wyrażenie regularne nie jest dokładnie testowane jednostkowo (ale wszyscy oczywiście mają kompleksowe testy jednostkowe dla wszystkich złożonych wyrażeń regularnych, zarówno dodatnich, jak i ujemnych ...).

Krótko mówiąc, czy istnieje rozwiązanie / alternatywa zapisu / wyrażenia dla wyrażeń regularnych bez utraty ich mocy? Jak wyglądałoby powyższe wyrażenie regularne z alternatywnym podejściem? Każdy język jest w porządku, choć najlepiej byłoby rozwiązanie w wielu językach, o ile wyrażenia regularne są w wielu językach.


A potem to, co robi wcześniejsze wyrażenie regularne: parsuj ciąg liczb w formacie 1:2:3.4, przechwytując każdą liczbę, gdzie spacje są dozwolone i tylko 3wymagane.

hyde
źródło
2
powiązane rzeczy na SO: stackoverflow.com/a/143636/674039
wim
24
Czytanie / edycja wyrażeń regularnych jest w zasadzie trywialne, jeśli wiesz, co mają uchwycić. Być może słyszałeś o tej rzadko używanej funkcji większości języków zwanej „komentarzami”. Jeśli nie umieścisz jednego powyżej złożonego wyrażenia regularnego wyjaśniającego, co robi, zapłacisz cenę później. Również przegląd kodu.
TC1
2
Dwie opcje, aby to wyczyścić bez rozbijania go na mniejsze części. Ich obecność lub brak różni się w zależności od języka. (1) rozszerzone wyrażenia regularne, w których białe znaki w wyrażeniu regularnym są ignorowane (chyba że poprzedzone znakiem ucieczki) i dodawany jest jednoliniowy formularz komentarza, dzięki czemu można podzielić go na logiczne fragmenty z wcięciem, odstępami między wierszami i komentarzami. (2) nazwane grupy przechwytywania, w których można nadać nazwę każdej nawiasowi, co dodaje zarówno samok dokumentację, jak i automatycznie zapełnia skrót dopasowań - znacznie lepiej niż indeksowana liczbowo tablica dopasowań lub zmienne $ N.
Ben Lee
3
Częścią problemu jest sam język wyrażenia regularnego i złe historyczne wybory w jego projekcie, które są ciągnięte jak bagaż. W zdrowym języku nawiasy grupujące są czysto syntaktycznym urządzeniem do kształtowania drzewa parsowania. Ale w implementacjach wyrażeń regularnych wracających do Uniksa mają one semantykę: wiązanie rejestrów z dopasowaniami podwyrażeń. Potrzebujesz więc bardziej skomplikowanych, brzydkich nawiasów, aby osiągnąć czyste grupowanie!
Kaz
2
Nie do końca praktyczna odpowiedź, ale warto wspomnieć, że moc wyrażeń regularnych jest dokładnie taka sama, jak w skończonym automacie. Oznacza to, że wyrażenia regularne mogą sprawdzać poprawność / parsować tę samą klasę ciągów sprawdzanych i analizowanych przez automaty skończone. Stąd czytelna dla człowieka reprezentacja wyrażenia regularnego prawdopodobnie powinna być w stanie szybko zbudować wykres i uważam, że większość języków tekstowych jest w tym naprawdę zła; dlatego do takich rzeczy używamy narzędzi wizualnych. Zajrzyj na hackingoff.com/compilers/regular-expression-to-nfa-dfa, aby uzyskać inspirację.
damix911,

Odpowiedzi:

80

Wiele osób wspomniało o komponowaniu z mniejszych części, ale nikt nie podał jeszcze przykładu, więc oto mój:

string number = "(\\d+)";
string unit = "(?:" + number + "\\s*:\\s*)";
string optionalDecimal = "(?:\\s*[.,]\\s*" + number + ")?";

Pattern re = Pattern.compile(
  "^\\s*(?:" + unit + "?" + unit + ")?" + number + optionalDecimal + "\\s*$"
);

Nie najbardziej czytelny, ale wydaje mi się, że jest wyraźniejszy niż oryginał.

Ponadto C # ma @operator, który może być dodany do łańcucha, aby wskazać, że należy go wziąć dosłownie (bez znaków specjalnych), więc numberbyłoby@"([\d]+)";

Bobson
źródło
Wystarczy teraz zauważyć, jak zarówno [\\d]+i [0-9]+powinny być tylko \\d+(no, niektórzy mogą znaleźć [0-9]+bardziej czytelny). Nie zamierzam edytować pytania, ale możesz chcieć naprawić tę odpowiedź.
hyde
@hyde - Dobry połów. Technicznie nie są to te same rzeczy - \dpasują do wszystkiego, co jest uważane za liczbę, nawet w innych systemach numeracji (chiński, arabski itp.), Podczas gdy [0-9]po prostu pasują do standardowych cyfr. Jednak dokonałem standaryzacji \\di uwzględniłem to we optionalDecimalwzorze.
Bobson
42

Kluczem do udokumentowania wyrażenia regularnego jest jego udokumentowanie. Zdecydowanie zbyt często ludzie podrzucają coś, co wydaje się być hałasem na linii, i porzucają to.

W ciągu Perl/x operator na końcu wyrażenia regularnego tłumi spacje pozwalając na dokumencie wyrażenie regularne.

Powyższe wyrażenie regularne stałoby się wówczas:

$re = qr/
  ^\s*
  (?:
    (?:       
      ([\d]+)\s*:\s*
    )?
    (?:
      ([\d]+)\s*:\s*
    )
  )?
  ([\d]+)
  (?:
    \s*[.,]\s*([\d]+)
  )?
  \s*$
/x;

Tak, to trochę pochłania pionowe białe znaki, chociaż można je skrócić bez poświęcania zbyt dużej czytelności.

A potem to, co robi wcześniejsze wyrażenie regularne: parsuj ciąg liczb w formacie 1: 2: 3.4, przechwytując każdą liczbę, gdzie dozwolone są spacje i wymagane są tylko 3.

Patrząc na to wyrażenie regularne, można zobaczyć, jak to działa (i nie działa). W takim przypadku wyrażenie regularne będzie pasować do ciągu 1.

Podobne podejścia można zastosować w innym języku. Działa tam opcja python re.VERBOSE .

Perl6 (powyższy przykład dotyczył perl5) idzie dalej z koncepcją reguł, która prowadzi do jeszcze potężniejszych struktur niż PCRE (zapewnia dostęp do innych gramatyk (bezkontekstowych i wrażliwych na kontekst) niż tylko zwykłe i rozszerzone regularne).

W Javie (gdzie ten przykład czerpie), można użyć konkatenacji ciągów, aby utworzyć wyrażenie regularne.

Pattern re = Pattern.compile(
  "^\\s*"+
  "(?:"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #1
    ")?"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #2
    ")"+
  ")?"+ // First groups match 0 or 1 times
  "([\\d]+)"+ // Capture group #3
  "(?:\\s*[.,]\\s*([0-9]+))?"+ // Capture group #4 (0 or 1 times)
  "\\s*$"
);

Wprawdzie tworzy to znacznie więcej "w ciągu, co może prowadzić do pewnych nieporozumień, może być łatwiej odczytane (szczególnie z podświetleniem składni w większości IDE) i udokumentowane.

Kluczem jest rozpoznanie siły i „jednokrotnego” napisania natury, w którą często wpadają wyrażenia regularne. Kluczem jest napisanie kodu, aby obronnie tego uniknąć, aby wyrażenie regularne pozostało jasne i zrozumiałe. Formatujemy kod Java dla zachowania przejrzystości - wyrażenia regularne nie różnią się, gdy język daje taką możliwość.


źródło
13
Istnieje duża różnica między „dokumentowaniem” a „dodawaniem podziałów linii”.
4
@JonofAllTrades Stworzenie kodu do odczytu jest pierwszym krokiem do wszystkiego. Dodanie podziałów linii pozwala także dodawać komentarze do tego podzbioru RE w tym samym wierszu (co jest trudniejsze w przypadku pojedynczej długiej linii tekstu wyrażenia regularnego).
2
@JonofAllTrades, nie zgadzam się dość mocno. „Dokumentowanie” i „dodawanie podziałów linii” nie różnią się tak bardzo, że oba służą temu samemu celowi - dzięki czemu kod jest łatwiejszy do zrozumienia. W przypadku źle sformatowanego kodu „dodawanie podziałów linii” służy temu celowi znacznie lepiej niż dodawanie dokumentacji.
Ben Lee,
2
Dodawanie podziałów linii to początek, ale stanowi około 10% pracy. Inne odpowiedzi podają więcej szczegółów, co jest pomocne.
26

Tryb „pełny” oferowany przez niektóre języki i biblioteki jest jedną z odpowiedzi na te obawy. W tym trybie białe znaki w wyrażeniu regularnym są usuwane (więc musisz użyć \s) i komentarze są możliwe. Oto krótki przykład w Pythonie, który domyślnie obsługuje to:

email_regex = re.compile(r"""
    ([\w\.\+]+) # username (captured)
    @
    \w+         # minimal viable domain part
    (?:\.w+)    # rest of the domain, after first dot
""", re.VERBOSE)

W każdym języku, który tego nie robi, wdrożenie tłumacza z trybu pełnego do „normalnego” powinno być prostym zadaniem. Jeśli martwisz się o czytelność wyrażeń regularnych, prawdopodobnie z łatwością uzasadnisz tę inwestycję czasową.

Xion
źródło
15

Każdy język, w którym używane są wyrażenia regularne, pozwala tworzyć je z prostszych bloków, aby ułatwić czytanie, a przy czymkolwiek bardziej skomplikowanym niż (lub tak skomplikowanym) jak twój przykład, zdecydowanie powinieneś skorzystać z tej opcji. Szczególny problem z Javą i wieloma innymi językami polega na tym, że nie traktują one wyrażeń regularnych jako „obywateli pierwszej klasy”, zamiast tego wymagają od nich wkradania się do języka za pomocą literałów łańcuchowych. Oznacza to wiele znaków cudzysłowu i ukośników odwrotnych, które w rzeczywistości nie są częścią składni wyrażeń regularnych i utrudniają czytanie, a także oznacza, że ​​nie można uzyskać dużo bardziej czytelnego bez skutecznego zdefiniowania własnego mini-języka i tłumacza.

Prototypowym lepszym sposobem integracji wyrażeń regularnych był oczywiście Perl z opcją białych znaków i operatorami wyrażeń regularnych. Perl 6 rozszerza koncepcję tworzenia wyrażeń regularnych z części na rzeczywiste gramatyki rekurencyjne, co jest o wiele lepsze w użyciu, ponieważ tak naprawdę nie ma żadnego porównania. Język mógł nie docenić łódki aktualności, ale jego wsparcie wyrażenia regularnego to The Good Stuff (tm).

Kilian Foth
źródło
1
Przez „prostsze bloki” wspomniane na początku odpowiedzi masz na myśli po prostu łączenie łańcuchów lub coś bardziej zaawansowanego?
hyde
7
Miałem na myśli zdefiniowanie podwyrażeń jako krótszych literałów łańcuchowych, przypisanie ich do zmiennych lokalnych o znaczących nazwach, a następnie konkatenację. Uważam, że nazwy są ważniejsze dla czytelności niż tylko poprawa układu.
Kilian Foth,
11

Lubię używać Expresso: http://www.ultrapico.com/Expresso.htm

Ta bezpłatna aplikacja ma następujące funkcje, które z czasem wydają mi się przydatne:

  • Możesz po prostu skopiować i wkleić wyrażenie regularne, a aplikacja go przeanalizuje
  • Po napisaniu wyrażenia regularnego możesz go przetestować bezpośrednio z aplikacji (aplikacja wyświetli listę przechwyceń, zamienników ...)
  • Po przetestowaniu wygeneruje kod C #, aby go zaimplementować (zwróć uwagę, że kod będzie zawierał objaśnienia dotyczące wyrażenia regularnego).

Na przykład po przedłożeniu wyrażenia regularnego wyglądałoby to tak: Przykładowy ekran z początkowo podanym wyrażeniem regularnym

Oczywiście, wypróbowanie go jest warte tysiąca słów, które go opisują. Pamiętaj również, że jestem w jakikolwiek sposób powiązany z edytorem tej aplikacji.

E. Jaep
źródło
4
czy mógłbyś wyjaśnić to bardziej szczegółowo - jak i dlaczego odpowiada na zadane pytanie? „Tylko odpowiedzi” nie są mile widziane na Stack Exchange
gnat
5
@gnat Przepraszamy za to. Masz całkowitą rację. Mam nadzieję, że moja zredagowana odpowiedź dostarczy więcej informacji.
E. Jaep
9

W przypadku niektórych rzeczy pomocne może być użycie gramatyki takiej jak BNF. Mogą być one znacznie łatwiejsze do odczytania niż wyrażenia regularne. Narzędzie takie jak GoldParser Builder może następnie przekształcić gramatykę w analizator składni, który wykonuje dla ciebie ciężkie podnoszenie.

Gramatyki BNF, EBNF itp. Mogą być znacznie łatwiejsze do odczytania i wykonania niż skomplikowane wyrażenie regularne. ZŁOTO to jedno narzędzie do takich rzeczy.

W linku wiki c2 poniżej znajduje się lista możliwych alternatyw, które można przejrzeć w Google, z uwzględnieniem niektórych dyskusji na ich temat. Jest to w zasadzie link „patrz także”, aby uzupełnić moją rekomendację dotyczącą silnika gramatycznego:

Alternatywy dla wyrażeń regularnych

Przyjmując, że „alternatywa” oznacza „semantycznie równoważne narzędzie o różnej składni”, istnieją przynajmniej te alternatywy dla / z RegularExpressions:

  • Podstawowe wyrażenia regularne
  • „Rozszerzone” wyrażenia regularne
  • Wyrażenia regularne zgodne z Perlem
  • ... i wiele innych wariantów ...
  • Składnia RE w stylu SNOBOL (SnobolLanguage, IconLanguage)
  • Składnia SRE (RE jako EssExpressions)
  • różne składnie FSM
  • Gramatyka przecięcia stanu skończonego (dość ekspresyjna)
  • ParsingExpressionGrammars, jak w OMetaLanguage i LuaLanguage ( http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html )
  • Tryb analizy RebolLanguage
  • Analiza prawdopodobieństwa na podstawie ...
Nick P.
źródło
czy mógłbyś wyjaśnić więcej o tym, co robi ten link i do czego służy? „Tylko odpowiedzi” nie są mile widziane na Stack Exchange
gnat
1
Witamy w Programistach, Nick P. Proszę zignorować downvote / r, ale proszę przeczytać stronę na meta, do której link @gnat.
Christoffer Lette,
@ Christoffer Lette Doceń swoją odpowiedź. Postaram się o tym pamiętać w przyszłych wpisach. @ gnat Komentarz Paulo Scardine odzwierciedla zamiary moich postów. Gramatyki BNF, EBNF itp. Mogą być znacznie łatwiejsze do odczytania i wykonania niż skomplikowane wyrażenie regularne. ZŁOTO to jedno narzędzie do takich rzeczy. Łącze C2 zawiera listę możliwych alternatyw, które można przejrzeć w Google, wraz z omówieniem niektórych z nich. Był to w zasadzie link „patrz także”, aby uzupełnić moją rekomendację silnika gramatycznego.
Nick P
6

To stare pytanie i nie widziałem żadnej wzmianki o wyrażeniach werbalnych, więc pomyślałem, że dodam tę informację również dla przyszłych poszukiwaczy. Wyrażenia słowne zostały zaprojektowane tak, aby wyrażenia regularne były zrozumiałe dla człowieka, bez konieczności uczenia się znaczenia wyrażeń regularnych. Zobacz następujący przykład. Myślę, że to najlepiej spełnia twoje oczekiwania.

// Create an example of how to test for correctly formed URLs
var tester = VerEx()
    .startOfLine()
    .then('http')
    .maybe('s')
    .then('://')
    .maybe('www.')
    .anythingBut(' ')
    .endOfLine();

// Create an example URL
var testMe = 'https://www.google.com';

// Use RegExp object's native test() function
if (tester.test(testMe)) {
    alert('We have a correct URL '); // This output will fire}
} else {
    alert('The URL is incorrect');
}

console.log(tester); // Outputs the actual expression used: /^(http)(s)?(\:\/\/)(www\.)?([^\ ]*)$/

Ten przykład dotyczy javascript, teraz możesz znaleźć tę bibliotekę dla wielu języków programowania.

Parivar Saraff
źródło
2
To jest niesamowite!
Jeremy Thompson,
3

Najprostszym sposobem byłoby nadal użycie wyrażenia regularnego, ale zbudowanie wyrażenia z komponowania prostszych wyrażeń o nazwach opisowych, np. Http://www.martinfowler.com/bliki/ComposedRegex.html (i tak, to z konkatku ciągów)

jednak alternatywnie można również użyć biblioteki kombinatora parserów, np. http://jparsec.codehaus.org/, która da ci pełny rekurencyjny porządny parser. znowu prawdziwa moc pochodzi z kompozycji (tym razem kompozycji funkcjonalnej).

jk.
źródło
3

Pomyślałem, że warto wspomnieć logstash za Grok wyrażeń. Grok opiera się na idei komponowania długich parsowania wyrażeń z krótszych. Umożliwia wygodne testowanie tych elementów składowych i jest dostarczany w paczce z ponad 100 często używanymi wzorami . Poza tymi wzorami pozwala na stosowanie wszystkich składni wyrażeń regularnych.

Powyższy wzór wyrażony w grok to (przetestowałem w aplikacji do debugowania, ale mogłem się pomylić):

"(( *%{NUMBER:a} *:)? *%{NUMBER:b} *:)? *%{NUMBER:c} *(. *%{NUMBER:d} *)?"

Opcjonalne części i spacje sprawiają, że wydaje się to trochę brzydsze niż zwykle, ale zarówno tutaj, jak iw innych przypadkach, użycie grok może uczynić twoje życie o wiele przyjemniejszym.

yoniLavi
źródło
2

W F # masz moduł FsVerbalExpressions . Pozwala komponować Regeksy z wyrażeń werbalnych, ma też kilka gotowych wyrażeń regularnych (takich jak URL).

Jednym z przykładów tej składni jest:

let groupName =  "GroupNumber"

VerbEx()
|> add "COD"
|> beginCaptureNamed groupName
|> any "0-9"
|> repeatPrevious 3
|> endCapture
|> then' "END"
|> capture "COD123END" groupName
|> printfn "%s"

// 123

Jeśli nie znasz składni F #, groupName jest łańcuchem „GroupNumber”.

Następnie tworzą wyrażenie słowne (VerbEx), które konstruują jako „COD (? <GroupNumber> [0-9] {3}) END”. Które następnie testują na łańcuchu „COD123END”, skąd otrzymują nazwaną grupę przechwytywania „GroupNumber”. Daje to 123.

Naprawdę uważam, że normalne wyrażenie regularne jest znacznie łatwiejsze do zrozumienia.

CodeMonkey
źródło
-2

Po pierwsze, zrozum, że kod, który po prostu działa, jest złym kodem. Dobry kod musi również dokładnie zgłaszać wszelkie napotkane błędy.

Na przykład, jeśli piszesz funkcję przesyłania gotówki z konta jednego użytkownika na konto innego użytkownika; nie zwróciłbyś po prostu logicznego „działającego lub nieudanego”, ponieważ to nie daje dzwoniącemu żadnego pojęcia o tym, co poszło źle i nie pozwala dzwoniącemu na prawidłowe poinformowanie użytkownika. Zamiast tego możesz mieć zestaw kodów błędów (lub zestaw wyjątków): nie można znaleźć konta docelowego, niewystarczające środki na koncie źródłowym, odmowa dostępu, nie można połączyć się z bazą danych, zbyt duże obciążenie (spróbuj ponownie później) itp. .

Pomyśl teraz o przykładzie „parsuj ciąg liczb w formacie 1: 2: 3.4”. Wyrażenie regularne to tylko raport „pozytywny / negatywny”, który nie pozwala użytkownikowi na przedstawienie odpowiedniej informacji zwrotnej (niezależnie od tego, czy ta informacja zwrotna jest komunikatem o błędzie w dzienniku, czy interaktywnym interfejsem GUI, w którym błędy są wyświetlane na czerwono jako typy użytkowników lub cokolwiek innego). Jakie rodzaje błędów nie można poprawnie opisać? Zły znak w pierwszej liczbie, pierwsza liczba za duża, brak dwukropka po pierwszej liczbie itp.

Aby przekonwertować „zły kod, który po prostu działa” na „dobry kod, który zapewnia odpowiednio błędy opisowe”, musisz podzielić regex na wiele mniejszych wyrażeń regularnych (zazwyczaj wyrażenia regularne, które są tak małe, że łatwiej jest to zrobić bez wyrażeń regularnych ).

Uczynienie kodu możliwym do odczytania / utrzymania jest tylko przypadkową konsekwencją poprawienia kodu.

Brendan
źródło
6
Prawdopodobnie nie jest to dobre założenie. Mój jest, ponieważ A) To nie dotyczy pytania ( Jak uczynić go czytelnym?), B) Dopasowywanie wyrażeń regularnych to pass / fail, a jeśli podzielisz je do punktu, w którym możesz powiedzieć dokładnie, dlaczego się nie udało, stracić dużo mocy i prędkości oraz zwiększyć złożoność, C) Pytanie nie wskazuje na to, że istnieje nawet możliwość niepowodzenia meczu - to po prostu pytanie o to, czy Regex będzie czytelny. Gdy masz kontrolę nad wprowadzanymi danymi i / lub sprawdzasz je wcześniej, możesz założyć, że są one prawidłowe.
Bobson,
A) Rozbicie go na mniejsze części sprawia, że ​​jest bardziej czytelne (w wyniku ulepszenia). C) W przypadku gdy nieznane / nieważne ciągi wchodzą do oprogramowania, rozsądny programista analizuje w tym momencie (z raportowaniem błędów) i konwertuje dane do postaci, która nie wymaga ponownej analizy - po tym wyrażeniu regularnym nie trzeba. B) to nonsens, który dotyczy tylko złego kodu (patrz punkty A i C).
Brendan,
Przechodząc od twojego C: Co jeśli to jest jego logika walidacji? Kod OP może być dokładnie tym, co sugerujesz - sprawdzaniem poprawności danych wejściowych, zgłaszaniem, czy nie jest poprawne, i przekształcaniem go w użyteczną formę (poprzez przechwytywanie). Wszystko, co mamy, to samo wyrażenie. Jak sugerowałbyś parsowanie go inaczej niż za pomocą wyrażenia regularnego? Jeśli dodasz przykładowy kod, który osiągnie ten sam wynik, usunę moją opinię.
Bobson
Jeśli jest to „C: Sprawdzanie poprawności (z raportowaniem błędów)”, to jest to zły kod, ponieważ raportowanie błędów jest złe. Jeśli się nie powiedzie; czy to dlatego, że ciąg miał wartość NULL, czy dlatego, że pierwszy numer zawierał zbyt wiele cyfr, czy też dlatego, że pierwszy separator nie był :? Wyobraź sobie kompilator, który miał tylko jeden komunikat o błędzie („BŁĄD”), który był zbyt głupi, aby powiedzieć użytkownikowi, na czym polega problem. Teraz wyobraź sobie tysiące stron internetowych, które są tak samo głupie i wyświetlają (np.) „Zły adres e-mail” i nic więcej.
Brendan
Wyobraź sobie również, że na wpół wyszkolony operator działu pomocy technicznej otrzymuje raport o błędzie od całkowicie nieprzeszkolonego użytkownika, który mówi: Oprogramowanie przestało działać - ostatni wiersz w dzienniku oprogramowania to „BŁĄD: Nie udało się wyodrębnić mniejszego numeru wersji z łańcucha wersji 1: 2-3.4 „(spodziewany dwukropek po drugim numerze)”
Brendan