Pytania rekrutacyjne dla developera

Pytania rekrutacyjne developer

Jest to tekst z serii pytań i odpowiedzi na rozmowę kwalifikacyjną Developera.

Pozostałe artykuły z tej serii to SQL oraz JavaScript.

Zapraszam do dzielenia się swoimi pytaniami z rozmów kwalifikacyjnych tutaj w komentarzach lub na grupie.

Co to jest leniwe (lazy loading) i zachłanne ładowanie danych (eager loading)?

Lazy loading to wzorzec projektowy mający na celu odroczenie inicjalizacji obiektów najpóźniej jak to tylko możliwe, czyli dopiero aż będą potrzebne. Właściwie wykorzystany może przyczynić się do poprawy wydajności aplikacji. Jego przeciwieństwem jest zachłanne pobieranie danych (eager loading).

Na czym polega problem n+1 zapytań?

Jest to problem bezpośrednio związany z leniwym pobieraniem danych. Najczęściej występuje w momencie generowania różnego rodzaju list rekordów. Pierwsze zapytanie pobiera główną listę rekordów, a następnie podczas iterowania po niej, dla każdego rekordu pobierane są dane w sposób leniwy, co generuje kolejne n zapytań.

Możliwym rozwiązaniem tego problemu jest zachłanne pobieranie danych lub specjalne przygotowanie encji zawierających wszystkie potrzebne dane, by już nie było potrzeby ich dociągania.

Co to są typy proste i referencyjne?

Typy proste (prymitywne) przechowują tylko “surowe” dane, takie jak: liczby, czy znaki, mówiąc w uproszczeniu, są to konkretne dane.

Natomiast typy referencyjne przechowują swego rodzaju wskaźniki na obiekty lub wartość null.

Co to jest Autoboxing and Unboxing?

Autoboxing to automatyczna konwersja, dokonywana przez kompilator Javy między typami prymitywnymi a odpowiadającymi im klasami osłonowymi, np. zamiana typu int na Integer lub typu double na Double.

Unboxing to zamiana odwrotna, czyli z klas osłonowych do typów prostych.

Co to są obiekty immutable?

Obiekty immutable, czyli niemodyfikowalne, to obiekty, które po utworzeniu nie mogą już zmienić swojego stanu. W efekcie tego każda ich modyfikacja wiąże się z utworzeniem nowego obiektu. Najbardziej znaną klasą niemodyfikowalną jest standardowy String.

Co to jest serializacja?

Serializacja to zamiana obiektów, np. w strumień bajtów z zachowaniem ich aktualnego stanu. Serializowany obiekt może zostać zapisany np. na dysku twardym lub w bazie danych, a następnie w procesie deserializacji odtworzony do swojej pierwotnej postaci.

Co to jest refleksja?

Mechanizm refleksji polega na modyfikowaniu kodu aplikacji podczas jej działania. Dzięki refleksji można zarządzać kodem programu prawie tak łatwo, jakby to były zwykłe dane.

Czym różnią się wyjątki oznaczone (checked) od nieoznaczonych (unchecked exceptions)?

Wyjątki checked są oznaczane już w momencie kompilacji kodu. Jeżeli w jakiejś metodzie może zostać rzucony wyjątek oznaczony, taka metoda musi go przechwycić i obsłużyć lub musi jawnie zadeklarować go przy pomocy słowa kluczowego throws.

Wyjątki nieoznaczone nie są weryfikowane podczas kompilacji, dlatego nie ma konieczności ich deklarowania w definicji metody.

W Javie wszystkie wyjątki dziedziczące po klasie Error i RuntimeException są nieoznaczone, a wszystkie pozostałe dziedziczące po Throwable są oznaczone.

Co to jest enum?

Enum to typ wyliczeniowy, czyli pewna struktura danych zawierająca listę wszystkich wartości, jakie może przyjąć ten typ. Typy wyliczeniowe wykorzystywane są bardzo często jako swego rodzaju stałe.

W powyższym przykładzie zmienna enumType może przyjąć tylko 3 wartości: EnumType.T1, EnumType.T2 lub EnumType.T3.

