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

5 bibliotek Javy, które podkręcą Twoją produktywność

Abhishek Kapoor Software Developer / Amdocs
Poznaj takie biblioteky Javy jak Guava, MapStruct, czy inne i zacznij z nich korzystać, aby być bardziej produktywnym podczas codziennego kodowania.
5 bibliotek Javy, które podkręcą Twoją produktywność

Pisanie powtarzalnego kodu lub kodu, który okazuje się być niepotrzebny, zajmuje mnóstwo czasu. Społeczność zgromadzona wokół Javy stworzyła wiele bibliotek, które ułatwiają wzrost produktywności poprzez pozbycie się konieczności pisania powtarzalnego kodu lub dostarczając narzędzi do rozwiązywania typowych problemów z Javą. W tym artykule poznamy niektóre z tych bibliotek.


1) Projekt Lombok

Masz już dość plików, w których są tylko powtarzalne metody, jak gettery, settery, konstruktory, czy nadpisane metody equals? Lombok jest więc stworzony dla Ciebie. Większość IDE potrafi automatycznie generować metody getter i setter za pomocą jednego kliknięcia, ale różnica polega na tym, że IDE generuje te metody w samym pliku java, a Lombok generuje wszystkie metody bezpośrednio do pliku klasy.

To jednak nie wszystko. Lombok pomoże nam również w usuwaniu innego powtarzalnego kodu. Spójrzmy na kilka przykładów.

public class StudentServiceWithoutLombok implements IStudentService {
  private static final Logger log = Logger.getLogger(StudentServiceWithLombok.class);

  @Override
  public void method1() {
    log.info("In method1 ");
  }

}


Powyższy kod jest bez Lomboka. Teraz napiszmy ten sam kod z frameworkiem Lombok.

@Log4j
public class StudentServiceWithLombok implements IStudentService {

  @Override
  public void method1() {
    log.info("In method1 ");
  }

}


Można było zauważyć, że nie musimy inicjalizować loggera w tym pliku i w tym przypadku jest to tylko jedna linia, ale w większych projektach z tysiącami plików, nie będziesz musiał pisać tej samej linii w kółko, a zamiast tego, możesz skoncentrować się na swojej logice biznesowej. Pozwól, że podam Ci kolejny przykład przedstawiający jeszcze jedną klasę bez Lomboka.

public class Student {

  private Integer rollNumber;
  private String name;

  public Student(Integer rollNumber, String name) {
    super();
    this.rollNumber = rollNumber;
    this.name = name;
  }

  public Integer getRollNumber() {
    return rollNumber;
  }

  public void setRollNumber(Integer rollNumber) {
    this.rollNumber = rollNumber;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  @Override
  public String toString() {
    return "Student [" +
      "rollNumber=" + rollNumber +
      ", name=" + name + ", " +
      "]";
  }
}


Gdybym miał teraz napisać ten sam kod z Lombokiem, wyglądałby tak jak poniżej:

@AllArgsConstructor
@Data
public class Student {
  private Integer rollNumber;
  private String name;
}


Zdziwiony? Cóż, kod z Lombokiem nie posiada żadnego powtarzalnego kodu i jest dużo łatwiejszy do czytania.

Lombok usuwa wiele linii powtarzalnego kodu, dzięki czemu możesz skupić się na logice biznesowej. Twój kod będzie także wyglądał schludniej. Jeżeli chodzi o Lombok, to jest tego o wiele więcej, niż zdążyliśmy omówić w artykule. O pozostałych świetnych funkcjach projektu Lombok dowiesz się z ich oficjalnej strony.


2) MapStruct

Czy używasz architektury wielowarstwowej w swoim projekcie w Javie? Jeśli tak, to zdecydowanie powinieneś pomyśleć o użyciu MapStruct.

W architekturze wielowarstwowej wszystkie warstwy aplikacji są ze sobą luźno powiązane. Mogą pojawić się sytuacje, w których będziesz musiał zmapować obiekt, który istnieje w jednej warstwie do obiektu innej warstwy. Częstym przykładem jest sytuacja, w której Twoje encje, które znajdują się w warstwie dostępu do danych, będą mapowane do obiektów domenowych (DTO) w warstwie aplikacji. Mapowanie prostych obiektów POJO na inne POJO może wiązać się z koniecznością zastosowania powtarzalnego kodu.

Rozważmy dwie poniższe klasy. Musimy tutaj zmapować klasę student z encji do obiektu domenowego.

@Entity
@Data
public class Student {
  private Integer rollNumber;
  private String name;
}

