Jak zatrudnić programistów Angular: kluczowe umiejętności i wiedza, których należy szukać

Opublikowany: 2022-09-14

Dzięki wysoce skalowalnej architekturze wiele zespołów programistów internetowych wybiera Angular do tworzenia wydajnych, wyrafinowanych aplikacji jednostronicowych. Ale zatrudnianie programistów Angulara jest łatwiejsze do powiedzenia niż do zrobienia. Chociaż istnieje wielu kandydatów, kluczem do bezproblemowego programowania jest znalezienie świetnego programisty Angular, takiego, który stosuje najlepsze praktyki i zaawansowane techniki, aby spełnić wysokie standardy kodowania.

Zrozumienie kluczowych pojęć związanych z popularnym front-endowym frameworkiem Google przygotuje Cię do prowadzenia rozmów z potencjalnymi klientami i zatrudniania najlepszych programistów — tych, którzy starają się przenieść bazę kodu na wyższy poziom. W tym artykule przedstawiono kluczowe umiejętności i wiedzę, które powinien posiadać profesjonalny specjalista Angular.

TL; DR

Wysokiej jakości kandydaci Angular to ci, którzy:

  • Poznaj podstawowe funkcje Angulara.
  • Projektuj zanim zaczną kodować.
  • Zapoznaj się z cyklami życia aplikacji Angular.
  • Posiadają solidną wiedzę z zakresu programowania reaktywnego.
  • Dowiedz się, czym jest stan i jak z niego korzystać.
  • Są wykwalifikowani i wspierają testy automatyczne.
  • Bądź na bieżąco z najnowszymi wydaniami Angulara.

Uwaga: Ten przewodnik dotyczy najnowszych wersji Angular, które nie są już znane jako AngularJS — „Angular” ma zastosowanie od Angular 2. Jeśli zatrudniasz do utrzymania lub aktualizacji starszego projektu aplikacji internetowej AngularJS (1.x oddział), sprawdź Jak zatrudnić świetnego programistę AngularJS.

Poznaj podstawowe funkcje Angular

Struktura Angular działa na TypeScript , a cały kod napisany w aplikacji jest transpilowany do JavaScript. TypeScript to nadzbiór JavaScript, który kompiluje się do zwykłego JavaScript. Kod kątowy jest reprezentowany przez ten nadzbiór.

Wielu programistów uczy się Angulara, ale brakuje im dobrego zrozumienia podstawowych pojęć wymaganych przez JavaScript, TypeScript, HTML lub CSS. Jeśli tych podstaw brakuje, programiści mają skłonność do stosowania nieodpowiednich obejść i w ten sposób pomnażają dług techniczny projektu.

Zapytaj więc kandydata, czy ma wiedzę na temat HTML5 i CSS3. Dobry programista Angular nie musi być ekspertem od HTML lub CSS, tak długo jak ktoś inny w zespole jest, ale powinien rozumieć te kluczowe pojęcia:

  • Flexbox
  • Zmienne SCSS
  • Różnica między span a div
  • Ważne klasy w CSS
  • Atrybuty

Programiści Angular powinni dobrze rozumieć JavaScript i TypeScript, a także pewne umiejętności w zakresie HTML i CSS.

Ćwierkać

Projekt przed kodowaniem

Dobry projekt to klucz do dobrej architektury aplikacji. Zapytaj swojego kandydata, w jaki sposób tworzy swoje projekty i porównaj swoje myślenie z tymi idealnymi rozważaniami:

  • Gdzie pójdzie kod? Czy potrzebna jest nowa biblioteka lub moduł?
  • Jakie są wejścia i wyjścia?
  • Czy powinny istnieć jakieś komponenty lub dyrektywy wielokrotnego użytku?
  • Dokąd pójdzie państwo? (Omówiono dalej w sekcji Zarządzanie stanem poniżej.)
  • Dokąd pójdzie logika biznesowa — tj. w jakiej usłudze?
  • Czy pewne komponenty mogą być współużytkowane przez biblioteki, aby stworzyć system projektowania interfejsu użytkownika?

Pełna specyfika konkretnego projektu jest mniej ważna niż to, czy kandydat ma zwyczaj tworzenia projektów. Wszystkie projekty są tymczasowe, więc w przypadku większości zastosowań dokumentacja może być tak prosta, jak zdjęcie szkicu na tablicy, chyba że wymagana jest formalna dokumentacja. Na późniejszym etapie programista może wygenerować projekt techniczny z kodu (za pomocą odpowiednich narzędzi), aby wyjaśnić, w jaki sposób wszystkie części są ze sobą powiązane.