Czy klasa może dziedziczyć po kilku interfejsach?

Java z zasady nie wspiera wielodziedziczenia (jako wyjątek można uznać interfejsy z default methods). Jedna klasa może dziedziczyć tylko po jednej klasie rodzica.

Klasy nie dziedziczą po interfejsach, a je implementują. Jedna klasa może implementować wiele interfejsów.

Jeden interfejs może dziedziczyć po kilku innych.

Jak pobrać pojedynczy znak z obiektu String?

Do pobrania jednego znaku ze stringa służy metoda charAt.

Jak wywołać metodę w klasie podrzędnej z klasy nadrzędnej?

Do wywoływania metod z klasy rodzice służy słowo kluczowe: super.

Podobnie jak metodę można wywołać również konstruktor. W tym wypadku jednak nie podajemy nazwy konstruktora, a samo słowo: super.

Na czym polega kontrakt między metodami hashCode i equals?

Dla metod zdefiniowano założenia, których przestrzeganie gwarantuje poprawne działanie obiektów np. z wykorzystaniem kolekcji (java.util.List, java.util.Map itp).

  1. Kolejne wywołania hashCode muszą zwracać ten sam wynik.
  2. Jeżeli obiekty są równe, wg metody equals, ich hashCode również musi być równy.
  3. Jeżeli obiekty są różne, to ich hashCode może być równy.
  4. Relacja wyznaczona metodą equals musi być zwrotna.
  5. Relacja wyznaczona metodą equals musi być symetryczna.
  6. Relacja wyznaczona metodą equals musi być przechodnia.
  7. Relacja wyznaczona metodą equals musi być spójna.
  8. Każdy obiekt jest różny od null, czyli wywołanie x.equals(null) dla obiektu x różnego od null, zawsze musi zwrócić false.

Więcej na temat tych metod oraz szczegółowe wyjaśnienie zawartego między nimi kontraktu można przeczytać w artykule o hashCode i equals.

Czym się różni lista (List) od zbioru (Set)?

Lista (java.util.List) reprezentuje uporządkowaną listę elementów i może zawierać duplikaty. Dodatkowo przechowuje kolejność dodawania danych.

Zbiór (java.util.Set) reprezentuje zbiór unikatowych elementów, natomiast przechowywana kolejność jest zależna od konkretnej implementacji zbioru.

Na czym polega mechanizm konkatenacji stringa?

Konkatenacja stringów to po prostu łączenie ich ze sobą.

Więcej na temat samej konkatenacji stringów oraz klasy StringBuilder, poprawiającej wydajność konkatenacji można przeczytać w podlinkowanych artykułach.

Co to jest rekurencja?

Rekurencja (rekursja) polega na odwoływaniu się funkcji do siebie samej.

W powyższym przykładzie metoda rekurencyjna zostanie wywołana 5 razy. Najpierw metoda sprawdza, czy argument wejściowy jest większy od zera, a następnie go wyświetla i wywołuje samą siebie z argumentem mniejszym o 1.

Korzystając z rekurencji należy uważać, by warunek kończący jej wykonanie był dobrze zdefiniowany, ponieważ możemy doprowadzić do zapętlenia się wywołań.

O czym mówią zasady SOLID?

SOLID jest to mnemonik opisujący pięć podstawowych założeń programowania obiektowego.

Single responsibility principle (Zasada jednej odpowiedzialności)

Dana klasa powinna mieć tylko jedną odpowiedzialność.

Open/closed principle (Zasada otwarte-zamknięte)

Zmiana wymagań powinna skutkować dodaniem nowego kodu rozszerzającego poprzedni, a nie modyfikacją działającego już kodu.

Liskov substitution principle (Zasada podstawienia Liskov)

Funkcje przyjmujące jako argument klasy bazowe powinny być w stanie obsłużyć również obiekty klas pochodnych.

Interface segregation principle (Zasada segregacji interfejsów)

Lepiej przygotować kilka specyficznych, dedykowanych interfejsów, niż jeden zbiorczy.

