Nasza strona używa cookies. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

10 dobrych praktyk kodowania w Javie

Poznaj dobre praktyki kodowania w Javie, które ułatwią życie Tobie i Twoim kolegom programistom.
10 dobrych praktyk kodowania w Javie

Najlepsze praktyki kodowania w Javie są często ignorowane przez programistów z powodu braku wiedzy na ich temat lub brak czasu na ich wdrożenie. Jednak czas, który poświęcasz na naukę i wdrażanie najlepszych praktyk, jest większą inwestycją, niż możesz sobie wyobrazić.

Najlepsze praktyki omówione w tym artykule są przeznaczone zarówno dla młodszych, jak i starszych programistów Javy. Pomogą Ci one poprawić działanie, zmniejszyć ryzyko związane z bezpieczeństwem, oszczędzić pamięć danych i uprościć debugowanie. To z kolei pozwoli Ci zaoszczędzić mnóstwo czasu. Zaczynajmy więc.


Stosuj prawidłowe konwencje nazewnictwa


Jeśli wiesz, w jaki sposób coś działa, masz całkiem duże szanse na odgadnięcie nazwy klasy lub interfejsu Springa.

Rod Johnson, twórca frameworka Spring, wypowiedział powyższe zdanie, aby podkreślić wagę przestrzegania konwencji nazewnictwa. I takowe powinny być przestrzegane również w kodzie Javy.

Dobrze sformułowana nazwa nie tylko pomaga w czytaniu kodu, ale także przekazuje wiele informacji o jego intencji. Przyjrzyjmy się przykładowi z życia wziętemu.

public class User{     
    private String userName;     
    public void setUserName(String userName){  
        this.userName = userName;     
    } 
}


Jak widać na powyższym przykładzie:

  • nazwy klas lub interfejsów powinny być rzeczownikami, ponieważ reprezentują one obiekty świata rzeczywistego
  • nazwy metod powinny być czasownikami, ponieważ są one zawsze częścią klasy i mówiąc ogólnie - reprezentują one działanie
  • nazwy zmiennych powinny być krótkie, ale sensowne, natomiast jednoznakowe nazwy zmiennych powinny być unikane, z wyjątkiem zmiennych tymczasowych, takich jak liczniki w pętli.


Tak więc, zamiast wypełniania swojego kodu bezsensownymi nazwami, używaj nazw o większym znaczeniu, które ułatwią Twoim kolegom programistom, inżynierom QA, a nawet Tobie samemu, zrozumienie kodu w przyszłości.


Minimalizuj używanie operatora "+" do łączenia ciągów znaków

Używanie operatora "+" w Javie do łączenia Stringów jest powszechną praktyką wśród wielu programistów, w tym moją. Jednakże, podczas łączenia wielu Stringów, operator "+" jest nieefektywny, ponieważ kompilator Javy tworzy wiele pośrednich obiektów String przed utworzeniem końcowego połączonego Stringu.

Taki przydział pamięci dla każdego Stringa spowalnia program i koniec końców może pochłonąć całą pamięć danych.

Rozwiązaniem, a zarazem najlepszą praktyką w Javie, byłoby użycie klas StringBuilder lub StringBuffer.  Funkcje wbudowane w te klasy, takie jak append(), mogą łączyć dwa Stringi bez tworzenia pośrednich obiektów String, oszczędzając czas przetwarzania i zużycie pamięci.

StringBuilder sbd = new StringBuilder("0");
for (int i = 1; i < 100; i++) {
    sbd.append(", "+i);        
}

 


Unikaj zmienności obiektów

Stan obiektu i wartości zmiennych obiektów zmiennych mogą się zmieniać podczas ich cyklu życia. Ponieważ wiele zmiennych może wskazywać na tę samą instancję, śledzenie, kiedy i gdzie zmienił się stan obiektu, może być dość trudne. Jest to przekonujący powód na to, by unikać mutowalności obiektów, kiedy tylko jest to możliwe.

Z drugiej jednak strony obiekty niezmienne nie zmieniają swojego wewnętrznego stanu w czasie, są bezpieczne dla wątków i nie produkując skutków ubocznych. Ze względu na te cechy, obiekty niezmienne są szczególnie przydatne w środowiskach wielowątkowych.

