Minęło kilka miesięcy, odkąd zacząłem pracę jako programista na poziomie podstawowym. Teraz, kiedy minęło już kilka krzywych uczenia się (np. Język, żargon, składnia VB i C #), zaczynam skupiać się na bardziej ezoterycznych tematach, jak pisać lepsze oprogramowanie.
Odpowiedzi na proste pytanie, które zadałem współpracownikowi, brzmiało: „Skupiam się na niewłaściwych rzeczach”. Chociaż szanuję tego współpracownika, nie zgadzam się, że jest to „niewłaściwa rzecz”, na której można się skupić.
Oto kod (w VB), a po nim pytanie.
Uwaga: Funkcja GenerateAlert () zwraca liczbę całkowitą.
Dim alertID as Integer = GenerateAlert()
_errorDictionary.Add(argErrorID, NewErrorInfo(Now(), alertID))
vs...
_errorDictionary.Add(argErrorID, New ErrorInfo(Now(), GenerateAlert()))
Pierwotnie napisałem to drugie i przepisałem go z „Dim alertID”, aby ktoś inny mógł łatwiej go odczytać. Ale oto moja troska i pytanie:
Gdyby napisać to przy pomocy Dim AlertID, faktycznie zajęłoby to więcej pamięci; skończone, ale więcej i czy tę metodę należy nazywać wiele razy, czy może to prowadzić do problemu? Jak .NET obsłuży ten obiekt AlertID. Poza platformą .NET należy ręcznie pozbyć się obiektu po użyciu (pod koniec części podrzędnej).
Chcę się upewnić, że zostanę doświadczonym programistą, który nie polega wyłącznie na wyrzucaniu elementów bezużytecznych. Czy ja o tym myślę? Czy skupiam się na niewłaściwych rzeczach?
Odpowiedzi:
„Przedwczesna optymalizacja jest źródłem wszelkiego zła (a przynajmniej większości) w programowaniu”. - Donald Knuth
Jeśli chodzi o pierwsze przejście, po prostu napisz kod, aby był poprawny i czysty. Jeśli później zostanie ustalone, że Twój kod ma krytyczne znaczenie dla wydajności (istnieją narzędzia do określania tego mianem profilerów), można go ponownie zapisać. Jeśli kod nie ma decydującego znaczenia dla wydajności, czytelność jest o wiele ważniejsza.
Czy warto zagłębić się w te tematy dotyczące wydajności i optymalizacji? Oczywiście, ale nie na dolara twojej firmy, jeśli jest to niepotrzebne.
źródło
Dla przeciętnego programu .NET tak, to jest przesadne myślenie. Może się zdarzyć, że będziesz chciał przejść do sedna tego, co dzieje się w .NET, ale jest to stosunkowo rzadkie.
Jedną z trudnych zmian, jakie miałem, było przejście z używania C i MASM na programowanie w klasycznym VB w latach 90-tych. Przyzwyczaiłem się do optymalizacji wszystkiego pod kątem wielkości i prędkości. Musiałem w większości zrezygnować z tego myślenia i pozwolić VB robić to, aby było skuteczne.
źródło
Jak mawiał mój współpracownik:
Innymi słowy, zawsze pamiętaj o KISS (niech to będzie głupie). Ponieważ nadmierna inżynieria, nadmierne myślenie pewnej logiki kodu może stanowić problem przy zmianie logiki następnym razem. Jednak utrzymywanie kodu w czystości i prostocie jest zawsze dobrą praktyką .
Jednak z czasem i doświadczeniem lepiej wiesz, który kod pachnie i wkrótce będziesz potrzebował optymalizacji.
źródło
Czytelność jest ważna. W przykładzie, choć nie jestem pewien, że jesteś naprawdę czyni rzeczy , które stają się bardziej czytelne. GenerateAlert () ma dobrą nazwę i nie powoduje dużego hałasu. Prawdopodobnie są lepsze sposoby wykorzystania twojego czasu.
Podejrzewam, że nie. Jest to stosunkowo prosta optymalizacja dla kompilatora.
Użycie zmiennej lokalnej jako pośrednika nie ma wpływu na moduł wyrzucania elementów bezużytecznych. Jeśli pamięć generowana przez GenerateAlert () new, będzie miała znaczenie. Ale to będzie miało znaczenie niezależnie od lokalnej zmiennej, czy nie.
AlertID nie jest obiektem. Wynikiem GenerateAlert () jest obiekt. AlertID to zmienna, która jeśli jest zmienną lokalną, jest po prostu przestrzenią powiązaną z metodą śledzenia rzeczy.
Jest to trudniejsze pytanie, które zależy od kontekstu i semantyki własności instancji podanej przez GenerateAlert (). Ogólnie rzecz biorąc, cokolwiek utworzyło instancję, należy ją usunąć. Twój program prawdopodobnie wyglądałby znacznie inaczej, gdyby został zaprojektowany z myślą o ręcznym zarządzaniu pamięcią.
Dobry programista wykorzystuje dostępne dla nich narzędzia, w tym śmietnik. Lepiej jest przemyśleć rzeczy, niż żyć nieświadomym. Być może skupiasz się na niewłaściwych rzeczach, ale skoro tu jesteśmy, równie dobrze możesz się o tym dowiedzieć.
źródło
Spraw, aby działał, czyść go, uczyń go SOLIDNYM, A NASTĘPNIE spraw, aby działał tak szybko, jak powinien .
To powinna być normalna kolejność rzeczy. Twoim pierwszym priorytetem jest stworzenie czegoś, co przejdzie testy akceptacyjne, które wstrząsną wymaganiami. To jest twój pierwszy priorytet, ponieważ jest to pierwszy priorytet twojego klienta; spełnianie wymagań funkcjonalnych w terminach rozwoju. Kolejnym priorytetem jest napisanie czystego, czytelnego kodu, który jest łatwy do zrozumienia, a zatem może być utrzymywany przez potomność bez żadnych WTF, gdy stanie się to konieczne (prawie nigdy nie jest to kwestia „jeśli”; ty lub ktoś po tobie będzie musiał odejść wróć i zmień / napraw coś). Trzecim priorytetem jest dostosowanie kodu do metodologii SOLID (lub GRASP, jeśli wolisz), która umieszcza kod w modułowych, wielokrotnego użytku, wymiennych częściach, które ponownie pomagają w utrzymaniu (nie tylko mogą zrozumieć, co zrobiłeś i dlaczego, ale są czyste linie, wzdłuż których mogę chirurgicznie usunąć i wymienić fragmenty kodu). Ostatnim priorytetem jest wydajność; jeśli kod jest na tyle ważny, że musi być zgodny ze specyfikacjami wydajności, prawie na pewno jest wystarczająco ważny, aby najpierw był poprawny, czysty i SOLIDNY.
Nawiązując do Christophera (i Donalda Knutha), „przedwczesna optymalizacja jest źródłem wszelkiego zła”. Ponadto rozważane rodzaje optymalizacji są niewielkie (odniesienie do nowego obiektu zostanie utworzone na stosie, niezależnie od tego, czy nadasz mu nazwę w kodzie źródłowym, czy nie), a także typu, który nie może powodować żadnych różnic w kompilacji IL. Nazwy zmiennych nie są przenoszone do IL, więc ponieważ deklarujesz zmienną tuż przed jej pierwszym (i prawdopodobnie jedynym) użyciem, postawiłbym trochę pieniędzy na piwo, że IL jest identyczna między Twoimi dwoma przykładami. Twój współpracownik ma więc 100% racji; patrzysz w niewłaściwym miejscu, jeśli patrzysz na zmienną nazwaną vs instancję wbudowaną, aby coś zoptymalizować.
Mikrooptymalizacje w .NET prawie nigdy nie są tego warte (mówię o 99,99% przypadków). Być może w C / C ++ JEŚLI wiesz, co robisz. Pracując w środowisku .NET, jesteś już wystarczająco daleko od metalu sprzętu, co powoduje znaczne obciążenie podczas wykonywania kodu. Biorąc pod uwagę, że jesteś już w środowisku, które wskazuje, że zrezygnowałeś z błyskawicznej prędkości i zamiast tego chcesz napisać „poprawny” kod, jeśli coś w środowisku .NET naprawdę nie działa wystarczająco szybko, albo jego złożoność jest zbyt wysoko, lub powinieneś rozważyć równoległe ustawienie. Oto kilka podstawowych wskazówek dotyczących optymalizacji; Gwarantuję Ci, że Twoja optymalizacja wydajności (prędkość uzyskana z poświęconego czasu) gwałtownie wzrośnie:
if(myObject != null && myObject.someProperty == 1)
) lub B zajmuje więcej niż 9 razy dłużej niż A do oceny (if(myObject != null && some10SecondMethodReturningBool())
).źródło
Jedynym czasem, gdy trzeba się wcześnie martwić optymalizacją, jest to, że wiesz, że masz do czynienia z czymś, co jest albo ogromne, albo że coś, co wiesz, wykona się ogromną liczbę razy.
Definicja „ogromnego” oczywiście różni się w zależności od tego, jakie są twoje systemy docelowe.
źródło
Wolałbym wersję dwuliniową po prostu dlatego, że łatwiej jest przejść przez debugger. Linia z kilkoma wbudowanymi połączeniami utrudnia.
źródło