Zrozumienie cykli życia aplikacji Angular

Zapytaj swojego kandydata, co wie o cyklu życia komponentu kątowego . Ich odpowiedź powinna zawierać trzy haki cyklu życia: ngOnInit , ngOnChanges i ngOnDestroy . Jak sugerują nazwy, ngOnInit jest wywoływane podczas inicjalizacji komponentu, ngOnDestroy jest wywoływane, gdy komponent jest zniszczony, a ngOnChanges jest wywoływane, gdy zmienia się atrybut. To ostatnie może wystąpić przed ngOnInit — gdy atrybut jest już przypisany przed całkowitym zainicjowaniem składnika, wówczas ngOnChanges jest wykonywane przed ngOnInit .

Jeśli kandydat wie również o ngDoCheck , ngAfterContentInit , ngAfterContentChecked , ngAfterViewInit i ngAfterViewChecked , zna wszystkie haki wykrywania zmian dla składników i jest o krok do przodu.

Dobre pytanie uzupełniające, które należy zadać w związku z każdym z zaczepów: „Kiedy następuje wykrycie zmiany?”

Po lewej stronie pojawi się pięć pudełek ze strzałkami skierowanymi w dół. Wszystkie są zielone z wyjątkiem czwartego, które jest niebieskie i ma nawias rozszerzający się na pięć kolejnych pól skierowanych w dół, które pojawiają się po prawej stronie (pierwszy jest biały, a pozostałe są niebieskie). Od góry do dołu, lewe pola brzmią: „constructor, ngOnChanges, ngOnInit, ngDoCheck i ngOnDestroy”. Strzałka od „Konstruktor” do „ngOnChanges” jest oznaczona „Komponent ma powiązane dane wejściowe”, a istnieje dodatkowa strzałka wskazująca od „Konstruktor” do „ngOnInit” z etykietą „Komponent nie ma powiązanych danych wejściowych”. Strzałka od „ngOnChanges” do „ngOnInit” jest oznaczona jako „Pierwsze uruchomienie” i istnieje dodatkowa strzałka wskazująca od „ngOnChanges” do „ngDoCheck” z etykietą „Nie pierwsze uruchomienie”. W lewym górnym rogu elementu „ngOnChanges” pojawia się białe pole z tekstem „1+ zmiana właściwości wejściowych powiązanych z danymi” i wskazuje na niego. Prawe pola, od góry do dołu, brzmią: „Wywołano po raz pierwszy?, ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit i ngAfterViewChecked”. Strzałka z „Pierwszy raz wywołany?” do „ngAfterContentInit” jest oznaczone „Tak” i jest dodatkowa strzałka wskazująca od „Pierwsze połączenie?” do „ngAfterContentChecked” oznaczonej „Nie”. Strzałka od „ngAfterContentChecked” do „ngAfterViewInit” jest oznaczona jako „Pierwszy raz wywołana”, a dodatkowa strzałka wskazuje od „ngAfterContentChecked” do „ngAfterViewChecked” z etykietą „Nie wywołane po raz pierwszy”.
Przegląd cykli życia komponentów Angular.

Mniej znanym cyklem życia jest cykl życia dostawcy , który ma tylko jeden haczyk: ngOnDestroy . Jest to wywoływane tylko wtedy, gdy dostawca jest dołączony na poziomie komponentu, w którym to przypadku zostaje zniszczony wraz z komponentem. Jeśli zostanie dostarczony na poziomie roota lub modułu, nigdy nie zostanie zniszczony.

Konstruktor dostawcy zostanie wykonany przy pierwszym użyciu dostawcy, więc możliwe jest, że konstruktor nigdy nie zostanie wykonany. Przetestuj swojego kandydata na temat tej możliwości — w rzeczywistych scenariuszach może to być często pomijane źródło błędów!

Solidna wiedza na temat programowania reaktywnego

W aplikacji Angular programowanie reaktywne jest często najtrudniejsze do zrozumienia. Wiele osób zaczyna programować fragment kodu, myśląc w sposób proceduralny, zakładając, że jest on łatwiejszy do zrozumienia i pracy z nim, podobnie jak kroki przepisu.

