Odgórny to świetny sposób na opisanie rzeczy, które znasz, lub na odbudowanie rzeczy, które już zbudowałeś.
Największym problemem odgórnym jest to, że dość często po prostu nie ma „góry”. Zmienisz zdanie na temat tego, co powinien zrobić system podczas opracowywania systemu i eksploracji domeny. Jak może być punktem wyjścia coś, czego nie wiesz (tj. Co chcesz, aby system zrobił)?
„Lokalny” z góry na dół jest dobrą rzeczą… pewne myślenie przed kodowaniem jest wyraźnie dobre. Ale zbyt dużo myślenia i planowania nie jest, ponieważ to, co sobie wyobrażasz, nie jest prawdziwym scenariuszem (chyba że już tam byłeś, tj. Jeśli nie budujesz, ale odbudowujesz). Globalne odgórne tworzenie nowych rzeczy to tylko nonsens.
Podejście oddolne powinno być (globalne) podejściem, chyba że znasz 100% problemu, potrzebujesz tylko znanego rozwiązania do zakodowania i nie przejmujesz się szukaniem możliwych alternatywnych rozwiązań.
Podejście Lisp to destylowane podejście oddolne. Nie tylko budujesz oddolnie, ale możesz również kształtować cegły tak, jak chcesz. Nic nie jest ustalone, wolność jest całkowita. Oczywiście wolność bierze odpowiedzialność i możesz robić okropne rzeczy, niewłaściwie wykorzystując tę moc.
Ale okropny kod można napisać w dowolnym języku. Nawet w językach, które są ukształtowane jako klatki dla umysłu, zaprojektowane z nadzieją, że dzięki tym językom nawet małpy mogłyby uruchomić dobre programy (pomysł tak błędny na tak wielu poziomach, że boli nawet samo myślenie o tym).
Twój przykład dotyczy serwera WWW. Teraz w 2012 r. Jest to dobrze zdefiniowany problem, musisz przestrzegać specyfikacji. Serwer WWW to tylko problem z implementacją. Zwłaszcza jeśli zamierzasz napisać serwer WWW zasadniczo identyczny z innymi gajillionami serwerów WWW, które tam są, nic nie jest tak naprawdę niejasne, z wyjątkiem kilku drobiazgów. Nawet twój komentarz na temat RSA wciąż mówi o jasno zdefiniowanym problemie, z formalnymi specyfikacjami.
Przy dobrze zdefiniowanym problemie, formalnych specyfikacjach i znanych już rozwiązaniach, kodowanie łączy się w kropki. Z góry na dół jest w porządku. To raj dla kierowników projektów.
W wielu przypadkach nie ma jednak sprawdzonego, dobrze znanego podejścia do łączenia kropek. W rzeczywistości bardzo często trudno powiedzieć nawet, jakie są kropki.
Załóżmy na przykład, że poprosiłeś automatyczną maszynę do cięcia, aby wyrównała cięte części do drukowanego materiału, który nie jest idealnie zgodny z teoretycznym powtarzalnym logo. Dostajesz części i zdjęcia materiału wykonane przez maszynę.
Co to jest reguła wyrównania? Ty decydujesz. Co to jest wzór, jak go przedstawić? Ty decydujesz. Jak wyrównać części? Ty decydujesz. Czy części można „wygiąć”? To zależy, niektóre nie, a niektóre tak, ale oczywiście nie za dużo. Co zrobić, jeśli materiał jest zbyt zniekształcony, aby część mogła go przeciąć w odpowiedni sposób? Ty decydujesz. Czy wszystkie rolki materiału są identyczne? Oczywiście, że nie, ale nie możesz zaszkodzić użytkownikowi w dostosowaniu reguł wyrównania dla każdego rzutu ... byłoby to niepraktyczne. Jakie zdjęcia widzą kamery? Materiał, cokolwiek to może znaczyć ... może być kolorowy, może być czarny na czarnym, gdzie tylko odruch światła sprawia, że wzór jest widoczny. Co to znaczy rozpoznać wzór? Ty decydujesz.
Teraz spróbuj zaprojektować ogólną strukturę rozwiązania tego problemu i podaj ofertę cenową i czasową. Założę się, że nawet architektura systemu ... (tak, architektura) będzie błędna. Szacunkowe koszty i czas będą liczbami losowymi.
Wdrożyliśmy go i teraz jest to działający system, ale wiele razy zmienialiśmy zdanie na temat samego kształtu systemu. Dodaliśmy całe podsystemy, do których teraz nie można nawet dotrzeć z menu. Wielokrotnie przełączaliśmy role master / slave w protokołach. Prawdopodobnie teraz mamy wystarczającą wiedzę, aby lepiej ją odbudować.
Inne firmy oczywiście rozwiązały ten sam problem ... ale chyba, że jesteś w jednej z tych firm, najprawdopodobniej twój szczegółowy projekt z góry na dół będzie żartem. Możemy zaprojektować go z góry na dół. Nie możesz, ponieważ nigdy wcześniej tego nie robiłeś.
Prawdopodobnie możesz rozwiązać ten sam problem. Działa jednak oddolnie. Zaczynając od tego, co wiesz, ucząc się tego, czego nie wiesz i sumując.
Nowe złożone systemy oprogramowania są rozwijane, a nie projektowane. Od czasu do czasu ktoś zaczyna projektować od nowa duży, złożony, źle określony system oprogramowania (zauważ, że przy dużym złożonym projekcie oprogramowania istnieją tylko trzy możliwości: a] specyfikacja jest rozmyta, b] specyfikacja jest błędna i sprzeczna lub c] zarówno… jak i najczęściej [c] ma miejsce).
Są to typowe projekty dużych firm, w których tysiące godzin wrzucono w same slajdy PowerPoint i same diagramy UML. Niezmiennie zawodzą całkowicie po spaleniu zawstydzających ilości zasobów ... lub w bardzo wyjątkowym przypadku w końcu dostarczają drogiego oprogramowania, które implementuje tylko niewielką część początkowej specyfikacji. I to oprogramowanie jest zawsze głęboko nienawidzone przez użytkowników ... nie tego rodzaju oprogramowania, które kupiłbyś, ale takiego oprogramowania, którego używasz, ponieważ jesteś do tego zmuszony.
Czy to oznacza, że uważam, że powinieneś myśleć tylko o kodowaniu? Oczywiście nie. Ale moim zdaniem konstrukcja powinna zaczynać się od dołu (cegły, konkretny kod) i powinna iść w górę ... a twoje skupienie i dbałość o szczegóły powinny w pewnym sensie „zanikać” w miarę zbliżania się do tego, co masz. Odgórne przedstawienie jest często przedstawiane tak, jakbyś chciał wprowadzić ten sam poziom szczegółowości do całego systemu naraz: po prostu dziel go na wszystkie węzły, aż wszystko stanie się oczywiste ... w rzeczywistości moduły podsystemu są „hodowane” z podprogramów. Jeśli nie masz wcześniejszego doświadczenia w konkretnym problemie, projektowanie odgórnego podsystemu, modułu lub biblioteki będzie straszne. Po zaprojektowaniu dobrej biblioteki możesz zaprojektować dobrą bibliotekę, a nie na odwrót.
Wiele pomysłów Lisp zyskuje na popularności (funkcje pierwszej klasy, zamykanie, dynamiczne pisanie jako domyślne, wyrzucanie elementów bezużytecznych, metaprogramowanie, interaktywne programowanie), ale Lisp jest nadal (wśród znanych mi języków) dość wyjątkowy pod względem łatwości kształtowania kodu za to, czego potrzebujesz.
Na przykład parametry słowa kluczowego są już obecne, ale jeśli nie byłyby obecne, można je dodać. Zrobiłem to (w tym weryfikację słów kluczowych w czasie kompilacji) dla zabawkowego kompilatora Lisp, z którym eksperymentuję i nie wymaga to dużo kodu.
Zamiast tego w C ++ najwięcej możesz uzyskać od ekspertów C ++, którzy mówią ci, że parametry słów kluczowych nie są tak przydatne, lub niesamowicie złożoną, zepsutą implementację szablonów w połowie wspieraną, która tak naprawdę nie jest tak przydatna. Czy klasy C ++ są pierwszorzędnymi obiektami? Nie i nic nie możesz na to poradzić. Czy możesz mieć introspekcję w czasie wykonywania lub w czasie kompilacji? Nie i nic nie możesz na to poradzić.
Ta elastyczność językowa Lisp sprawia, że świetnie nadaje się do budowania oddolnego. Możesz budować nie tylko podprogramy, ale także składnię i semantykę języka. I w pewnym sensie sama Lisp jest oddolna.