CODEBILITY

Blog o tematyce IT

Pytania rekrutacyjne #1 – .NET Developer

pytania rekrutacyjne na stanowisko .net developer

Cześć! To już drugi artykuł z serii “Od zera do developera“. Aby przejść tę drogę należy nie tylko umieć zamienić nasze myśli na działający kod ale przede wszystkim posiadać wiedzę na temat języków, technologii i frameworków w jakich przyjdzie Ci pracować. Nieważne czy jesteś studentem czy nie, czy doświadczonym developerem, a może jesteś już po stażu, udając się na rozmowę kwalifikacyjną na pewno będzie przed Tobą czekać rozmowa z osobą techniczną, która po pierwsze sprawdzi Twoje umiejętności techniczne jak i wiedzę, ale też prześwietli pod kątem umiejętności pracy w zespole czy pod kątem konkretnego projektu, do którego możesz zostać przypisany. Najczęściej na takiej rozmowie padają pytania rekrutacyjne stricte teoretyczne, ale też należy spodziewać się testów i zadań praktycznych.

Z doświadczenia wiem, że jest jeszcze ogromna liczba programistów, którzy pomimo dużego, kilkuletniego doświadczenia nie zaznajomili się z podstawami programowania i języka. Z tego powodu zdecydowałem się podzielić z Tobą garstką pytań rekrutacyjnych, które z dużym prawdopodobieństwem mogą paść na rozmowie kwalifikacyjnej. Oto pierwsza część pytań, z którymi można najczęściej się spotkać:

Pytania rekrutacyjne na stanowisko .NET Developer:

1. const vs. readonly

Często padające pytanie, a odpowiedź jest bardzo prosta. Pierwszą różnicą jest to, że const deklaruje stałą, której wartość ustawiana jest podczas kompilacji, natomiast wartość readonly ustawiana jest w momencie wykonywania programu.

Drugą różnicą jest to, że razem z const nie możemy użyć słowa kluczowego static, natomiast readonly daje nam taką możliwość.

Trzeciar różnica jest taka, że wartość można ustawiać wyłącznie w momencie deklaracji. Readonly pozwala na przypisanie wartości zarówno podczas deklaracji jak i w konstruktorze. Możliwe też jest zmiana tego pola za pomocą refleksji. Więcej o tym tutaj.

 

2. boxing vs. unboxing

Boxing to proces konwersji typu wartościowego na typ referencyjny. Jak łatwo się domyślić, unboxing to proces odwrotny, czyli konwersji typu referencyjnego na wartościowy.

 

3. interfejs vs. klasa abstrakcyjna

Wszystkie elementy z interfejsu muszą być zaimplementowane. Klasa abstrakcyjna może dać częściową lub całkowitą implementację z funkcjonalnością oraz abstrakcyjne metody i właściwości, które będą musiały zostać określone w klasie dziedziczącej. Klasa abstrakcyjna i interfejs nie może zostać utworzony.

Można dziedziczyć po jednej klasie ale po wielu interfejsach.

Nowością w C# 8.0 jest to, że interfejs może posiadać implementację. Więcej można znaleźć tutaj.

 

4. Modyfikatory dostępu

public -Brak ograniczeń. Wszystkie składowe oznaczone tym modyfikatorem dostępne są poza nasza klasą.

private – Składowe oznaczone tym modyfikatorem dostępne są jedynie wewnątrz klasy.

protected – Składowe oznaczone tym modyfikatorem dostępne są jedynie wewnątrz klasy oraz klas dziedziczących po niej.

internal – Składowe oznaczone tym modyfikatorem dostępne są dla klas znajdujących się w tym samym pakiecie.

protected internal – Klasa nie może być jednocześnie protected i internal, dlatego odpowiedni modyfikator dobierany jest w zależności od użycia. Dla klas dziedziczących użyty będzie protected, dla klas niedziedziczących ale będących w tym samym pakiecie użyty będzie internal.