@Data
public class StudentDTO {
  private Integer rollNumber;
  private String name;
}


Gdybyś musiał zmapować dwie klasy, to prawdopodobnie napiszesz klasę konwertującą, która będzie posiadała funkcję, która przyjmie Student jako wejście i zwróci StudentDTO jako wyjście. Coś takiego, jak tutaj:

public class StudenttoStudentDTOconvertor {
  public StudentDTO convert(Student student) {
    StudentDTO studentDTO = new StudenDTO();
    studentDTO.setName(student.getName);
    studentDTO.setRollNo(student.getRollNo());
    return studentDTO;
  }
}


Student był zwykłą klasą z tylko dwoma polami. Zauważ również, że musimy napisać 4 linie kodu, a gdyby ta klasa miała dużą ilość pól, to ilość linii w kodzie konwertera również wzrośnie. Aby uniknąć pisania takiego powtarzalnego kodu, możemy użyć MapStruct, który wygeneruje go automatycznie. A teraz przepiszmy nasz kod klasy konwertującej za pomocą MapStruct.

@Mapper
public interface StudenttoStudentDTOMapper {
  StudentDTO map(Student student);
}


Cóż, to w sumie wszystko. Nie będziesz musiał implementować interfejsu. MapStruct zrobi to automatycznie za Ciebie. Jeśli w przyszłości zdecydujesz się dodać jeszcze jedno nowe pole, powiedzmy np. imię ojca w klasie encji, wtedy możesz dodać to samo pole w DTO i nie musisz już wtedy dokonywać żadnych zmian w klasie Mapper. Ciekawe, prawda? Jeśli chcesz dowiedzieć się więcej o innych ciekawych funkcjach MapStruct, sprawdź ich oficjalną stronę.


3) Guava

Nie umiem lepiej wytłumaczyć Guavy, niż jak zostało to zdefiniowane w repozytorium GitHuba. Poniżej zamieszczam definicję, którą stamtąd skopiowałem:

Guava to zestaw podstawowych bibliotek Javy od Google, który zawiera nowe typy kolekcji (takie jak multimapy i multizbiory), niemutowalne kolekcje, bibliotekę grafów oraz narzędzia do współbieżności, I/O, haszowania, cache'owania, typów prymitywnych, ciągów znaków i wiele więcej! Jest on powszechnie stosowany w większości projektów Java w Google, a także w wielu innych firmach.


Brzmi ciekawie, prawda? Guava posiada narzędzia, które mogą pomóc w rozwiązywaniu nie tylko prostych problemów w Javie, ale również tych bardziej złożonych. Nie do końca rozumiesz? Zrozummy więc na przykładzie:

public void checkAge(int age) {
  if (age < 0) {
    throw new IllegalArgumentException(“age id invalid”);
  }
}


Ten sam program napisany z biblioteką Guavy będzie wyglądał tak:

public void checkAge(int age) {
  Preconditions.checkArgument(age > 0, “Invalid Age”);
}


Oba programy wykonują tę samą pracę, ale kod wykorzystujący bibliotekę Guavy jest czystszy. Wygląda tak, jakby niewiele się tutaj działo, jednak Guava to jeszcze inne ciekawe funkcje. Spójrzmy na jeszcze jeden przykład.

public void example() {
  // Initialising Guava LinkedHashMap Collection
  Map < String, String > myMap = Maps.newLinkedHashMap();
  myMap.put(“name”, “abc”);
  myMap.put(“rollno”, “123”);
  String delimiter = “ & ”;
  String separator = “ = ”;
  String result = Joiner.on(delimiter).withKeyValueSeperator(separator).join(myMap);
  String expected = “name = abc & rollno = 123”;
  assertThat(result, expected);
}


Z powyższego programu widać, jak łatwo można było z Guavą przekonwertować mapę na ciąg znaków. Jeśli masz jakikolwiek problem w Javie, czy to związany z cache'owaniem, współbieżnością, czy jakąkolwiek inną domeną, w większości przypadków znajdziesz rozwiązanie w bibliotece Guavy. Jeśli chcesz dowiedzieć się więcej o tej bibliotece, nie zapomnij sprawdzić ich repozytorium na GitHubie.


4) Feign

Jeśli pracujesz jako programista Javy, na pewno spotkałeś się z sytuacją, w której musisz wywołać jakiś interfejs REST API. Jest wiele klientów HTTP, takich jak OkHttpClient, które mogą służyć do wywoływania interfejsów REST API, ale zazwyczaj pojawia się tutaj potrzeba napisania sporej ilości kodu, który nie przyczynia się w ogóle do naszych potrzeb biznesowych.

Co więcej, jeśli wywołujesz wiele interfejsów API REST, Twój kod zostanie również zduplikowany. Oprócz bibliotek klientów HTTP, mamy także wrappery takie jak RestTemplate, które mogą nam bardzo ułatwić życie. Przykładowy kod napisany przy użyciu OkHttpClient będzie wyglądał tak jak poniżej.

OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://127.0.0.1/posts/1")
  .build();
Call call = okHttpClient.newCall(request);
try (Response response = call.execute(); ResponseBody body = response.body()) {

  String string = body.string();
  System.out.println(string);
} catch (IOException e) {
  throw new RuntimeException(e);
}


Zauważ, że musimy obsłużyć wątek, a także przekonwertować odpowiedź na nasze obiekty, abyśmy mogli z nich skorzystać. Czy nie wydaje Ci się, że piszemy trochę za dużo kodu dla wywołania prostego REST API? Zobaczmy więc, jak będzie wyglądał kod przy użyciu RestTemplate.

final String uri = "https://127.0.0.1/posts/1"
RestTemplate restTemplate = new RestTemplate();
PostDTO result = restTemplate.getForObject(uri, PostDTO.class);


W RestTemplate jest to dość proste, a Twoja odpowiedź także jest konwertowana do naszego obiektu, który możemy faktycznie wykorzystać. Wspaniale, prawda? Nadal jednak, jeśli wywołujemy wiele Rest API, w każdym API musimy stworzyć zmienną z URL i wywołać REST API z kodu. A nie wspomniałem jeszcze o tym, że musimy wykonać obsługę błędów. Istnieją tutaj dwa sposoby. Pierwszy to po prostu zastosowanie bloku try-catch, ale wtedy ten sam kod musi być napisany dla każdego wywołania, natomiast inną opcją jest stworzenie handlera wyjątków. Jednak w obu przypadkach musimy napisać dużo więcej kodu.

Zobaczmy teraz, jak moglibyśmy wywołać Rest API, używając Feign.

@FeignClient(name = "content-service", url = "127.0.0.1")
public interface ContentService {
  @RequestLine("GET posts/{postNumber}")
  String getDocumentByType(@Param("contentType") String postNumber);
}


Wierzcie lub nie, ale to jest to. Feign automatycznie wygeneruje kod do wywołania REST API, a my jako programiści nie będziemy musieli się już o nic martwić. Jeśli chcemy dodać więcej API, możemy użyć metody i nie będziemy musieli przepisywać kodu, aby wywołać REST API.

Brzmi ciekawie? Feign ma o wiele więcej funkcji. Możemy łatwo zmienić URL poprzez zmianę w konfiguracji. Jeśli chcesz ponowić próbę jakiegoś API w przypadku jakiegoś konkretnego błędu, Feign ułatwi Ci to zadanie. Możesz również bardzo łatwo przetestować swój kod. Więcej ciekawych funkcji Feigna znajdziesz w repozytorium na GitHubie.


5) Hibernate

Czy przypadkiem pisanie zapytań SQL w Twoim kodzie nie jest dla Ciebie uciążliwe? Czy zdarza Ci się zapomnieć o zamknięciu połączenia po wykonaniu zapytania? W takim razie ta biblioteka przypadnie Ci do gustu. Kiedy próbujesz uzyskać dostęp do bazy danych, musisz napisać dużo powtarzalnego kodu. Musisz otworzyć połączenie, uruchomić zapytanie, przekonwertować ResultSet do encji i zamknąć połączenie, a poza tym trzeba również napisać wydajne zapytania. Jeśli użyjesz Hibernate, nie będziesz musiał martwić się już o żadną z powyższych rzeczy i będziesz mógł skupić się na logice. Więcej o Hibernate dowiesz się tutaj.


Wnioski

W świecie programowania, naturalnym jest, że chcesz zminimalizować ilość powtarzalnego kodu w swojej aplikacji. Na pewno też nie chcesz zbytnio marnować czasu pisząc go coraz więcej. Wiąże się z tym tworzenie przypadków testowych w celu przetestowania każdej linii, a i tak istnieje możliwość, że zostanie wprowadzony jakiś błąd. W Javie istnieje wiele bibliotek, które pomagają poradzić sobie z powtarzalnym kodem, a niektóre biblioteki zapewniają dobrze przetestowane narzędzia, dzięki czemu nie musisz wymyślać koła na nowo.



Oryginał tekstu w języku angielskim przeczytasz tutaj.

2 komentarzy

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

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

Dowiedz się więcej