Allman
W Epomis używamy stylu Allman - najwygodniej jest ustawić w IDE schemat do automatycznego formatowania.
Dla IntelliJ:
Settings -> Editor -> Code Style
klikamy Scheme
i wybieramy Project
(wtedy Allman będzie działał tylko w Epomis - reszta projektów będzie formatowana domyślnie) Import Scheme..
szukamy folderu other
w Epomis
i wybieramy plik AllMyStyle.xml
Następnie, w klasie z którą pracujemy, wciskamy Ctrl+Alt+L
- auto format. Działa to również na modułach.
Warto również zaznaczyć opcję, do automatycznego formatowania kodu podczas commitu
.
Formatowanie
1. Importy
-
Nie używamy wieloznaczników (wildcard)
*
. Deklarujemy każdy import oddzielnie, IDE i tak nam je zawinie, więc nie martwimy się tym, że może być ich dużo.
Źle:
import epomis.acceptor.applicant.linkedin.entity.*;
Dobrze:
import epomis.acceptor.applicant.linkedin.entity.InMailConversation;
import epomis.acceptor.applicant.linkedin.entity.InMailMessage;
import epomis.acceptor.applicant.linkedin.entity.ImportedMessage;
import epomis.acceptor.applicant.linkedin.entity.DeliveredMessage;
import epomis.acceptor.applicant.linkedin.entity.PromotedMessage;
-
Grupujemy importy, oddzielając jedną pustą linią.
Źle:
import epomis.service.connection6.request.DataEntry;
import epomis.service.connection6.response.HtmlResponse;
import org.jsoup.nodes.Document;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import epomis.acceptor.applicant.ApplicationForm;
import epomis.acceptor.applicant.HtmlApplicant;
Dobrze:
import epomis.service.connection6.request.DataEntry;
import epomis.service.connection6.response.HtmlResponse;
import lombok.SneakyThrows;
import lombok.RequiredArgsConstructor;
import epomis.acceptor.applicant.ApplicationForm;
import epomis.acceptor.applicant.HtmlApplicant;
import org.jsoup.nodes.Document;
import org.springframework.stereotype.Service;
2. Puste linie
Zwracamy uwagę na to, żeby nie było ich, w miejscach niepotrzebnych, jednocześnie dodając odstęp jeśli wpłynie to na poprawę czytelności a zarazem zrozumienia kodu.
- Usuwamy puste linie otaczające klamerki:
class DataResolver
{
// <------------ źle
List<DataEntry> resolverMissingRequestData(ApplyForm applyForm, UserResume userResume)
{
// <------------ źle
List<DataEntry> userDataEntries = userResume.userDataEntries();
List<ApplyFormEntry> formData = applyForm.getFormData();
// <------------ dobrze!
return requestDataResolver.resolveFormData(userDataEntries, formData);
// <------------ źle
}
// <------------ źle
}
- Dodajemy puste linie grupując odpowiedzialności:
private InMailMessage extractMessage(LinkedinMessage linkedinMessage)
{
String senderName = getMiniProfile(linkedinMessage).getFirstName();
String senderLastName = getMiniProfile(linkedinMessage).getLastName();
String messageBody = linkedinMessage
.getEventContent()
.getMessageEvent()
.getBody();
String date = dateConverter.dateConvert(linkedinMessage.getCreatedAt());
return InMailMessage
.builder()
.date(date)
.senderName(senderName)
.senderLastName(senderLastName)
.messageBody(messageBody)
.build();
}
3. Łańcuchy i strumienie wywołań
Podczas wywoływania metod lub korzystania ze strumieni, dbamy o to, żeby każde kolejne wywołanie metody, znajdywało się w kolejnej linii. Tworzymy kolumny a nie wiersze wywołań. Operator .
(kropkę) stawiamy w następnej linii. Dotyczy to tylko sytuacji w której są 2 lub więcej wywołań!
private void someMethod(ApplicationForm applicationForm)
{
Ad ad = applicationForm // <----- źle, jest tylko jedno wywołanie
.getAd();
Ad ad = applicationForm.getAd(); // <------ dobrze
String href = applicationForm.getAd().getHref(); // <----- źle, dwa wywołania
String href = applicationForm // <------ dobrze
.getAd()
.getHref();
}
4. Top down approach
The "top down" approach takes a high level definition of the problem and subdivides it into subproblems, which you then do recursively until you're down to pieces that are obvious and easy to code. This is often associated with the "functional decomposition" style of programming, but needn't be.
Też tu się stosuje konwencja polożenia metod w ciale klasy i odnośnie siebie. Metody o wyższej abstrakcji - wyżej, niższej niżej. Na kod to się przekłada w następujący sposób:
- metoda A używa metody B, wtedy B powinna znaleźć się pod metodą A;
- metody A i C używają B, wtedy B powinna znaleźć się pod najniższą z nich;
- metoda A używa B i C, wtedy B i C powinni znaleźć się pod A w kolejności użycia;
- w miarę możliwości preferujemy by na początku klasy się znajdywały metody publiczne (tzn. publiczny interfejs klasy).
To rozwiązuję parę probłemów:
- zlokalizowanie wywolanych metod (zawsze jest niżej, nie trzeba skrolować w obie strony)
- minimalizacja odłeglości między powiązanymi metodami (po prostu znajdują się bliżej)
- spójność kodu