Ostatnio próbuję ogarnąć następujący fakt.
Z jednej strony istnieje szereg wytycznych i standardów kodowania dla tego, co jest uważane za „zdrowe”, „czyste”, „dobrze napisane” i tak dalej. Zobacz też „Czysty kod”, który wydaje się być tutaj szeroko omawiany. Przykładowa reguła: metody o długości 7 linii i 1 lub 2 poziomy wcięcia. Oczekuje się, że kod, który nie następuje, umrze z powodu złej konserwacji.
Z drugiej strony, mogę pracować z OpenCV, OpenCascade, VTK itp. To jest kod naukowy. Mają 2-stronicowe metody (sen ja), OpenCascade ma metodę lub klasę podzieloną na 10 plików (tutaj nie ma żartów), VTK też jest czasem bałagan. Jednak projekty te rozwijają się, są utrzymywane i szeroko stosowane!
Gdzie jest haczyk? Czy wolno nam pisać naukowy, wymagający matematyki kod, który po prostu działa i możemy go utrzymać? Czy jesteś oddzielnym zestawem standardów dla takich projektów, jeśli takie istnieją?
Może to być naiwne pytanie, ale jestem w czymś, co wydaje się pustką programistyczną, próbując stworzyć zestaw zasad, jak robić i nie robić rzeczy, w taki sposób nauczono mnie pracy w szkole średniej. Odkąd ukończyłem szkołę, nie miałem prawie żadnych wytycznych w zakresie rzeczy, które musiałem robić, głównie programowania - nikt nie zawracał sobie głowy nauczaniem tego.
źródło
Odpowiedzi:
Nie, nie jest.
Kod badawczy jest często „wyrzucany” i zapisywany przez osoby, które nie są programistami ze względu na pochodzenie, bez względu na swoje kwalifikacje akademickie. Część kodu, który napisałem, sprawiłaby, że płaczę . Ale zadziałało!
Jedną rzeczą do rozważenia jest to, że strażnicy projektów kierują tym, co zostaje uwzględnione. Jeśli duży projekt rozpoczął się jako projekt kodu akademickiego / badawczego, kończy się działaniem, a teraz jest bałaganem, ktoś musi podjąć inicjatywę, aby go przeredagować.
Zmodyfikowanie istniejącego kodu, który nie powoduje problemów, zajmuje dużo pracy. Zwłaszcza jeśli jest w ogóle specyficzny dla domeny lub nie ma testów. Zobaczysz, że OpenCV ma przewodnik po stylach, który jest bardzo obszerny, nawet jeśli nie idealny. Stosujesz to z mocą wsteczną do całego istniejącego kodu? To znaczy ... nie dla osób o słabym sercu.
Jest to jeszcze trudniejsze, jeśli cały ten kod działa. Ponieważ to nie jest zepsute. Po co to naprawiać?
W pewnym sensie jest to odpowiedź. Działający kod jest nadal użyteczny i dlatego jest bardziej prawdopodobne, że zostanie utrzymany.
Może to być bałagan, szczególnie na początku. Niektóre z tych projektów prawdopodobnie rozpoczęły się jako projekt jednorazowy, który „nie wymagałby ponownego wykorzystania i mógłby zostać wyrzucony”.
Weź również pod uwagę, że jeśli wdrażasz złożony algorytm, sensowniejsze może być posiadanie większych metod, ponieważ ty (i inni znający stronę naukową) lepiej rozumiesz algorytm. Moja praca dyplomowa dotyczyła optymalizacji. Posiadanie głównej logiki algorytmu jako jednej metody było znacznie łatwiejsze do zrozumienia, niż próbowałoby to rozdzielić. Z pewnością naruszyło zasadę „7 wierszy na metodę”, ale oznaczało również, że inny badacz mógł spojrzeć na mój kod i szybciej zrozumieć moje modyfikacje algorytmu.
Gdyby to wdrożenie zostało wyabstrahowane i dobrze zaprojektowane, ta przejrzystość zostałaby utracona dla programistów .
Myślę, że ludzie często mają taki pomysł, że wszystkie projekty open source zaczynają się od „hej, mam świetny pomysł na bibliotekę, która będzie bardzo popularna i używana przez tysiące / miliony innych”, a potem każdy projekt tak się dzieje.
Rzeczywistość polega na tym, że wiele projektów jest uruchamianych i ginie. Śmiesznie niewielki odsetek projektów „dociera” do poziomu OpenCV lub VTK itp.
OpenCV powstał jako projekt badawczy firmy Intel. Wikipedia opisuje to jako część „serii projektów”. Jego pierwsza wersja niebędąca wersją beta miała miejsce w 2006 roku, czyli siedem lat po jej uruchomieniu. Podejrzewam, że początkowo celem były znaczące wersje beta, a nie idealny kod.
Ponadto „własność” OpenCV uległa znacznej zmianie. To powoduje zmianę standardów, chyba że wszystkie odpowiedzialne strony przyjmą dokładnie te same normy i zachowają je przez czas trwania projektu.
Powinienem również zauważyć, że OpenCV istniał przez kilka lat, zanim opublikowano Manifest Agile, z którego czerpie inspirację Clean Code (a VTK prawie 10). VTK został uruchomiony 17 lat przed opublikowaniem Clean Code (OpenCV był „tylko” 9 lat wcześniej).
źródło
Naukowcy nie są programistami. Ich zadaniem nie jest pisanie kodu per se. Ich zadaniem jest rozwiązywanie problemów, a programowanie jest tylko jednym z narzędzi, z których mogą korzystać.
Większość kodu napisanego przez - jak by to nazwali - profesjonalnych programistów to bałagan. Większość tego kodu nie używa wzorców projektowych ani ich nie używa. Większość komentarzy to kandydaci do TheDailyWTF . Ponieważ w naszej branży widzimy takie wyniki od osób, których praca polega na pisaniu kodu, czego można oczekiwać od osób, których zadaniem nie jest pisanie programów?
Czy wszystkie praktyki, których rzeczywisty profesjonalny programista uczy się podczas swojej kariery, przyniosłyby korzyści naukowcom? Absolutnie. Czy każdy naukowiec mógłby spędzić pięć do dziesięciu lat swojego życia na tworzeniu oprogramowania? Prawdopodobnie nie. Dlatego jakość kodu jest taka, jaka jest.
Kolejnym czynnikiem jest kultura. Jeśli twoje pary nie piszą czystego kodu, dlaczego miałbyś? Ponieważ nikogo to nie obchodzi, tak naprawdę nie masz ochoty na dodatkowy wysiłek.
Wreszcie, większość kodu naukowego ma stosunkowo krótką żywotność. Piszecie kod dla konkretnego badania, a kiedy badanie zostanie zakończone, nie będziecie go ponownie wykorzystywać. Kiedy masz już ten nawyk, trudno jest odróżnić biblioteki wielokrotnego użytku, takie jak te, które przytaczasz, i kod wyrzucający.
źródło
Ignorować? Nie. Ponownie rozważyć i dostosować? Pewnie. Wiele kodu naukowego wymaga intensywnej matematyki i ma kluczowe znaczenie dla wydajności. Rzeczy takie jak narzut wywołania funkcji mogą w rzeczywistości stać się problemem, więc możesz skończyć z głębiej zagnieżdżonymi strukturami niż w typowej aplikacji komercyjnej. To nie znaczy, że powinieneś najpierw zanurzyć się w tysiąc mikrooptymalizacji. Nadal powinieneś skupić się na wyborze odpowiedniego algorytmu i dokonywać tylko optymalizacji, których efekt można zmierzyć.
Niektóre różnice są oczywiste i trywialne. Wytyczne kodowania zazwyczaj wymagają wybrania znaczących nazw zmiennych, a nazwy jednoliterowe będą natychmiast podejrzane. Aplikacja naukowa nadal będzie chciała znaczących nazw zmiennych, ale czasami najbardziej znaczącą nazwą będzie pojedyncza litera, odnosząca się do zmiennej w dobrze znanym równaniu.
źródło
Aj
i,T0
ponieważ w taki sposób nazwy zmiennych były nazywane w funkcjach, które tłumaczyłem na kod. Używanie czegoś takiegocorrelationIndex
lubstartTime
narzekałoby.Wszystkie istniejące odpowiedzi kompleksowo obejmowały to pytanie. Chciałbym jednak wskazać, jaki jest prawdziwy antypód między takimi jak OpenCV itp., A na przykład kod opracowany zgodnie z dobrymi praktykami biznesowymi (Code Complete, Clean Code, SOLID itp.)
Zasadniczo kod źródłowy ma być KISS ma wiele korzyści biznesowych - „ bądź prosty, głupi”. Istnieje również powiązany YAGNI - „Nie potrzebujesz go”.
Niestety, w przypadku intensywnego obliczeniowo oprogramowania w domenach naukowych kod źródłowy rzadko jest prosty lub ubogi .
Tradycyjnie OpenCV cierpiał na brak uogólnień (wiele duplikacji kodu w celu obsługi różnych opcji), podczas gdy VTK cierpiał na nadmierne uogólnienia (szablony).
Na początku niektóre części OpenCV zostały pierwotnie opracowane w C. Później OpenCV przyjął API C ++, które znamy dzisiaj. Niektóre algorytmy zostały przepisane, aby wykorzystać interfejsy C ++ (abstrakcyjne klasy podstawowe) i szablony C ++. Inne algorytmy były po prostu opakowaniami oryginalnego kodu C. Pozostałości tego kodu można znaleźć rozrzucone w module „imgproc”.
OpenCV zawiera wiele programów SIMD (wektoryzacja). Do tej pory programowanie SIMD w C ++ nadal wymaga użycia intrinsics (intel.com) , (arm.com) .
Cechy wewnętrzne SIMD czytają jak język asemblerowy, z tym wyjątkiem, że kompilator zajmuje się przypisywaniem zmiennych do rejestru, a kompilatorowi może swobodnie zmieniać kolejność instrukcji dla zwiększenia wydajności. Algorytmy napisane w celu użycia wewnętrznych funkcji SIMD miały wysokie koszty utrzymania. Z tego powodu wspomniałem wcześniej zadane pytanie - Koszt utrzymania bazy kodu programowania SIMD .
Osoba, która nie wykonuje programowania SIMD, może łatwo przekonać się, że SIMD można elegancko obudować i że programowanie SIMD niskiego poziomu nie powinno być już konieczne. W rzeczywistości jest to dość dalekie od prawdy. Rzuciłbym każdemu wyzwanie, aby spróbował zaimplementować użyteczny algorytm w SIMD (nie fraktale) i dostrzegł trudność użycia w tych proponowanych enkapsulacjach.
Poniżej znajduje się długa lista pomysłów, gdy próbuję przeanalizować, dlaczego oprogramowanie obliczeniowe nie może być KISS lub YAGNI. Jednak wszystkie te pomysły są nadmiernymi uogólnieniami i nie wydają się potwierdzać powyższej obserwacji.
Głównymi czynnikami przyczyniającymi się są:
Niektóre z powyższych czynników są antypodami rozwoju oprogramowania biznesowego:
źródło
Zależy to od tego, co nazywacie „wspólnymi standardami kodowania”. Nie nazwałbym ekstremów Agile „wspólnymi”. W szczególności uznanie funkcji, która ma osiem linii za zbyt długą lub która ma więcej niż dwa poziomy wcięcia za zbyt skomplikowane, jest absurdalnym standardem w dziedzinie programowania numerycznego / naukowego.
Bardzo prosta funkcja macierzy razy macierzy ma więcej niż siedem linii i ma trzy poziomy wcięcia. Funkcja ta stanie się znacznie bardziej złożona niż ta, którą należy się obawiać o wydajność. Jest to tak powszechna operacja, że ważna jest wydajność. Rozbicie go na kawałki jest dokładnie tym, czego nie chcesz robić. Rozkład macierzy będzie jeszcze bardziej złożony.
źródło
Postanowiłem opublikować to jako nową odpowiedź, ponieważ jest to zupełnie inna perspektywa.
Rzućmy okiem na przykładowy kod, który uważam za „czysty kod” pod względem widzenia komputera i zrozumienia obrazu:
https://github.com/opencv/opencv/blob/05b15943d6a42c99e5f921b7dbaa8323f3c042c6/modules/photo/src/seamless_cloning_impl.cpp
Dla osób zaznajomionych z MATLAB i obliczeniami naukowymi kod w C ++ jest prawie tak zwięzły, jak najczystszy możliwy kod MATLAB.
Teraz musimy zapytać, dlaczego cała baza kodu biblioteki (w tym przykładzie OpenCV) nie jest zapisana w tym samym standardzie co przykładowy kod?
Musimy rozwarstwiać bazę kodu dużej biblioteki naukowej na poziomy abstrakcji .
Na niskim poziomie dosłownie ponownie wdrażasz dodawanie i odejmowanie. Lub dosłownie mapowanie każdej operacji na najszybsze implementacje na każdej platformie.
https://github.com/opencv/opencv/blob/master/modules/core/src/hal_replacement.hpp
Na poziomie średnim znajduje się „najbrudniejszy” kod, w którym może spędzić około 80–90% czasu wykonywania procesora. (Podobnie, może 80% - 90% nakładów programistycznych zostało wydanych na poziomie średnim, jeśli liczymy oddzielnie nakłady programistyczne od badań naukowych).
Na wysokim poziomie mamy najczystszy kod napisany przez naukowców.
Konieczna jest silna doskonałość w organizacji kodu źródłowego, aby upewnić się, że poziomy te się nie mieszają. To wykracza poza standardy kodowania , więcej ma związek z zarządzaniem open source .
Na przykład czasami podejmowana jest decyzja o podzieleniu jednego projektu typu open source na dwa. Nie możesz sprawić, by te rzeczy się wydarzyły za pomocą zatwierdzeń kodu.
źródło