Pytania rekrutacyjne Web Developer cz. 5 - okładka

Web developer – pytania rekrutacyjne cz. 5

Ten wpis jest kontynuacją serii wpisów z pytaniami rekrutacyjnymi na stanowisko web developera. Pełną listę wpisów z tej serii znajdziesz poniżej:

Tym razem przedstawię kolejne 15 pytań wraz z omówieniem i odpowiedziami. Standardowo źródłem pytań jest aplikacja Fefaq.

1. Czym jest garbage collector?

Garbage collector jest specjalnym mechanizmem, który pozwala na “odśmiecenie pamięci”. W momencie, gdy w pamięci zalegają nieużywane obiekty do gry wkracza garbage collector, który je usuwa. Więcej o działaniu garbage collectora w JavaScript dowiesz się z pierwszego linka w źródłach (MDN).

Pytania rekrutacyjne Web Developer - event bubbling

2. Czym jest event bubbling oraz event capturing?

Oba te pojęcia służą “przekazywaniu zdarzeń”. Dla ułatwienia stwórzmy prostą strukturę HTML’ową:


<section>
      <div>
        <p>foo</p>
      </div>
</section>

Event bubbling możemy skojarzyć sobie z bąbelkami w wodzie. Bąbelki wypływają ku powierzchni i bardzo podobnie działa mechanizm event bubblingu. Zdarzenia są przekazywane od najbardziej wewnętrznego elementu do najbardziej zewnętrznego. W naszym przykładzie, dla przykładu event kliknięcia wykonany na elemencie p zostanie przekazany w następującej kolejności: p > div > section. Event bubbling możemy przerwać poprzez funkcję event.stopPropagation().

Drugim zagadnieniem jest event capturing. Tutaj sytuacja wygląda odwrotnie. W naszym przykładzie kliknięcie na element p najpierw wywoła akcje związane z elementem section, następnie div zaś na samym końcu wywoła się akcja na elemencie p. W skrócie, flow wygląda następująco: section > div > p.

3. Na czym polega technika CSS Sprites?

Technika CSS Sprites polega na połączeniu grafik używanych na stronie w jeden plik. Pozwala to na znaczne ograniczenie liczby requestów jakimi musielibyśmy bombardować serwer. Dla przykładu mając 100 grafik na stronie, to po połączeniu ich w jedną grafikę zmniejszamy liczbę requestów o 99!

Mając stworzoną mapę grafik, wystarczy, że zamiast grafik załadujemy mapę grafik jako tło i odpowiednio je wypozycjonujemy za pomocą background-position.

4. Po co robimy testy jednostkowe?

Testy tworzymy po to, aby sprawdzić jak działa napisany przez nas kod. Testy jednostkowe testują najdrobniejsze fragmenty kodu np. funkcje lub metody. Co ważne, w momencie gdy testowana metoda korzysta z jakiegoś zewnętrznego serwisu lub metod, to te dodatkowe elementy powinny zostać zmockowane. Mocki tworzymy po to, aby testować wyłącznie nasz drobny fragment kodu a nie współdziałanie ze sobą komponentów aplikacji – tym zajmują się już testy integracyjne. Testy jednostkowe znajdują się u podstawy piramidy testów, ponieważ ilościowo jest ich najwięcej. Pisanie testów jednostkowy w JavaScript ułatwiają nam między innymi: Jasmine, Jest czy Mocha.

5. Czym jest konflikt w Git i jak może zostać rozwiązany?

Konflikt w Git może zaistnieć w następującej sytuacji:

  1. Programista A tworzy branch feature i wprowadza na nim zmiany w istniejącym już wcześniej pliku.
  2. W międzyczasie programista B na branchu master wprowadza zmiany.
  3. Programista A kończy pracę na branchu feature, pushuje wprowadzone zmiany i przełącza się na mastera.
  4. Programista A chce zmerge’ować mastera z branchem feature
  5.  … i w tym momencie mamy konflikt. Programista B edytował ten sam plik, co programista A i system kontroli wersji nie wie, która wersja jest poprawna.

W tym momencie przed programistą A stoi zadanie na wybraniu poprawnej wersji. Brzmi to skomplikowanie, ale w praktyce wystarczy skasować niechciany kod a zostawić właściwy… i gotowe!

Pytania rekrutacyjne Web Developer - narzędzia

6. Jakie znasz narzędzia i mechanizmy do zapewniania jakości kodu?