Programowanie reaktywne polega na reagowaniu na rzeczy, których nie możemy kontrolować, a które mogą wystąpić w nieprzewidywalnej kolejności. Chociaż codziennie reagujemy na rzeczy w ten sposób — na przykład hamowanie, gdy samochód przed nami nagle się zatrzymuje — wielu programistom trudno jest reaktywne podejście do programowania.

Ale wszystko, co dzieje się w aplikacji Angular, opiera się na programowaniu reaktywnym. Niektóre przykłady reaktywności w aplikacji zakupowej Angular mogą obejmować na przykład:

  • Gdy użytkownik się zaloguje, liczba na ikonie koszyka na zakupy zostanie zaktualizowana, a pozycje menu zmienią się na bardziej szczegółowe opcje.
  • Gdy użytkownik przechodzi do kategorii, produkty aktualizują się w zależności od wybranej kategorii.
  • Gdy użytkownik dodaje produkt do koszyka, ikona koszyka aktualizuje się wraz z liczbą produktów.
  • Gdy element jest niedostępny (zarejestrowany za pomocą detektora monitorującego bieżące ilości zapasów z zaplecza), interfejs użytkownika strony aktualizuje się.

Pamiętaj, że te rzeczy dzieją się automatycznie i nie wymagają odświeżania strony, aby się pojawiły. Podczas rozmowy poproś kandydata o opisanie, w jaki sposób zastosował programowanie reaktywne w opracowanej przez siebie aplikacji. Jeśli kandydat opisuje rozwiązania, które wymagają odświeżenia strony lub ręcznego wywołania ChangeDetectorRef.detectChanges() w celu odświeżenia komponentu, należy wziąć pod uwagę żółtą flagę.

Pułapki z obserwowalnymi w Angular

Mniej doświadczeni programiści mogą czasami stwierdzić, że kod, który piszą w swoich aplikacjach Angular, nie jest wykonywany. Doświadczeni programiści Angular mogą zidentyfikować częstą przyczynę: nie ma subskrypcji na Observable , głównym typie obiektu w programowaniu reaktywnym. Tylko z abonamentem będą wykonywane połączenia back-end lub inne reakcje.

Istnieją dwa sposoby tworzenia subskrypcji: Deweloperzy mogą używać potoku async lub metody subscribe . Ale jest zastrzeżenie: jeśli programiści dokonają ręcznej subskrypcji (za pomocą metody subscribe ), Observable będzie musiał zostać zniszczony ręcznie (chociaż są pewne skrajne przypadki, w których dzieje się to domyślnie). Deweloperzy mogą niszczyć Observables na wiele sposobów:

  • Jeśli to możliwe, użyj potoku async (niszczy to Observable , gdy komponent nie jest już potrzebny).
  • Ręczne anulowanie subskrypcji przy użyciu metody unsubscribe na Observable pod koniec okresu istnienia składnika ( ngOnDestroy ).
  • W bardziej deklaratywny sposób z operatorem takeUntil wewnątrz operatora pipe i używając podmiotu (tj. czegoś o nazwie destroy$ ). W tym przypadku podmiot emituje destroy$.next() pod koniec okresu istnienia komponentu ( ngOnDestroy ). Po odebraniu zdarzenia zniszczenia operator takeUntil nie będzie już akceptować zdarzeń z Observable, z którymi jest powiązany, aby jego logika subskrybenta nie była już wyzwalana. Aby zapoznać się z przykładem, zobacz operator takeUntil w sekcji 2. Podobną funkcjonalność można uzyskać za pomocą operatorów take i takeWhile .
  • Ponieważ aplikacje Angular przeszły na kompilator Ivy, możemy również używać adnotacji. Biblioteka until-destroy lub inna biblioteka innej firmy, taka jak SubSink, może być używana do płynnego anulowania subskrypcji elementów obserwowalnych po zniszczeniu komponentu.

Innym potencjalnym problemem związanym z programowaniem reaktywnym są wycieki pamięci i wielokrotne wywołania zaplecza. Zapytaj kandydata, czy zdaje sobie sprawę z tych problemów i jak normalnie by je rozwiązał. Wycieki pamięci mogą wystąpić w przypadku braku rezygnacji z subskrypcji Observable s, jak opisano powyżej. Wiele połączeń do zaplecza z powodu wielu subskrypcji na połączenie zaplecza można rozwiązać, udostępniając Observable .

