Czy „konwencja w sprawie konfiguracji” nie narusza podstawowych zasad programowania?

51

Patrzyłem na platformę WPF MVVM Caliburn.Micro i czytałem, że wiele standardowych rzeczy opiera się na konwencjach nazewnictwa .

Na przykład automatyczne wiązanie właściwości w widoku z właściwościami w ViewModel. Chociaż wydaje się to być wygodne (usuwa część kodu typu „kocioł”), moją pierwszą instynktowną reakcją jest to, że nie jest zupełnie oczywiste dla nowego programisty, który przeczyta ten kod. Innymi słowy, funkcjonalność aplikacji nie jest całkowicie wyjaśniona własnym kodem, ale także dokumentacją frameworka.

EDYTOWAĆ:

To podejście nazywa się konwencją nad konfiguracją. Ponieważ nie mogłem znaleźć żadnych pytań na ten temat, zmieniłem swoje pytanie:

Moje pytanie brzmi:

Czy konwencja dotycząca konfiguracji to właściwy sposób uproszczenia, czy też narusza niektóre zasady programowania (a jeśli tak, to które)?

Geerten
źródło
8
Większość podejść / zasad do pewnego stopnia narusza niektóre inne podejścia / zasady. Jest to głównie kwestia priorytetów i kompromisów.
Joachim Sauer
1
To prawda, ale uważam różnicę podaną w moim pytaniu za nieco dziwną, dlatego jestem zainteresowany konkretnymi kompromisami i być może naruszonymi zasadami przy stosowaniu konwencji nad konfiguracją.
Geerten
Istotna jest tutaj koncepcja identyfikowalności oprogramowania. Programiści polegają na narzędziach takich jak grep, ale potrzebują lepszych narzędzi do śledzenia wykorzystania wygenerowanego kodu. Na przykład narzędzia powinny wyraźniej zaznaczyć, że klasa css „identyfikator użytkownika” jest powiązana z wygenerowaną metodą getUserId () i kolumną tabeli user_id.
Macneil

Odpowiedzi:

49

Nie uważam, że „aplikacja powinna być w pełni wyjaśniona własnym kodem”, jest podstawową zasadą programowania. Istnieje wiele rzeczy, których nie wyjaśniono po prostu patrząc na kod aplikacji. Oprócz znajomości podstawowych elementów samego języka programowania (składnia i semantyka), musisz znać konwencje. Jeśli identyfikator w Javie zaczyna się od dużej litery, jest to typ. Jest wiele takich konwencji, które musisz znać.

Konwencja dotycząca konfiguracji polega na zmniejszeniu liczby decyzji podejmowanych przez programistę. W przypadku niektórych rzeczy jest to oczywiste - nikt nie pomyślałby o posiadaniu języka, w którym wielkie litery typów należy zadeklarować na początku programu - ale w przypadku innych rzeczy nie jest to takie oczywiste.

Równoważenie konwencji i konfiguracji jest trudnym zadaniem. Zbyt duża konwencja może powodować, że kod jest mylący (na przykład zmienne niejawne Perla). Zbyt duża swoboda po stronie programisty może utrudniać zrozumienie systemów, ponieważ wiedza uzyskana z jednego systemu rzadko jest przydatna podczas studiowania innego.

Dobrym przykładem tego, gdzie konwencja pomaga programiście, jest pisanie wtyczek Eclipse. Patrząc na wtyczkę, której nigdy nie widziałem, od razu wiem o niej wiele. Lista zależności znajduje się w pliku MANIFEST.MF, punkty rozszerzenia znajdują się w plugin.xml, kod źródłowy znajduje się pod „src” i tak dalej. Gdyby te rzeczy zostały zdefiniowane przez programistę, każda wtyczka Eclipse byłaby inna, a nawigacja kodu byłaby znacznie trudniejsza.