Najbardziej podstawowym sposobem osiągnięcia niezmienności jest uczynienie wszystkich mutowalnych pól private i final, tak aby nie mogły być zmienione z zewnątrz po ich zainicjalizowaniu. Spring Framework pozwala na zachowanie niezmienności obiektów poprzez użycie constructor modelu wstrzykiwania zależności.


Logowanie

Znaczenie logowania w czasie pisania kodu, a w szczególności w utrzymaniu, jest nie do przecenienia. Każdy programista Javy, który kiedykolwiek debugował kod produkcyjny, w pewnym momencie zapewne marzył o większej ilości logów.

API do logowania w Javie, które znajduje się w pakiecie java.util.logging, pozwala na śledzenie błędów w aplikacjach. Kiedy wywołanie logowania jest generowane przez aplikację, Logger rejestruje event w LogRecord. Następnie wysyła je do odpowiednich handlerów lub appenderów.

W Javie istnieje wiele bibliotek i frameworków logowania, m.in SLF4J oraz Logback. Podczas gdy sprawiają one, że logowanie w bazie kodu jest stosunkowo proste, powinieneś upewnić się, że stosujesz się do najlepszych praktyk logowania. W przeciwnym razie niechlujne podejście do logowania może stać się w przyszłości koszmarem, a nie dobrodziejstwem. Przyjrzyjmy się więc niektórym z tych najlepszych praktyk:

  • Unikaj nadmiernego logowania i uwzględniaj tylko te informacje, które mogą być przydatne w wykrywaniu i usuwaniu usterek.
  • Wybieraj poziomy logowania ostrożnie; być może będziesz musiał włączyć poziomy logowania selektywnie w produkcji.
  • Aby uzyskać szybszą analizę, należy użyć zewnętrznych narzędzi do śledzenia, agregacji i filtrowania komunikatów logowania.


Przyjrzyjmy się przykładowi prawidłowo opisanego logowania.

logger.info(String.format(“A new user has been created with userId: %s”, userId));


Zawsze sprawdzaj parametry

Zawsze sprawdzaj poprawność parametrów wejściowych swoich metod publicznych przed wykonaniem jakiejkolwiek logiki, aby zapewnić odporność na błędy. Asercje w Javie są najlepszym sposobem na sprawdzenie poprawności parametrów metod. W poniższym przykładzie, jeśli wiek jest mniejszy niż zero, wyrzucany jest błąd AssertionError

public void setAge(int age) {
    assert age >= 0 : "Age should be positive";
}


Uwaga: Aby uniknąć wpływu na wydajność systemu produkcyjnego, możesz wyłączyć asercje w czasie wykonywania.

Inną opcją jest użycie Google Guava, gdzie klasa Preconditions może być użyta do sprawdzania poprawności parametrów. Guava zapewnia większą elastyczność niż podstawowa asercja Javy.


Unikaj pustych bloków catch

Pisanie właściwych i znaczących komunikatów w bloku catch podczas obsługi wyjątków jest praktyką stosowaną przez najlpszych. Początkujący programiści często pozostawiają na początku puste bloki catch, ponieważ są oni jedynymi osobami pracującymi nad kodem. Kiedy jednak wyjątek zostanie wyłapany przez pusty blok catch, program nie pokazuje niczego, a przez to późniejsze debugowanie staje się koszmarem.

Ponadto, nieobsłużone wyjątki bądź zrzucenie stosu mogą sprawić, że Twoja aplikacja będzie podatna na ataki przez wstrzykiwanie.

Dlatego bardzo ważne jest, aby poprawnie obsłużyć wyjątki w bloku catch. Poniższy przykład demonstruje, jak użyć go w prawidłowy sposób.

try {                
    doSomeWork();        
} catch (NullPointerException e) {  
    log("Exception occurred", e);
    response.sendError(
        HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
        "Exception occurred");
    return;
}


W przykładzie logujemy stack trace i zwracamy ogólną odpowiedź, aby uniemożliwić atakującym zobaczenie go.


Unikaj zbędnej inicjalizacji

Jest niepotrzebne i zbędne, aby jawnie ustawiać wartości na 0, false lub null dla jakichkolwiek pól, lub elementów tablicy.