Poznaj stan i jak go używać

Wszystkie aplikacje jednostronicowe mają stan, który jest dostępny gdzieś w interfejsie użytkownika. Ale czym właściwie jest stan? Zawiera wszystkie zmienne specyficzne dla bieżącego doświadczenia użytkownika. Na przykład dane uwierzytelnionego użytkownika, takie jak nazwa i adres URL obrazu profilu, wybrany element menu lub lista ekranowa, taka jak lista elementów koszyka.

W aplikacji Angular należy wziąć pod uwagę trzy główne typy stanu frontonu:

Państwo Zakres
Aplikacja Ogólne informacje dostępne dla całej aplikacji, takie jak uwierzytelnieni użytkownicy, role użytkowników, pozycje menu lub koszyk zakupów użytkownika. Wszystko, co zmieni się w tym stanie, zmieni się dla całej aplikacji.
Moduł Informacje dostępne dla całego modułu, w którym używana jest usługa. Za każdym razem, gdy programista ponownie używa modułu z dostawcami, tworzy nowe wystąpienie każdego dostawcy. Stan nigdy nie zostanie zniszczony i zostanie utworzony dopiero przy pierwszym użyciu danego dostawcy.
Składnik Informacje dostępne dla określonego komponentu. Komponenty to najmniejsze części aplikacji. Aplikacja Angular może mieć wiele stanów składników, ale będą one dostępne tylko za pośrednictwem każdego składnika. Stan zostanie utworzony, gdy komponent zostanie utworzony, a zniszczony, gdy komponent zostanie zniszczony.

Dobre zrozumienie, czym jest stan i kiedy należy go wczytać lub przeładować, jest jedną z kluczowych umiejętności, których należy szukać przy zatrudnianiu programistów Angulara. Jest to główny obszar do zbadania, czy Twój zespół ma możliwość przejrzenia przykładowego kodu napisanego przez kandydata. Jeśli wnioskodawca korzysta z biblioteki do zarządzania państwowego:

  • Poszukaj użycia bibliotek NgRx, Akita, NgX lub podobnych bibliotek specyficznych dla zarządzania stanem.
  • Następnie sprawdź, czy w powiązanym kodzie znajdują się powiadomienia dotyczące effects , action , reducer , store i selector .

Spójrzmy na ogólny przepływ stanu aplikacji w NgRx (który jest podobny do Akita i innych bibliotek) jako przykład:

Białe pole „Selector” w lewym górnym rogu wskazuje na zielone pole „Component” w lewym dolnym rogu, które w prawo wskazuje na białe, warstwowe pole „Action”. Pole „Akcja” wskazuje białe, warstwowe pole „Reduktor” i prawe (z kropkowaną strzałką) białe, warstwowe pole „Efekty”. Pole „Reducer” wskazuje na niebieskie pole „Store”, które wskazuje na lewo do pola „Selector”. W prawym dolnym rogu pole „Efekty” wskazuje w lewo (z kropkowaną strzałką) pole „Działanie” i aż do zielonego pola „Usługa”. Pole „Serwis” wskazuje na pole „Efekty” i na zielony stos butli. Zielony stos butli wskazuje pole „Serwis”.

Jeśli deweloper tworzy własne państwo z usługami, jego kompetencje w zarządzaniu państwem mogą być trudniejsze do zidentyfikowania:

  • Szukaj odniesień do słów state lub effect .
  • Sprawdź, czy kod reaguje na jakąś akcję, np. jeśli użytkownik naciśnie przycisk A, tekst powinien się zmienić na ekranie B.

Pytania, które ankieterzy powinni zadać na temat stanu

Nie zawsze możesz dowiedzieć się wszystkiego, co musisz wiedzieć, sprawdzając kod kandydata. Dodaj te zapytania do swojej listy pytań, aby sprawdzić, jak dobrze potencjalni programiści Angular rozumieją stan:

  • Gdzie użyłeś state — i jak? Jest to solidny punkt wyjścia do zrozumienia ich doświadczenia ze stanem; nie bój się dociekać konkretów.
  • Jak podejmujesz decyzję o skorzystaniu z biblioteki? To dobry znak, jeśli wiedzą, że nie zawsze jest przydatne dołączanie biblioteki stanowej do aplikacji.
  • Co byś umieścił w państwie, gdzie byś to umieścił i jak wykorzystujesz system zarządzania państwem? Jeśli powiedzą: „Wprowadzam wszystko w mój globalny stan aplikacji”, jest to pewny znak, że programista nie jest świadomy negatywnych skutków ubocznych, jakie taki system może wywołać w aplikacji.