JesperE
źródło
4
+1: tworzenie oprogramowania jest wystarczająco skomplikowane. Jeśli możesz uniknąć złożoności spraw, nad którymi masz kontrolę, zrób to. Oszczędzaj złożoność miejsc, które są absolutnie potrzebne.
scrwtp
1
Dzięki za jasne wyjaśnienie różnicy i równowagi.
Geerten,
3
„Jeśli identyfikator w Javie zaczyna się od dużej litery, jest to typ.” - czy jest to typ zależy od kontekstu składni, a nie od wzorca nazewnictwa, konwencje nazewnictwa Java nie wpływają na „konfigurację kompilacji”. Czy na pewno jest to prawidłowy przykład? Ostatni przykład również nie jest poprawny - dotyczy „konwencji konfiguracji”, a nie „konwencji konfiguracji”. Mówisz właściwe rzeczy, ale mają one niewiele wspólnego z zasadą poddania.
Den
4
Nie przesadzaj z analizą przykładów, są to tylko przykłady. Pierwszy to tylko przykład konwencji, ostatni to przykład, w którym konwencja jest dobra. Przykład Perla to przykład, w którym zbyt wiele konwencji (implikacji) jest złą rzeczą (należy dodać IMO).
JesperE
1
Nienawidzę tego, że konwencja nad konfiguracją staje się konwencją bez konfiguracji ... w tym drugim przypadku masz tendencję do uwięzienia w bazie kodu, może być trudno zintegrować się z innymi narzędziami.
Andy,
77

Daj +1 do @JesperE i lubię coś dodać:

czy to narusza niektóre zasady programowania

Tak, „konwencja konfiguracji” narusza zasadę „jawne jest lepsze niż niejawne” (patrz na przykład „Zen-Of-Python” ).

Z drugiej strony, przeciwna „konfiguracja ponad konwencją” narusza „Prosta jest lepsza niż złożona”, a co gorsza, narusza zasadę OSUSZANIA w subtelny sposób, ponieważ trzeba powtarzać nazwy używane w kodzie również w konfiguracji .

Doktor Brown
źródło
4
To najbardziej bezpośrednia odpowiedź na pytanie!
Joachim Sauer
To jest prawdziwa poprawna odpowiedź wśród dwóch najbardziej uprzywilejowanych.
Den
+1 za „wyraźne jest lepsze niż niejawne”
Justin Ohms
12
Moją ulubioną częścią tej odpowiedzi jest to, że pośrednio podkreśla rzeczywistość, niż zasady dobrego tworzenia oprogramowania często pozostają ze sobą w napięciu. Inżynieria polega na równoważeniu napięć odpowiednio do konkretnego kontekstu i zastosowania.
Chris Krycho
Dobra odpowiedź. Aby rozwinąć komentarz @Chris Krycho, miłą cechą standardów lub zasad oprogramowania jest to, że masz tak wiele do wyboru. :-)
user949300,
9

Niektóre „konwencje dotyczące konfiguracji” sprowadzają się do rozsądnych wartości domyślnych. Musisz tylko skonfigurować coś, aby użyć go do niestandardowego celu. Muszę porównać Struts do Rails tutaj. W Railsach musisz umieścić swoje „akcje / ekrany” w folderze, a potem one po prostu działają. W Struts nadal musisz umieścić je w folderze, ale musisz także wymyślić nazwę akcji ORAZ plik JSP ORAZ nazwę formularza ORAZ fasolkę formularza ORAZ określić, jak te trzy rzeczy działają razem w Struts-config. xml ORAZ określ, że formularz należy do żądania (RESTful). Jeśli to nie wystarczy, mapowanie form / form-bean ma własną sekcję w Struts-config, która jest następnie mapowana niezależnie na sekcję akcji w tym samym pliku i wszystko opiera się na ręcznie napisanych ciągach w pliku JSP, aby działać prawidłowo. Dla każdego ekranu to co najmniej 6 rzeczy, których nie powinieneś robić i tyle okazji do popełnienia błędu. Myślę, że możesz ustawić większość lub wszystkie te rzeczy ręcznie w Railsach, jeśli potrzebujesz, ale 2/3 czasu rozwoju Struts zajmuje budowanie i utrzymywanie niepotrzebnych warstw złożoności.

Szczerze mówiąc, Struts 1 został zaprojektowany, gdy ludzie przenosili aplikacje między komputerem a Internetem. Elastyczność, którą wyposażył Struts, sprawia, że ​​nadaje się do wszystkiego, co robi Rails, a także do wszystkiego, czego potrzebuje aplikacja komputerowa. Niestety górą konfiguracji, która umożliwia tę elastyczność, jest ogromna kula i łańcuch dla kogoś, kto musi tylko napisać aplikację internetową lub tylko aplikację komputerową.

