Enumy na sterydach

Enumy na sterydach

Enumy są w javie od wersji 5. Dla większości jest to niemal od zawsze. Niestety przez wielu są one lekceważone i przez to nie potrafią pokazać swojej prawdziwej mocy. Czym dokładnie są typy wyliczeniowe znajdziecie na samouczku programisty. Poniżej przedstawię kilka sposobów, które sprawią, że odkryjesz ich moc. Dzięki temu może zaczniesz ich używać częściej i z większą świadomością.

Enumy to singletony

Chyba jedną z najczęściej zapominanych własności enumów jest to, że są singletonami. Zamiast napisać prostego enuma, wielu wciąż próbuje stworzyć ten wzorzec projektowy w sposób klasyczny. W większości przypadków nie ma takiej potrzeby.

Stałe

Mogłeś się spotkać z kodem, który sprawdzał określone wartości.

Integer status = restCall();
if(status.equals(200) {
            importantSuccessLogic();
        } else if (status.equals(400) {
             importantSuccessLogic();
        } else {
            throw new IllegalArgumentException();
        }

Zawsze gdy masz jakaś określoną grupę stałych, użyj enuma. Twój kod będzie czytelniejszy i łatwiejszy w utrzymaniu. Również dzięki temu będziesz wiedział co te wartości oznaczają i w jakim są kontekście.

Lombok

Znam wiele osób dla których największym zaskoczeniem było to, że w enumach można wykorzystywać lomboka. Co ciekawe nikt nie potrafił powiedzieć dlaczego miałby on nie działać. Więc taki kod jest jak najbardziej poprawny.

@RequiredArgsConstructor
public enum Status {
    
    SUCCESS(200),
    
    ERROR(400);
    
    private final Integer httpCode;
    
}

Pobieranie

Enumy mają własne metody fabrykujące

 valueOf(String name) 

Jednak to działa tylko wtedy gdy, przekazany parametr jest dokładnie taki sam jak enum. Nie w każdym przypadku taka sytuacja nam odpowiada. Dzięki streamom w łatwy sposób można pobrać enum na podstawie jego wartości.

    static Status of(Integer code) {
        return Stream.of(values())
                .filter(st->st.httpCode == code)
                .findAny()
                .orElseThrow(()->new IllegalArgumentException());
    }

Gdy patrzysz na powyższy kod, może zaczniesz dostrzegać ogromny potencjał. Czy wiesz jak to można wykorzystać? Może zmapować wszystkie kody http na odpowiedni enum? Na szczęście z tym też nie ma problemu. Dobrym rozwiązaniem może być użycie pattern matchingu. Z takim podejściem powstaje bardzo czytelny kod i jednocześnie bardzo potężny.

Dla wielu enumy to jak historia
Dla wielu enumy to jak historia

Interfejsy

Wiesz o tym, że w typach wyliczeniowych mogą być metody abstrakcyjne. Ale tak samo enumy mogą implementować interfejsy. Metody, które są zaimplementowane mogą znaleźć się w dwóch miejscach.

public enum Status implements SomeInterface {

    SUCCESS(200),
    ERROR(400);

    @Override
    public void importantLogic() {

    }

W tym miejscu metoda someLogic jest dla wszystkich typów w danym enumie. Ale może też zostać nadpisana przez poszczególne typy.

public enum Status implements SomeInterface {

    SUCCESS(200) {
   @Override
    public void importantLogic() {

    }},

    ERROR(400) {
   @Override
    public void importantLogic() {

    }};

    @Override
    public void importantLogic() {

    }

Zobacz jakie możliwości otwierają się przed Tobą. Możesz stworzyć z  niego beana springowego, który ma jakąś prostą logikę. Innym wykorzystaniem to feature toggle. Dzięki takiemu podejściu wiele problemów możesz rozwiązać w całkiem inny sposób.

Przekształcenie na koniec

Mam nadzieję, że pamiętasz wcześniejszy przykład z logiką wyboru statusu. Dzięki użyciu enumów tamten kod może się skrócić i zostać ulepszony do postaci:

Integer status = restCall();
Status.of(status).importantLogic();

Moim zdaniem powyższy kod jest bardzo prosty i czytelny. A taki kod jest zawsze łatwiejszy w utrzymaniu.

Kiedy używać

Staraj się używać enumów. Nie mówię, że w każdym możliwym przypadku. Jednak w sytuacjach, gdy masz grupę wartości/stałych powiązanych ze sobą jest to z dużą dozą prawdopodobieństwa odpowiednie miejsce dla nich. Innym dobrym przykładem są konwencje w kodzie, tworzenie kluczy lokalizacyjnych czy inne konfiguracje. Mimo tego, że enumy są niepozorne to można w nich odnaleźć wielkie możliwości. Dzięki temu Twój kod może być lepszy.