Deweloperzy, którzy rozumieją różne typy stanów, unikną tych skutków ubocznych:

  • Stan, który dotyczy tylko jednego składnika, może zostać zmodyfikowany lub uszkodzony przez inne składniki.
  • Dane są zagnieżdżone w sklepie, więc ich śledzenie staje się trudne, a dane stają się nieczytelne dla człowieka (na potrzeby debugowania, wymiany danych itp.).
  • Edytowanie danych w formularzu już emituje je do reszty aplikacji, podczas gdy dane powinny być wypychane do sklepu tylko podczas zapisywania danych — innymi słowy, reszta aplikacji może zużywać nieprawidłowe dane.

Nie trwa długo, zanim globalny sklep stanie się nieuporządkowanym bałaganem i nie jest jasne, skąd pochodzi każda część bałaganu, co utrudnia debugowanie i utrzymanie.

Zrozumienie znaczenia testów automatycznych

Testowanie automatyczne powinno być uważane za równie ważne jak jakość kodu dla każdej aplikacji internetowej Angulara. Jednym z głównych powodów, dla których programiści piszą testy, jest dokumentowanie ich kodu: jeśli nowy programista dołącza do firmy, logika biznesowa i pewne przepływy interfejsu użytkownika powinny być jasne w oparciu o oczekiwania zestawu testów. Ponadto automatyczne testowanie ujawnia błędy na wczesnym etapie rozwoju.

Zadaj potencjalnemu programiście Angular trzy pytania testowe:

  • Jakie są twoje przemyślenia na temat testowania? Każdy kandydat, któremu nie zależy na automatycznym testowaniu, powinien przestać być brany pod uwagę. Nawet jeśli wolą nie używać programowania opartego na testach (TDD), programiści, którzy nie dostrzegają wartości testów automatycznych, będą kosztować Twoją firmę czas na ręczne testowanie i, co gorsza, przestoje użytkowników końcowych, gdy regresje pojawią się podczas wprowadzania zmian w aplikacji nadgodziny.
  • Na czym się skupiasz podczas testowania? Zamiast testować podstawowe dane, takie jak możliwość przypisania wartości do pola lub dążenie do określonych metryk pokrycia testów (tj. pokrycia 85%), świetny programista Angular powinien skupić się na testowaniu podstawowej logiki biznesowej.
  • Czy zazwyczaj jest więcej testów E2E czy więcej testów jednostkowych? Czemu? Jako aplikacje front-endowe aplikacje Angular mogą wykorzystywać dwa główne rodzaje testów automatycznych: testy jednostkowe i testy end-to-end (E2E). Zazwyczaj zestaw testów zawiera wiele testów jednostkowych i mniej testów E2E. Testy jednostkowe są małe, dzięki czemu można je szybko napisać i wykonać. Testy E2E są większe i wolniejsze. Uczciwe ostrzeżenie: nie wszyscy programiści będą mieli takie samo zdanie co do prawidłowego stosunku testów jednostkowych i E2E do utrzymania. W rzeczywistości zależy to od złożoności testowanej aplikacji, a nawet wtedy odpowiedź jest do pewnego stopnia dyskusyjna.