Modyfikator sealed powoduje, że po danej klasie nie można dziedziczyć. Można go używać także wraz z metodami – klasy dziedziczące nie będą mogły przeciążać danej metody.

 

5. Do czego można użyć słowa kluczowego using?

Pierwszą i najważniejszą rzeczą, o której myśli programista to używanie tego słowa kluczowego do dołączania przestrzeni nazw. Brawo! Jest to poprawna odpowiedź, lecz niewyczerpana. Otóż kolejnym celem, w którym wykorzystujemy using jest ograniczenie czasu życia obiektu, np.

using (SqlConnection connection = new SqlConnection( connectionString))

{

SqlCommand command = new SqlCommand(queryString, connection);

command.Connection.Open();

command.ExecuteNonQuery();

}

Użycie słowa kluczowego using zamienia nam jawne wywołanie metody Disopose() na niejawne.

 

6. SOLID

Ssingle responsibility principle. Zasada pojedynczej odpowiedzialności. Każda klasa powinna być odpowiedzialna za jeden obszar projektu.

O open-closed, Zasada otwarte – zamknięte. Kod powinien być otwarty na rozbudowę a zamknięty na modyfikacje.

LZasada podstawiania Barbary Liskov,

“Funkcje które używają wskaźników lub referencji do klas bazowych, muszą być w stanie używać również obiektów klas dziedziczących po klasach bazowych, bez dokładnej znajomości tych obiektów.”

Mówi o tym klasa dziedzicząca powinna rozszerzać możliwości klasy bazowej a nie całkowicie zmieniać jej funkcjonalność.

IZasada segregacji interfejsów. Ma za zadanie przede wszystkich wyeliminowanie nieporęcznych, niepotrzebnie rozbudowanych interfejsów. Do tej grupy można zaliczyć nadmiernie rozbudowane i niespójne interfejsy klas. Każdy taki interfejs zgodnie z tą zasadą powinien zostać podzielony na mniejsze grupy metod.

DZasada odwracania zależności. Moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych. Obie grupy modułów powinny zależeć od abstrakcji.

 

7. TDD

TDDTest-Driven Development – to podejście do tworzenia oprogramowania. Podejście to zakłada, że przed napisaniem właściwej funkcjonalności programista zaczyna od utworzenia testu. TDD to podejście, które składa się z trzech faz. Te trzy fazy łączą się w cykl. Cały proces pisania kodu składa się z właśnie takich cykli, które powtarzasz jeden po drugim. Cykl to trzy fazy:

Red – Pierwszym krokiem jest napisanie testu,

Green – Kolejnym krokiem jest napisanie kodu, który implementuje brakującą funkcjonalność,

Refactor – Refaktoryzacja kodu.

 

8. Throw vs. Throw ex

Różnica jest taka, że stosując pierwszą z nich nie tracimy informacji zawartej w stosie wywołań (stack trace). To znaczy, że jeśli ponownie rzucony przez nas wyjątek złapiemy w kolejnym bloku try/cacth to będzie tam dostępna pełna informacja o stosie wywołań począwszy od pierwotnego źródła wyjątku. W drugim przypadku stos wywołań będzie zawierał ograniczoną informację – będzie wyglądał tak, jakby pierwotnym źródłem wyjątku była metoda, w której został on złapany i ponownie rzucony.

 

9. Jaki jest cel używania operatora is w C#?

Operator is jest operatorem rzutowania. Zwraca flagę true jeżeli rzutowanie się powiedzie. Zwraca flagę false jeżeli rzutowanie będzie niepoprawne. Operator ten zwykle znajduje zastosowanie podczas sprawdzania typów w instrukcji warunkowej if.

 

10. Jaki jest cel używania operatora as w C#?

Operator as dokonuje rzutowania bez zwracania wyjątku jeżeli rzutowanie się nie powiedzie. W przeciwnym wypadku zwraca null. Rzutować możemy jedynie na typy, które są nullowalne – nie możemy używać struktur.