Domyślnie Java ustawia wartości pól lub elementów tablicy na wartości wymienione powyżej. Funkcja ta została specjalnie włączona do Javy, aby zredukować powtarzające się kodowanie. Powinniśmy więc z niej korzystać.


Float czy Double?

Niedostatecznie doświadczeni programiści często używają float i double w nieodpowiednich kontekstach. Zazwyczaj wybierają tylko jeden typ, niezależnie od wytycznych. Natomiast jest to warunek konieczny do ich używania.

Jeśli potrzebujesz precyzyjnych obliczeń, zamiast float powinieneś użyć double. Większości procesorów zajmuje prawie tyle samo czasu na przetwarzanie operacji na float i double, ale double oferuje znacznie większą precyzję niż float.

Kiedy precyzja nie jest dużym problemem, możesz użyć float zamiast double, ponieważ zajmuje on połowę miejsca w pamięci, które zajmuje double.

Pamiętaj, że użycie odpowiedniego typu danych znacząco poprawia wydajność Twojego kodu.


Najlepszy sposób na sprawdzenie nieparzystości

Widziałem, że wielu programistów używa i % 2 == 1 od razu, aby sprawdzić, czy liczba jest nieparzysta, czy nie, co jest oczywiście nieprawidłowe. Takie działanie jest odpowiednie tylko dla liczb dodatnich. Poniższa metoda jest poprawnym sposobem sprawdzenia nieparzystości liczby zarówno dodatniej jak i ujemnej w Javie.

public boolean isOdd(int num) {
   return (num % 2 != 0)
}


Nawet jeśli powyższe działanie jest poprawne, to nie jest to jednak najlepsza praktyka do stosowania w Javie. Ponieważ operator poziomu bitowego AND jest znacznie szybszy niż arytmetyczne działanie modulo, użycie poniższej metody do sprawdzenia nieparzystości jest najlepszą praktyką w Javie.

public boolean isOdd(int num) {
   return (num & 1) != 0;
}


Unikanie wycieków pamięci

Chociaż Java automatycznie zarządza pamięcią i unika większości wycieków pamięci, to jednak mogą one wystąpić i wystąpią, jeśli nie będą przestrzegane odpowiednie praktyki. Niektóre z nich obejmują zwolnienie połączeń do bazy danych po zakończeniu zapytania, używanie bloku finally tak często, jak to możliwe, unikanie klas wewnętrznych i zwalnianie instancji przechowywanych w Static Tables.

Istnieje również wiele narzędzi, które pomogą Ci wykryć wycieki pamięci w Twoim kodzie.

  • Zakładka  Memory w IntelliJ IDEA pozwala wyświetlić szczegóły wszystkich obiektów na stercie, co jest dużym ułatwieniem w wykrywaniu wycieków pamięci i ich przyczyn. W IntelliJ można również użyć okna narzędzia Profiler, aby przechwycić zrzuty pamięci uruchomionych procesów i przeanalizować je pod kątem wycieków.
  •  Memory Analyzer (MAT) w Eclipse pozwala zbadać stertę Javy pod kątem wycieków pamięci i zmniejszyć jej zużycie. Możesz łatwo przeanalizować zrzut sterty, nawet jeśli zawiera ona miliony obiektów oraz zobaczyć rozmiary każdego z nich.
  • NetBeans Profiler może być użyty do analizy wykorzystania pamięci w Java SE, Java FX, EJB, aplikacjach mobilnych i internetowych.
  • Poza tym możesz użyć Java Flight Recorder lub open-source VisualVM do debugowania wycieków pamięci w aplikacji.


Wycieki pamięci w Twojej aplikacji mogą znacząco obniżyć wydajność, tak więc upewnij się, że możesz ich uniknąć, stosując się do najlepszych praktyk wymienionych powyżej.

To już wszystko na ten moment. Mam nadzieję, że będziesz przestrzegać tych najlepszych praktyk, aby upewnić się, że Twój kod jest czysty, a Twoja aplikacja wydajna.

Dziękuję za przeczytanie i życzę udanego kodowania!



Oryginał tekstu w języku angielskim przeczytasz tutaj.

1 komentarz

Lubisz dzielić się wiedzą i chcesz zostać autorem?

Podziel się wiedzą z 160 tysiącami naszych czytelników

Dowiedz się więcej