Pracowałem gdzieś, że zrobili następny krok i argumentowali: „Konfiguracja nad kodem ”, ale widząc, że doprowadzono to do jego logicznej skrajności, wynik jest taki, że konfiguracja staje się nowym językiem kodowania. Była to gra typu shell, w której złożoność była przenoszona bez oswajania w jakikolwiek znaczący sposób. Dzięki temu doceniłem wszystkie sprawdzanie typu i inne sieci bezpieczeństwa, które ma dobrze zaprojektowany język programowania. Niektóre na wpół upakowane formaty plików konfiguracyjnych, które wybuchają bez komunikatu o błędzie, jeśli dodasz spację lub apostrof, NIE są ulepszeniem w stosunku do wysokiej jakości języka programowania, który zawiera zestawy narzędzi do edycji i kompilator jakości.

Nie wyobrażam sobie, aby rozsądne wartości domyślne naruszały jakiekolwiek teoretyczne zasady dotyczące rozszerzalności i modułowości. Programista Ruby / Rails prędzej uderzyłby ich gorącym pokerem w oko, niż przestawiłby się na framework taki jak Struts 1, w którym wszystkie konfiguracje są jawnie tworzone w wielu plikach XML. Nie spieram się ogólnie o Rails vs. Struts, ale ta konwencja może być ogromną wygraną w wydajności. Te dwie technologie są najbardziej ekstremalnym porównaniem w świecie rzeczywistym, z jakim się spotkałem.

Jeśli w ogóle pracujesz w Javie, sprawdź Joshua Blocha, „Efektywna Java”, pozycja 2: „Rozważ konstruktora w obliczu wielu parametrów konstruktora”, str. 11-16. Do większości celów niektóre parametry (konfiguracja) są wymagane, a niektóre są opcjonalne. Podstawową ideą jest wymaganie tylko niezbędnej konfiguracji i tylko spowodowanie, aby użytkownik (którym może być inny program) określił dodatkowe opcje w razie potrzeby. Miesiąc temu wyczyściłem sporo kodu z tym wzorem i pozytywnie błyszczy.

GlenPeterson
źródło
7

Innymi słowy, funkcjonalność aplikacji nie jest całkowicie wyjaśniona własnym kodem, ale także dokumentacją frameworka.

Funkcjonalność aplikacji używającej frameworka jest zawsze zależna od frameworka, konwencja dotycząca konfiguracji nie ma znaczenia w tym względzie.

Z mojego doświadczenia wynika, że ​​konwencja konfiguracji nie tylko czyni kod bardziej czytelnym, ale także zmniejsza możliwość wprowadzania subtelnych błędów (szczególnie błędów kopiowania-wklejania).

Załóżmy na przykład, że w niektórych ramach A zdarzenie FooBarwywołuje wywołanie handleFooBar. W innej strukturze B korelacja ta jest skonfigurowana gdzieś w pliku XML.

A więc w A jest po prostu

handleFooBar() {
   ...
}

i chyba że masz błędnie napisane FooBar, będzie ono wywoływane za każdym razem, gdy FooBar się wydarzy.

W B jest znowu

handleFooBar() {
   ...
}

ale również

<eventconfiguration>
  <event>
    <type>FooBar</type>
    <handler>handleFooBar</handler>
  </event>
</eventconfiguration>

Przy setkach rzeczy do skonfigurowania w ten sposób, zbyt łatwo jest przypadkowo stworzyć subtelny błąd

<eventconfiguration>
  <event>
    <type>BarFoo</type>
    <handler>handleFooBar</handler>
  </event>
</eventconfiguration>

ponieważ po wklejeniu kopii zmieniliśmy się tylko, <type>ale zapomnieliśmy zmienić <handler>.

Ponieważ te pliki konfiguracyjne są duże i monotonne, jest mniej prawdopodobne, że ktoś znajdzie błąd przez korektę, niż znalazłby podobny błąd w rzeczywistym kodzie programu.

użytkownik 281377
źródło
1
+1: unikanie powtarzalne, nudne do zapisu, trudnych do odczytania, niemal zawsze oczywisty konfiguracji jest Główną zaletą konferencyjnym-over-konfiguracji.
Joachim Sauer
-1

Może to naruszać kilka zasad, ale jednocześnie przestrzega jednej z najbardziej podstawowych zasad projektowania, SRP (zasada pojedynczej odpowiedzialności).

rai.skumar
źródło
2
Stosowanie konwencji nie ma nic wspólnego z pojedynczą odpowiedzialnością. Mógłbym używać konwencji i robić w niej 100 rzeczy.
Suamere