Schemat blokowy zaczyna się w lewym górnym rogu z podzielonym jasnoniebieskim i zielonym polem. Jasnoniebieska część zawiera tekst „Jakie są twoje przemyślenia na temat testowania?” a w zielonej części znajduje się tekst „Czy kandydatowi zależy na automatycznym testowaniu?” Od zielonej części strzałka „Nie” wskazuje w prawo do ciemnoniebieskiego pola z napisem „Kandydat nie ma odpowiednich umiejętności testowania”, a strzałka „Tak” wskazuje w dół do innego podzielonego pola. Jasnoniebieska część drugiego pola zawiera tekst „Na czym się skupiasz podczas testowania?” a zielona część zawiera tekst „Czy kandydat koncentruje się na testowaniu kluczowej logiki biznesowej (wykraczając poza procent pokrycia kodu)?” Od zielonej części strzałka „Nie” wskazuje w prawo do ciemnoniebieskiego pola z napisem „Kandydat może nie mieć odpowiednich umiejętności testowania”, a strzałka „Tak” wskazuje w dół do innego podzielonego pola. Jasnoniebieska część trzeciego pola zawiera tekst „Czy zazwyczaj jest więcej testów E2E czy więcej testów jednostkowych? Dlaczego?” a zielona część zawiera tekst „Czy kandydat rozumie znaczenie i cel zarówno testowania jednostkowego, jak i kompleksowego?” Od zielonej części strzałka „Nie” wskazuje w górę i w prawo do ciemnoniebieskiego pola z napisem „Kandydat może nie mieć odpowiednich umiejętności testowania”, a strzałka „Tak” wskazuje w prawo do ciemnoniebieskiego pola z napisem „Kandydat ma odpowiednie testy umiejętności."
Przewodnik po testowaniu pytań do rozmowy kwalifikacyjnej dla programistów Angular.

Ramy testowania Angular

Programiści Angular mają wybór, jeśli chodzi o zautomatyzowane frameworki testowe. Testy jednostkowe mogą być wykonywane przez Jest lub Jasmine i Karma. Każdy programista Angulara powinien znać Jasmine i Karmę. Jest również powszechny — jest na ogół szybszy i oferuje bardziej zaawansowane opcje testowania.

Standardem testowania E2E dla aplikacji Angular jest Protractor, domyślne narzędzie generowane przez Angular CLI. Alternatywą jest Cypress, obiecująca platforma testowa E2E z wieloma opcjami.

Upewnij się, że kandydat posiada dogłębną wiedzę na temat co najmniej jednego frameworka testów jednostkowych i jednego frameworka testowego E2E.

Bądź na bieżąco z najnowszymi wydaniami Angular

Wielcy programiści Angulara mogą nie zawsze korzystać z najnowszej wersji w fazie rozwoju z różnych powodów, ale powinni znać harmonogram wydań Angulara, aby być na bieżąco ze zmianami i być przygotowanym na zmianę. Jednym ze sposobów oceny tego jest zapytanie kandydata, czy zna strategię wydawania Angulara. Angular dąży do wydania głównego co sześć miesięcy, zwykle około lutego i maja. Wersja Angulara jest objęta „aktywnym wsparciem” w ciągu pierwszych sześciu miesięcy od daty wydania i jest objęta „wsparciem długoterminowym” przez 12 miesięcy od daty wydania. Jest to dość napięty harmonogram w porównaniu z niektórymi innymi technologiami, dlatego szczególnie ważne jest, aby być na bieżąco.

Możesz również przeprowadzić rozeznanie na temat najnowszej wersji Angulara i zapytać kandydata o korzyści płynące z tych nowych funkcji. Na przykład mniej więcej w czasie, gdy Angular 14 został wydany, mogłeś zapytać kandydata o:

  • Samodzielne komponenty, które zmniejszają zapotrzebowanie na moduły Angular. Samodzielne komponenty nie są deklarowane w żadnym istniejącym NgModule i bezpośrednio zarządzają własnymi zależnościami. W rezultacie można na nich bezpośrednio polegać bez potrzeby pośredniego NgModule .
  • Wpisane formularze, kolejna ważna aktualizacja w Angular 14, która ustawia ścisłe pisanie jako domyślne dla Angular Reactive Forms. Wpisane formularze zapewniają, że wartości wewnątrz FormControls , FormGroups i FormArrays są bezpieczne pod względem typu na całej powierzchni interfejsu API. Umożliwia to bezpieczniejsze formularze, zwłaszcza w przypadku głęboko zagnieżdżonych złożonych przypadków.

Następny świetny programista Angular dla Twojego zespołu front-end

Każdy projekt i zespół do tworzenia stron internetowych jest inny i przyłoży inną wagę do różnych aspektów umiejętności i wiedzy programisty Angulara. Jednak zrozumienie podstawowych tematów, które tu przedstawiliśmy, pozwoli menedżerom ds. rekrutacji na znaczący udział w rekrutacji — nawet w bardziej technicznych ocenach.

Blog Toptal Engineering wyraża wdzięczność Ramazanowi Yildizowi za zapoznanie się z koncepcjami technicznymi i diagramami przedstawionymi w tym artykule.