Przede wszystkim należy zacząć od skonfigurowania IDE/edytora. Poprawnie skonfigurowane środowisko pracy potrafi pomóc czy podpowiedzieć naprawdę sporo. IDE potrafi nas poinformować chociażby o nadmiarowych zmiennych, czy też o nadmiernie rozbudowanych warunkach.

Kolejnym krokiem powinno być wykorzystanie linterów. Lintery pilnują nas, aby nasz code style był spójny i jednolity. Do lintera należy stworzyć config. Możemy stworzyć taki config od zera, ale możemy też skorzystać z gotowców. Przykładem takiego lintera w JavaScript jest ESLint. Po zainstalowaniu ESLinta (np. przy pomocy npm, o którym więcej dowiesz się w TYM wpisie) należy stworzyć config poleceniem eslint --init. W tym momencie zostaniemy zapytani jak chcemy stworzyć konfigurację. Możemy odpowiedzieć na kilka pytań odnośnie naszego stylu. Możemy również przeskanować pliki tak, aby konfigurator wykrył nasz code style. Trzecia możliwość to skorzystanie z gotowych konfiguracji – na przykład konfiguracja Google czy Airbnb.

Do zapewnienia jakości kodu powinniśmy również tworzyć wcześniej wspomniane testy. Dobrze napisane testy pozwolą wychwycić nieprawidłowości nie tyle syntaktyczne (o których powinno poinformować nas IDE) co semantyczne.

Kolejne dwa procesy, o które warto zadbać to refactoring i code review. Refactoring służy uproszczeniu kodu – często coś idzie zapisać w krótszy i  prostszy sposób, ale nie widzimy tego od razu. Warto po czasie wrócić do kodu i go przejrzeć. Natomiast code review polega na przejrzeniu kodu przez innego programistę po to, aby na chłodno ocenił nasz kod i zaproponował poprawki.

7. Jakie znasz metody HTTP?

Korzystając z protokołu HTTP mamy do dyspozycji następujące metody:

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD
  • CONNECT
  • OPTIONS
  • TRACE
  • PATCH

O pierwszych 4 metodach możesz dowiedzieć się więcej z mojego wpisu Wstęp do REST API, gdzie poświęciłem im dłuższą chwilę.

8. Jaka jest różnica pomiędzy SVG a Canvas?

SVG to format plików grafiki wektorowej. Otwierając plik z formatem .svg zobaczysz, że jest on zbudowany ze znaczników XML’a. Znaczniki te możemy obsługiwać za pomocą CSS’a i JavaScriptu, dzięki czemu otrzymujemy bardzo szeroki wachlarz możliwości.

Canvas natomiast jest API dostarczonym wraz z HTML5. Pozwala ono na stworzenie płótna, po którym za pomocą JavaScriptu możemy rysować. Więcej o Canvas dowiesz się z mojego artykułu Podstawy pracy z Canvas API.

9. Czym jest IIFE?

IIFE możemy rozszyfrować jako Immediately Invoked Function Expression. Jest to funkcja opakowana w dodatkowe okrągłe nawiasy, a za nimi jest dostawiona kolejna para nawiasów. Taki zabieg sprawia, że funkcja wewnątrz tych nawiasów jest wywoływana od razu, gdy wystąpi w kodzie. Poniżej przedstawiam poglądowy kod:

//tradycyjne function declaration
function foo() {
  console.log('bar');
}
foo();

//IIFE
(function() {
  console.log('baz');
})();

Pytania rekrutacyjne Web Developer - wyciek pamięci

10. Czym jest wyciek pamięci (memory leak)? Jak mu zaradzić?

Z memory leak, czyli wyciekiem pamięci mamy do czynienia w momencie, gdy programista zapomni usunąć z pamięci danych, których nie używa. Dane takie zalegają w pamięci i zwyczajnie ją zaśmiecają. W części języków programowania programista musi usunąć te dane samodzielnie, w innych natomiast działa wspomniany już wcześniej garbage collector.

11. Jak pozbyć się duplikatów z tablicy w JS?

Osobiście do głowy przyszły mi dwa rozwiązania. Pierwsza z nich to skorzystanie z obiektu Set. Cechą Seta jest właśnie to, że nie pozwala na przechowywanie zduplikowanych wartości. Dodatkowo tworząc seta wystarczy skorzystać ze spread operatora i rozwiązanie mamy prawie gotowe. Tak otrzymany Set traktujemy jeszcze raz spread operatorem i otrzymujemy tablicę bez duplikatów:

const arr = ["foo", "bar","baz", "bar", "bar", "baz"];