Dependency inversion principle (Zasada odwrócenia zależności)

Moduły wyższego poziomu nie powinny być zależne od tych z niższego poziomu.

Co to jest mock?

Mock  to swego rodzaju atrapa obiektu, wykorzystywana do symulowania zachowania rzeczywistego obiektu.

Mocki wykorzystywane są zazwyczaj podczas testów. Przy ich pomocy można zasymulować konkretny przypadek testowy.

Co to jest ciągła integracja (Continuous Integration)?

Ciągła integracja polega na rozwijaniu oprogramowania z częstym i regularnym dołączaniem bieżących zmian do głównego kodu aplikacji. Dzięki wykorzystaniu ciągłej integracji zmniejsza się koszty i potencjalne ryzyko łączenia prac wykonywanych przez różne osoby. Przekłada się to również na wcześniejsze wykrycie potencjalnych błędów.

Co to jest TDD?

TDD, czyli Test-driven development to technika tworzenia oprogramowania oparta o testy. Metodyka ta polega na wielokrotnym powtarzaniu poniższych kroków:

  1. Przygotowanie automatycznego testu sprawdzającego daną funkcjonalność. Ponieważ funkcjonalność jeszcze nie istnieje, test nie powinien się powieść.
  2. Podstawowa implementacja funkcjonalności, tak by spełnić warunki założone w teście.
  3. Refaktoryzacja kodu, żeby spełniał oczekiwane standardy z jednoczesną weryfikacją, czy warunki testowe są dalej spełnione.

Powyższe trzy kroki często nazywane są również: red, green, refactor.

Jakie znasz poziomy testów?

Testy jednostkowe

Weryfikacja poprawności działania pojedynczego elementu aplikacji. Do testów jednostkowych można wykorzystać np. bibliotekę JUnit.

Testy integracyjne

Weryfikacja działania połączonych elementów aplikacji.

Testy akceptacyjne

Celem testów akceptacyjnych nie jest już wykrycie błędów, a jedynie potwierdzenie jakości oprogramowania. Tego rodzaju testy są bardzo często wykonywane z udziałem klienta odbierającego produkt.

Jakie znasz wzorce projektowe?

Pytanie o wzorce projektowe pada bardzo często, dlatego warto nauczyć się przynajmniej kilku podstawowych wzorców:

Wzorce kreacyjne

  • budowniczy
  • fabryka
  • singleton

Wzorce strukturalne

  • adapter
  • dekorator
  • fasada

Wzorce czynnościowe

  • łańcuch odpowiedzialności
  • iterator
  • strategia
  • obserwator

Co to jest wątek (thread)?

Wątek pozwala uruchomić fragmenty kodu aplikacji współbieżnie. Dzięki wątkom można np. część operacji wykonywać asynchronicznie, nie blokując głównego przepływu aplikacji lub skończyć pracę szybciej, wykorzystując kilka wątków jednocześnie.

Powyższy fragment kodu demonstruje proste wykorzystanie wątków w Javie. Metoda run zawiera fragment logiki wykonywany w osobnym wątków, natomiast metoda start rozpoczyna działanie tego wątku.

Zadania praktyczne

  • Napisz kod, który wypisze 10 pierwszych liczb ciągu fibonacciego.
  • Napisz program, który wypisze liczby od 1 do 100. Dodatkowo dla wielokrotności trójki wyświetli  ‘A’ zamiast liczby, dla wielokrotności piątki wyświetli ‘B’, a dla liczb będących wielokrotnością trójki i piątki wyświetli ‘AB’.
  • Zadania w stylu „czy program się skompiluje”.
  • Zadania w stylu “co wyświetli dany program”.

Programista – Pytania rekrutacyjne

Lista pytań rekrutacyjnych, które pozwolą przygotować Ci się na rozmowę kwalifikacyjną.

4 komentarze
Share:

4 Comments

  1. kszych says:

    Set gwarantuje lub nie gwarantuje zachowania kolejności w zależności od implementacji, więc jest to półprawda. Na przykład HashSet vs LinkedHashSet.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *