Clean code

Clean code

Możliwe, że zdarzyło Ci się czytać kod innego programisty – czy to na jakimś forum, a może kod kolegi. Czy czytanie cudzego kodu jest łatwe?

A no nie zawsze, szczególnie wtedy nie jest łatwe, gdy drugi programista nie korzysta przynajmniej z podstawowych założeń Clean Code.

Sami musimy się wcielić w tego drugiego programistę, która piszę kod nie tylko dla siebie – ale też dla innych.

Postaram Ci się pokazać kilka koncepcji, które pozwolą Ci tworzyć tak kod, tak jak byś miał go rozwijać/utrzymywać przez całe swoje życie – do dzieła!

Komentowanie kodu

Co do komentarzy jest jedna prosta zasada – komentarzy prawie nie powinno być w kodzie – takiej zasady powinniśmy się trzymać. Jedynym wyjątkiem są tzw. Java Docsy – czyli komentarze na podstawie, których jest generowana dokumentacja.

Skoro nie możemy korzystać zbyt często z komentarzy to musimy zadbać o jedną rzecz – pisać kod samotłumaczący się!

Jeżeli sam kod od samego początku nic o sobie nie mówi to jest bardzo źle – jednak nie ma co teraz panikować, wystarczy zastosować kilka prostych zasad.

Nazwy zmiennych

Wszystkie zmienne nazywaj tak, aby na pierwszy rzut oka było wiadomo co w niej jest przechowywane – w jakim celu ona tu po prostu jest.

Nie używajmy żadnych skrótowców typu: a1, x, asd, dupa – no chyba, że faktycznie przechowujemy tam obiekt odnoszący się do części ciała.

Przykładowe nazwy, które od razu mówią z czym mamy do czynienia:

int age;
String login;
Long userId;
String url;

Zauważ, że zmienna userId – jest zapisana w notacji lowerCamelCase – jest to najczęściej stosowana konwencja zapisywania nazw zmiennych w Javie.

Skoro nawiązałem już do notacji – wybierz jedną notację, w której będzie pisać całą aplikację – namawiam, aby to była notacja CamelCase.

Zwróć uwagę, że wszystkie nazwy zmiennych są w języku angielskim – zawsze pisz wszystkie nazwy w języku angielskim – nigdy nie wiadomo, kto zajrzy (lub kto będzie chciał zajrzeć) do Twojego kodu.

Metody

Powiedzieliśmy już sobie o zmiennych – czas na metody – również o ich nazywaniu. Wiele konwencji się powtórzy.

Stosuj tą samą notację do nazywania metod jakiej używasz do nazywania zmiennych – w moim przypadku (i większości) jest to notacja lowerCamelCase.

Nazwy metod powinny być w języku angielskim.

Nazwa metody powinna zawierać w sobie bezokolicznik informujący o tym za co jest odpowiedzialna.

Z pewnością lepszą nazwą będzie:

public float calculateAverage(int [] numbers){
};

Niż

public float average(int [] numbers){
};

W drugim przykładzie nie do końca od razu wiadomo co z tą średnią.

Wszystkie metody zwracające powinny zawierać przedrostek – get np.:

public User getUserById(Long id){
};

Tzw. settery powinny zaczynać się od przedrosta – set np.:

public void setUserId(Long id){
};

Zmienne, które zwracają boolean powinny się zaczynać od przedrostów – has i is np:

public boolean isMale(){
}

Lub

public boolean hasCapacity(){
}

Pamiętaj, żeby tworzyć metody, które są odpowiedzialne tylko za jedną rzecz – nie twórz hiper-ekstra dużych funkcji – są one po prostu nieczytelne. Rozbij lepiej swój kod na kilka funkcji i je wywołuj w funkcji odpowiedzialnej za daną funkcjonalność.

Zamiast tworzyć taką funkcję:

public void registerUser(User user){
    if(userDao.existsUserByLogin(user.getLogin()) && userDao.existsUserByEmail(user.getEmail())){
        userDao.addUser(user);
    }
}

Lepiej rozbić to na kilka funkcji:

public boolean isNotLoginExist(String login){
    return userDao.existsUserByLogin(login);
}

public boolean isNotEmailExist(String email){
    return userDao.existsUserByEmail(email);
}

public boolean canRegisterUser(User user){
    return isNotEmailExist(user.getEmail()) && isNotLoginExist(user.getLogin());
}

public void registerUser(User user){
    if(canRegisterUser(user)){
        userDao.addUser(user);
    }
}

Na pierwszy rzut oka wiem co gdzie jest sprawdzane – dodatkowo wszystkie te metody mogę używać w innych fragmentach aplikacji!

Klasy

Rozpocznijmy ponownie od konwencji – w przypadku klas stosuję (i zazwyczaj się stosuję) notację UpperCamelCase – czyli nazwa klasy zaczyna się z dużej litery.

Przykładowa klasa:

public class UserService {
}

Oczywiście nazwy klas powinny być również zapisywane w języku angielskim – nic się tutaj nie zmienia!

Nazwa powinna już być jednym rzeczownikiem – lub złączeniem kilku.

Na przykłada taka klasa:

public class UserManager {
}

Może zawierać w sobie metody odpowiedzialne za zarządzanie użytkownikami – wiadomo o tym od razu, gdy tylko zobaczymy słowo user manager.

Kolejną klasą może być:

public class UserValidation {
}

Od razu wiadomo, że klasa jest odpowiedzialna za wszelką walidację usera.

Kolejnym ważnym zagadnieniem, o którym trzeba pamiętać podczas tworzenia klasy jest zasada jednej odpowiedzialności – o co w niej chodzi?

Chodzi o to, aby klasa była odpowiedzialna tylko za konkretne działania, które można w jakikolwiek skategoryzować.

Zamiast tworzyć klasę klasę UserService – gdzie będą wszystkie metody odpowiedzialne za działania na userach to jest bez sensu – podzielmy to.

Zróbmy osobną klasę odpowiedzialną za komunikację z bazą danych np. UserDao.

Zróbmy klasę odpowiedzialną za walidację użytkowników np. UserValidation.

Nie twórzmy wielkich klas odpowiedzialnych za wszystko – starajmy się, aby nasze klasy były najbardziej możliwe małe i nie brały na siebie zbyt dużej odpowiedzialności.

Podsumowanie

Przedstawiłem Ci kilka zasad, większość z nich możesz od razu wprowadzić w swoje programistyczne życie – mogę Cię zapewnić, że sam sobie kiedyś podziękujesz, gdy zajrzysz w przyszłości do starego kodu. Inni programiści też Ci za to podziękują – może nie osobiście, ale chociaż w duchu.

Na koniec przygotowałem dla Ciebie krótką listę koncepcji, o których wspomniałem w tym artykule:

  1. Do nazywania zmiennych, metod i klas używaj języka angielskiego!
  2. Nazwa zmiennej powinna od razu mówić w jakim celu została stworzona.
  3. Nazwa metody powinna mówić o tym za co jest odpowiedzialna – stosuj bezokoliczniki.
  4. Nazwa klasy powinna mówić za co jest odpowiedzialna – stosuj rzeczowniki.
  5. Nie buduj hiper-ekstra-wielkich i skomplikowanych funkcji – pamiętaj, aby dzielić większe metody na mniejsze – kod będzie czytelniejsze, a dodatkowe metody mogą się jeszcze przydać.
  6. W obrębie całej aplikacji stosuj jedną notację nazewnictwa – w Javie stosuję się lowerCamelCase dla zmiennych i metod oraz UpperCamelCase dla klas.
  7. Nazwy stałych zapisuj wielkimi literami oddzielając jej człony podkreśleniem (podłogą).
  8. Nie pisz komentarzy – pisz czysty kod!

A czy Ty stosujesz już te wszystkie zasady w swoim kodzie? O której może nie wiedziałeś, a może jest jakaś zasada, którą stosujesz i chciałbyś się nią z nami podzielić? Czekam na Wasze zasady kodowe w komentarzach, cześć! 😉