const noDuplicates = [...new Set([...arr])];
console.log(noDuplicates);

Drugim sposobem na jaki wpadłem jest przeiterowanie po tablicy pierwotnej i przenoszenie wartości z jednej tablicy do drugiej:


const arr = ["foo", "bar","baz", "bar", "bar", "baz"];

const noDuplicates = [];
arr.forEach(el => {
  if(noDuplicates.indexOf(el) === -1) noDuplicates.push(el);
});
console.log(noDuplicates);

W tym miejscu należy wspomnieć, że obie z tych metod zadziałają w stu procentach skutecznie jedynie w przypadku typów prostych. W typach referencyjnych porównywane są referencje a nie wartości. Dlatego też wprowadzając do tablicy dwa identyczne obiekty, po usunięciu obiektów oba te obiekty nadal tam pozostaną. Inaczej natomiast stanie się, gdy przekażemy do jednej tablicy dwa razy ten sam obiekt (zwróć uwagę na różnicę). Tutaj odwołujemy się dwukrotnie do tego samego obiektu, czyli jednego adresu w pamięci. W tym przypadku jedna z pozycji zostanie z tablicy usunięta. Dla zobrazowania pozostawiam przykład:


const obj = {a: 2};
const arr = ["foo", "bar","baz", "bar", "bar", "baz", obj, obj, {a: 1}, {a: 1}];

const noDuplicates = [...new Set([...arr])];
console.log(noDuplicates);

12. Czym jest CORS?

CORS, czyli Cross-Origin Resource Sharing to mechanizm, który pozwala na komunikację między aplikacjami zlokalizowanymi w różnych domenach. Jednym z mechanizmów bezpieczeństwa w przeglądarkach jest Same-Origin Policy. Mechanizm ten nie pozwala przykładowo na wykonwanie zapytań do API znajdującego się pod inna domeną (ale nie tylko). Mimo wszystko zdarzają się sytuacje, gdy skorzystanie z wcześniej wspomnianego już API pod zewnętrzną domeną jest konieczne. W tym miejscu wkracza właśnie CORS. W źródłach znajdziesz artykuł na Sekuraku, gdzie CORS został bardzo szczegółowo opisany. Jeśli zainteresował Cię temat CORS to jest to pozycja wręcz obowiązkowa. Link do artykułu znajdziesz TUTAJ lub na końcu artykułu w źródłach.

13. Czym jest property descriptor?

Property descriptor opisuje właściwość danego obiektu. Każda property w obiekty ma swój descriptor. Taki descriptor możemy podejrzeć za pomocą Object.getOwnPropertyDescriptor(object, 'property'). Zobaczmy jak wygląda property descriptor:


var car = {
  model: 'Golf', 
  brand: 'Volkswagen', 
  engine: '1.9TDI'
};

console.log(Object.getOwnPropertyDescriptor(car, 'engine'));

// Expected output:
//[object Object] {
//  configurable: true,
//  enumerable: true,
//  value: "1.9TDI",
//  writable: true
//}

Pojawił nam się obiekt z czterema właściwościami: configurable, enumerable, value oraz writable. Ustawienie wartości writable na false sprawi, że wartość stanie się wartością tylko do odczytu. Wartość enumerable odpowiada, za to, czy możemy iterować po danej property za pomocą np. Object.keys() czy for..in. Configurable natomiast odpowiada za to, czy możemy daną property usunąć oraz czy możemy zmieniać pozostałe deskryptory. Właściwości value myślę, żę chyba nie trzeba tumaczyć.

14. Czym jest Scrum?

Scrum to sposób pracy polegający na pracy w iteracjach, inaczej w tak zwanych sprintach. Każdy sprint powinien wnosić jakąś znaczącą wartość dodaną do projektu. Praca w Scrumie wyróżnia trzy główne role:

  • Product Owner, którego zadaniem jest dostarczenie specyfikacji i wymagań,
  • Zespół Developerski, który ma za zadanie dostarczyć produkt w oparciu o wymagania,
  • Scrum Master natomiast odpowiedzialny jest za opiekę nad zespołem developerskim oraz całym procesem scrumowym.

15. Jak połączyć kilka ostatnich N commitów w jeden?

Można to osiągnąć za pomocą polecenia git rebase -i HEAD~N, gdzie N oznacza liczbę commitów które chcemy ze sobą połączyć. Alternatywnie zamiast liczby commitów możęmy podać hash commita, do którego ma się commit (co ważne – połączenie wykona się bez tego commita, którego hash został podany!).

Źródła i materiały dodatkowe: