Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 8 stycznia 2025 14:23
  • Data zakończenia: 8 stycznia 2025 14:41

Egzamin zdany!

Wynik: 33/40 punktów (82,5%)

Wymagane minimum: 20 punktów (50%)

Pochwal się swoim wynikiem!
Szczegółowe wyniki:
Pytanie 1

Aplikacje webowe stworzone z użyciem frameworka Angular lub biblioteki React, działające na standardowych portach, można uruchomić na lokalnym serwerze, wpisując w przeglądarkę

A. localhost:8000 (React) lub localhost:49887 (Angular)
B. localhost:5001 (React) lub localhost:8080 (Angular)
C. localhost:8080 (React) lub localhost:8000 (Angular)
D. localhost:3000 (React) lub localhost:4200 (Angular)
React domyślnie startuje na porcie 3000, a Angular na 4200 – to są takie standardy, które praktycznie wszyscy w branży znają i stosują. Kiedy zaczynasz nowy projekt w React, korzystając na przykład z create-react-app, serwer deweloperski po prostu nasłuchuje na http://localhost:3000. Analogicznie, jak generujesz projekt w Angular CLI i odpalasz ng serve, wtedy aplikacja wystartuje na http://localhost:4200. To są domyślne porty – nie musisz nic specjalnie ustawiać, wystarczy wpisać te adresy w przeglądarce. Z mojego doświadczenia, dobrze jest zapamiętać te ustawienia, bo praktycznie na każdym warsztacie czy bootcampie te adresy padają od ręki. Jeśli chodzi o praktykę, czasami port jest już zajęty i wtedy narzędzie zaproponuje inny, ale te wartości startowe to taka baza. Warto pamiętać, że zmiana portu wynika zazwyczaj z konfliktu, a nie z jakiejś specjalnej potrzeby. Dodatkowo, rozpoznanie tych portów pozwala szybciej debugować problemy z uruchomieniem aplikacji – jak coś nie wstaje na tych adresach, to od razu wiadomo, gdzie szukać. Ogólnie rzecz biorąc, korzystanie z tych domyślnych portów przyspiesza współpracę w zespole, bo każdy wie, gdzie szukać aplikacji, więc nie trzeba się rozpisywać w README, na jakim porcie coś działa. Moim zdaniem, to jeden z tych drobnych szczegółów, które składają się na dobre nawyki programistyczne.

Pytanie 2

Programista aplikacji mobilnych chce przekwalifikować się na pracownika Full-Stack Developer. Wskaż kurs, który powinien wybrać, aby było to możliwe

A. Ultimate C# Serier from Beginner to Advanced
B. Raster and Vector Graphics with Adobe
C. Mastering Cross-platform Developping
D. Complete JavaScript React, SQL, Node.js Cource
Wybór kursu "Complete JavaScript React, SQL, Node.js Course" to zdecydowanie najbardziej logiczna opcja, jeśli ktoś myśli poważnie o przejściu na ścieżkę Full-Stack Developera. Full-stack to bardzo specyficzne pojęcie – chodzi tu o umiejętność poruszania się zarówno po stronie front-endu (czyli tego, co widzi użytkownik), jak i back-endu (czyli serwera, bazy danych, logiki biznesowej). Ten kurs obejmuje JavaScript, który jest teraz królem w świecie web developmentu – daje ogromne możliwości i na froncie (np. React), i na backendzie (Node.js). Do tego dochodzi SQL, czyli język zapytań do baz danych, bez którego ciężko sobie wyobrazić jakąkolwiek aplikację z prawdziwego zdarzenia. Przerobienie takiego kursu zapewnia znajomość pełnego cyklu tworzenia aplikacji webowych: od interfejsu użytkownika, przez komunikację z API, aż po operacje na bazach danych. W praktyce, firmy szukające full-stacków oczekują właśnie takiego wachlarza umiejętności, bo to pozwala tworzyć całe systemy praktycznie w pojedynkę lub w małych zespołach. Z mojego doświadczenia, nawet podstawowa znajomość Reacta i Node.js otwiera drzwi do wielu ofert pracy i własnych projektów, bo można szybko stworzyć MVP i sprawnie wdrażać nowe funkcjonalności. Warto też dodać, że technologie te mają świetną dokumentację i aktywne społeczności, gdzie można znaleźć wsparcie i praktyczne porady. Według mnie, to najlepszy kierunek na rynku dla kogoś, kto zna już programowanie mobilne i chce się rozwinąć na pełen stos webowy, bo można wykorzystać wiele dotychczasowych umiejętności, a jednocześnie nauczyć się rzeczy praktycznie wykorzystywanych na co dzień w nowoczesnych firmach IT.

Pytanie 3

Wskaż fragment kodu, który stanowi realizację przedstawionego algorytmu w języku C++.

Kod 1
do {
  suma = suma + i;
} while (suma <= liczba);
cout << suma;
Kod 2
if (suma <= liczba) {
  suma = suma + i;
  i++;
}
else
  cout << suma;
Kod 3
for (i = suma; i <= liczba; i++)
  suma = suma + i;
else
  cout << suma;
Kod 4
while (suma <= liczba) {
  suma = suma + i;
  i++;
}
cout << suma;
Ilustracja do pytania
A. kod 4
B. kod 1
C. kod 2
D. kod 3
W niepoprawnych fragmentach kodu problemem nie jest sam język C plus plus, tylko sposób odwzorowania algorytmu z rysunku. Schemat blokowy jasno mówi, że dopóki suma jest mniejsza lub równa liczba, mamy wielokrotnie dodawać kolejne wartości i oraz zwiększać licznik, a dopiero po wyjściu z tego cyklu jednorazowo wypisać wartość suma. Konstrukcja z pętlą do while wykonuje ciało przynajmniej raz bez wcześniejszego sprawdzenia warunku, czyli najpierw dodaje i do sumy, a dopiero później porównuje suma <= liczba. To subtelne przesunięcie powoduje, że kod może wykonać jedną iterację za dużo w stosunku do schematu. W praktyce bywa to bardzo groźne, na przykład przy obsłudze buforów w systemach wbudowanych czy przy obliczeniach finansowych. Fragment oparty wyłącznie na instrukcji if z else nie tworzy żadnej pętli, więc kod wykona maksymalnie jedno dodanie i, a to jest całkowicie sprzeczne z ideą powtarzania z diagramu. To typowy błąd uczniów, którzy mylą pojedyncze rozgałęzienie z cyklicznym przetwarzaniem danych. Z kolei użycie pętli for z else wygląda na pierwszy rzut oka efektownie, ale również nie odpowiada schematowi. Po pierwsze, zakres iteracji jest na sztywno powiązany z warunkiem i <= liczba, a algorytm operuje na warunku suma <= liczba. Po drugie, else po pętli for nie jest standardową konstrukcją w C plus plus i w praktyce taki kod nawet się nie skompiluje. Z mojego doświadczenia wynika, że źródłem większości takich pomyłek jest próba zbyt kreatywnego kombinowania zamiast trzymania się prostego tłumaczenia: warunek na rombie przekładamy na warunek w pętli, strzałka oznacza powrót na początek, a blok pisz suma to pojedyncza instrukcja po zakończeniu pętli. Dopiero jak to rozumiemy, można zaczynać optymalizacje czy inne fajerwerki składniowe.

Pytanie 4

Resuscytacja krążeniowo-oddechowa polega na realizowaniu

A. 10 ucisków klatki piersiowej oraz 5 oddechów ratunkowych
B. 30 ucisków klatki piersiowej oraz 2 oddechy ratunkowe
C. 15 ucisków klatki piersiowej oraz 3 oddechy ratunkowe
D. 20 ucisków klatki piersiowej oraz 1 oddech ratunkowy
Resuscytacja krążeniowo-oddechowa (RKO) w obecnych wytycznych Europejskiej Rady Resuscytacji polega właśnie na wykonywaniu 30 ucisków klatki piersiowej na przemian z 2 oddechami ratunkowymi. Taki schemat jest rekomendowany zarówno dla dorosłych, jak i dzieci (poza niemowlętami i sytuacjami szczególnymi), bo zapewnia optymalną perfuzję mózgu i serca, a jednocześnie daje szansę na dostarczenie tlenu do organizmu. Gdyby skrócić liczbę ucisków albo oddechów, efektywność spada, a szansa przeżycia jest mniejsza. Ja zawsze powtarzam, że praktyka czyni mistrza – jak ćwiczyliśmy na fantomach, to właśnie ten rytm: 30 ucisków, potem 2 szybkie oddechy, bez zbędnych przerw. Praktycznie, w stresie łatwo się pogubić, ale jak sobie utrwalicie ten schemat, działa automatycznie. Warto wiedzieć, że uciski muszą być na głębokość około 5–6 cm u dorosłych, z częstotliwością co najmniej 100–120 na minutę – to jest kluczowe dla skuteczności. Z mojego doświadczenia wynika, że najczęściej popełnianym błędem jest zbyt płytkie uciskanie i zbyt długie przerwy na oddechy, warto to poćwiczyć. Kiedy nie chce się robić oddechów (np. obawa przed zakażeniem), można prowadzić tylko uciski, ale pełne RKO daje największe szanse. Takie podejście jest sprawdzone praktycznie na całym świecie i jak dla mnie, nie ma sensu kombinować z innymi proporcjami.

Pytanie 5

Jakie rozwiązanie jest najbardziej odpowiednie przy projektowaniu aplikacji, która ma funkcjonować na różnych systemach operacyjnych?

A. Pełne dopasowanie aplikacji do systemu Windows
B. Opracowanie dedykowanego kodu dla każdej platformy
C. Wykorzystanie technik responsywnego projektowania interfejsu
D. Koncentrowanie się wyłącznie na estetyce aplikacji
Przy projektowaniu aplikacji na różne systemy operacyjne łatwo wpaść w pułapkę starych nawyków albo uproszczonego myślenia, co często prowadzi do nietrafionych decyzji projektowych. Częstą pokusą jest pisanie osobnego, dedykowanego kodu dla każdej platformy. Kto kiedyś pisał natywne aplikacje pod Windowsa i MacOS ten wie, jak szybko taki model staje się koszmarem w utrzymaniu. Z mojego doświadczenia wynika, że taka fragmentacja powoduje, że każda zmiana musi być wdrażana i testowana osobno, co prowadzi do rozjazdu funkcjonalności i wzrostu kosztów – a to jest dokładnie odwrotność tego, czego oczekuje się od nowoczesnego software’u. Z kolei pełne dopasowanie tylko do Windowsa całkowicie pomija wymagania użytkowników innych platform i zamyka aplikację na szerokie grono odbiorców. Takie podejście bywa wygodne na początku, ale ogranicza potencjał produktu i w praktyce jest sprzeczne z dzisiejszymi oczekiwaniami rynku, gdzie multiplatformowość to już standard, nie luksus. Skupianie się wyłącznie na estetyce aplikacji to chyba najczęstszy błąd początkujących – ładny wygląd nie gwarantuje użyteczności, dostępności ani funkcjonalności na różnych systemach operacyjnych. Branża IT od lat promuje podejście user-centered design, gdzie ważniejsza od samej estetyki jest adaptacja interfejsu do różnorodnych urządzeń i warunków użytkowania. Responsywny design bazuje na elastyczności oraz automatycznym dostosowywaniu się do środowiska, co pozwala uniknąć masy problemów z kompatybilnością i znacznie poprawia doświadczenie użytkownika. W mojej opinii, ignorowanie tych aspektów to częsty powód niepowodzeń nawet ambitnych projektów. Warto patrzeć szerzej i planować rozwiązania, które są przyszłościowe, modularne oraz skalowalne.

Pytanie 6

Które z wymienionych narzędzi nie znajduje zastosowania w tworzeniu aplikacji desktopowych?

A. Kompilator
B. Przeglądarka internetowa
C. Edytor graficzny
D. Debugger
Przeglądarka internetowa nie jest narzędziem wykorzystywanym bezpośrednio w procesie tworzenia aplikacji desktopowych. Chociaż może służyć do przeszukiwania dokumentacji lub testowania aplikacji webowych, jej funkcjonalność nie wspiera bezpośredniego tworzenia aplikacji desktopowych. W tworzeniu aplikacji desktopowych kluczowe są narzędzia takie jak kompilatory, debugery i edytory kodu. Kompilatory przekształcają kod źródłowy na kod wykonywalny, debugery pozwalają na śledzenie błędów, a edytory kodu umożliwiają pisanie i edytowanie aplikacji.

Pytanie 7

Jakie będzie działanie przedstawionych dwóch równoważnych fragmentów kodu źródłowego?

Kod w React:

function Heading(props) {
    return (
        <h1> {props.title} </h1>
    );
}

// w metodzie render
return (
    <Heading title="Egzamin zawodowy" />
);

Kod w Angular:
// heading.component.ts
import {Component} from '@angular/core';
@Component({
    selector: 'app-heading',
    templateUrl: './heading.component.html',
    styleUrls: ['./heading.component.css']
})

export class HeadingComponent {
    title:String = "Egzamin zawodowy";
    ...
}

// heading.component.html
<h1>{{title}}</h1>
A. Nadany tytuł każdego elementu HTML: "Egzamin zawodowy"
B. Wyświetlony na stronie tekst w nagłówku: "Egzamin zawodowy"
C. Wyświetlony na stronie tekst w akapicie: "Egzamin zawodowy"
D. Nadany tytuł strony: "Egzamin zawodowy"
Zdarza się, że łatwo pomylić różne sposoby prezentacji tekstu na stronie, zwłaszcza gdy ma się do czynienia z wieloma frameworkami naraz. W przedstawionych fragmentach kodu zarówno w React, jak i w Angularze, kluczowe jest użycie tagu <h1>, czyli nagłówka pierwszego poziomu. Jeżeli uznałeś, że zostanie wyświetlony tekst w akapicie, to być może zasugerowałeś się inną składnią, bo <p> w kodzie w ogóle nie ma. Możliwe też, że patrząc na słowo „title”, pojawiła się skojarzenie z atrybutem title w HTML (który odpowiada za tzw. tooltip po najechaniu kursorem lub tytuł strony), ale w tym przypadku title to po prostu nazwa właściwości przekazywanej do komponentu lub pola w klasie, nie specjalny atrybut HTML. Kolejna zmyłka, nadawanie tytułu wszystkim elementom HTML – brzmi jak coś, co można by zrobić globalnie stylem, ale tutaj nic takiego się nie dzieje. W kodzie nie występuje żaden mechanizm, który iteruje po wszystkich elementach i ustawia im atrybut, to nie jest ten przypadek. Jeśli chodzi o tytuł strony, to w przeglądarce jest on definiowany przez <title> w sekcji <head> dokumentu HTML, a tutaj pracujemy tylko z zawartością renderowaną w widocznym DOM, nie konfigurujemy meta-danych strony. To częsty błąd – mylić zmienne używane w kodzie z atrybutami HTML o tej samej nazwie. Warto pamiętać, że w React i Angularze komponowanie widoków opiera się głównie o manipulację treścią w obrębie renderowanego drzewa DOM, a nie bezpośrednią modyfikację atrybutów meta czy stylów całego dokumentu. Dobrze jest też zawsze spojrzeć na strukturę znacznika – gdy widać <h1>, od razu powinno się zakładać, że chodzi o nagłówek – i, szczerze mówiąc, takie pytania świetnie pokazują, jak ważne jest rozumienie, co faktycznie renderuje się na stronie, bo czasem pozorne podobieństwo nazw prowadzi do błędnych wniosków.

Pytanie 8

Szablon MojaTablica oferuje funkcjonalność tablicy z indeksami oraz elementami różnych typów. W oparciu o pokazany kod, który wykorzystuje ten szablon do tworzenia tablicy asocjacyjnej, wskaż definicję, która posługuje się szablonem do zainicjowania tablicy, gdzie indeksami są liczby całkowite, a elementami są napisy?

MojaTablica tab1 = new MojaTablica<string, string>();
tab1["good"] = "dobry";
A. int tab2[] = new MojaTablica()
B. int tab2 = new MojaTablica()
C. MojaTablica tab2 = MOjaTablica()
D. MojaTablica tab2 = new MojaTablica()
Aby utworzyć tablicę asocjacyjną w oparciu o szablon, należy zainicjalizować ją przy użyciu właściwej składni: MojaTablica tab2 = new MojaTablica();. Tego typu deklaracja tworzy obiekt tablicy, gdzie klucze są liczbami całkowitymi, a wartości przechowywane w tablicy to napisy. Tablice asocjacyjne to potężne narzędzie pozwalające na szybkie wyszukiwanie i przechowywanie danych, bazujące na unikalnych kluczach, co umożliwia efektywne zarządzanie złożonymi strukturami danych.

Pytanie 9

Jakie jest przeznaczenie polecenia "git merge"?

A. Do zakładania nowego repozytorium
B. Do pobierania aktualizacji zdalnego repozytorium
C. Do usuwania zmian w repozytorium
D. Do łączenia zmian z różnych gałęzi
Wiele osób na początku nauki Gita myli różne polecenia, bo brzmią podobnie albo wydają się robić coś bliskiego. "git merge" często bywa mylone z poleceniami typu "git pull" czy "git clone", które mają jednak zupełnie inne zastosowanie. Pobieranie aktualizacji ze zdalnego repozytorium to domena "git pull" – to polecenie automatycznie pobiera nowe commity i próbuje je od razu zintegrować z lokalną gałęzią, często zresztą używając w tle właśnie "merge". Ale samo "git merge" nie ściąga niczego z internetu, ono tylko łączy zmiany już obecne w lokalnych gałęziach. Z kolei tworzenie nowego repozytorium to zadanie "git init"; to zupełnie inny etap pracy, bo dotyczy rozpoczęcia projektu, a nie zarządzania jego rozwojem. Usuwanie zmian w repozytorium – tutaj najczęściej używa się "git reset" czy "git revert", zależnie od tego czy chcemy cofnąć zmiany lokalnie czy naprawić coś w historii. Merge natomiast nie służy do usuwania ani cofania, tylko do scalania zmian – to kluczowe, żeby nie pomylić tych narzędzi, bo można przez to nieźle namieszać w kodzie. Moim zdaniem, głównym błędem jest założenie, że wszystkie polecenia związane z aktualizacją kodu robią to samo, podczas gdy w Git każde z nich ma bardzo konkretne zadanie i konsekwencje. Dla dobrych praktyk w zespole ważne jest, żeby rozumieć subtelne różnice między tymi operacjami. Praktyka pokazuje, że błędne użycie "merge" – jak również zamiana go z "pull" albo "reset" – potrafi prowadzić do chaosu w historii projektu. Warto zatem dobrze opanować przeznaczenie każdego z poleceń przed rozpoczęciem pracy nad większym projektem.

Pytanie 10

Przedstawiony fragment dotyczy funkcji resize w języku C++. Ta funkcja obniży długość elementu string, gdy wartość parametru

Resize string
Resizes the string to a length of n characters.

If n is smaller than the current string length, the current value is shortened to its first n character, removing the characters beyond the nth.

If n is greater than the current string length, the current content is extended by inserting at the end as many characters as needed to reach a size of n. If c is specified, the new elements are initialized as copies of c; otherwise, they are value-initialized characters (null characters).

Parameters
n
New string length, expressed in number of characters.
size_t is an unsigned integral type (the same as member type string::size_type).
c
Character used to fill the new character space added to the string (in case the string is expanded).
Źródło: http://www.cplusplus.com/reference/string/string/resize/
A. n jest większa od aktualnej długości łańcucha
B. c jest większa od aktualnej długości łańcucha
C. c jest mniejsza od aktualnej długości łańcucha
D. n jest mniejsza od aktualnej długości łańcucha
To jest dokładnie to, o co chodzi w funkcji resize dla std::string w C++. Jeśli podany parametr n jest mniejszy od aktualnej długości łańcucha, to obcinamy stringa do tych właśnie n znaków – reszta znika bezpowrotnie. Moim zdaniem to bardzo wygodne, bo nie trzeba ręcznie wycinać fragmentu czy bawić się w operacje na podłańcuchach. Praktycznie rzecz biorąc, można dzięki temu szybko skrócić dane wejściowe, np. gdy pobieramy z pliku długi tekst, a potrzebujemy tylko jego fragment do dalszego przetwarzania. W branży często się to przydaje – na przykład ograniczając długość nicku użytkownika do określonej liczby znaków lub przytrzymując długość serializowanych danych w protokołach sieciowych. Resize działa wprost i zgodnie ze standardem C++, usuwając znaki od indeksu n wzwyż. Co ciekawe, metoda nie tylko skraca, ale też rozszerza string – wtedy wypełnia go nowymi znakami (np. 'x' czy znakiem pustym), ale to właśnie skracanie jest często pomijane przez początkujących, a jest naprawdę przydatne. No i trzeba pamiętać, że oryginalne znaki spoza zakresu po prostu znikają – nie ma żadnych ostrzeżeń. Z mojego doświadczenia to jedna z tych funkcji, do których z czasem nabiera się szacunku – bo ułatwia życie na co dzień przy operacjach na łańcuchach znaków.

Pytanie 11

Które z podanych logo reprezentuje narzędzie, które nie jest używane do tworzenia aplikacji mobilnych?

Ilustracja do pytania
A. 4
B. 3
C. 1
D. 2
Wybrałeś odpowiedź nr 4, czyli logo Xcode. To rzeczywiście poprawny wybór, bo Xcode to środowisko programistyczne stworzone przez Apple głównie do tworzenia aplikacji na systemy iOS, macOS, watchOS oraz tvOS. W praktyce Xcode jest praktycznie niezbędny, jeśli chodzi o natywny rozwój aplikacji mobilnych na iPhone’a czy iPada – zresztą Apple wymaga używania tego narzędzia do publikowania aplikacji w App Store. Jednak gdy spojrzymy na pozostałe loga: Android Studio (1), Xamarin (3) oraz Angular (2), to tylko Angular nie jest narzędziem do budowy natywnych aplikacji mobilnych. Angular to framework frontendowy, używany głównie do tworzenia aplikacji webowych typu SPA (Single Page Application). Oczywiście, da się użyć Angulara z Cordovą czy Ionicem, żeby zrobić hybrydową aplikację na telefon, ale to nie jest to samo, co pełnoprawny toolchain do mobilnych aplikacji natywnych. W branży panuje przekonanie, że lepiej korzystać z narzędzi dedykowanych platformie, bo to daje lepszą wydajność i stabilność, a Angular to rozwiązanie, które jest bliżej weba niż mobile. Takie rozróżnienie jest ważne zwłaszcza przy podejmowaniu decyzji o technologii przy większych projektach mobilnych.

Pytanie 12

Który z wymienionych przykładów przedstawia typ rekordowy?

A. float w języku C
B. struct w języku C++
C. int w języku Python
D. bool w języku Java
Typ 'int' w Pythonie przechowuje liczby całkowite i nie pozwala na grupowanie wielu wartości pod jedną zmienną. 'Bool' w Javie to typ logiczny przechowujący wartości 'true' i 'false' – nie umożliwia przechowywania wielu pól. 'Float' w C to typ zmiennoprzecinkowy używany do przechowywania liczb rzeczywistych i nie jest typem rekordowym. Tylko 'struct' umożliwia tworzenie niestandardowych typów danych składających się z różnych pól, co czyni go kluczowym narzędziem w modelowaniu bardziej złożonych obiektów.

Pytanie 13

Jakie składniki powinien mieć plan projektu?

A. Wyłącznie etapy projektu
B. Terminy i zasoby ludzkie
C. Tylko czas wykonania i budżet
D. Etapy projektu, ramy czasowe, zasoby i zadania
Harmonogram projektu powinien zawierać etapy projektu, ramy czasowe, zasoby oraz zadania. Taka kompleksowa struktura umożliwia skuteczne zarządzanie projektem i pozwala na śledzenie postępów. Każdy etap harmonogramu powinien być dokładnie opisany, a zadania powinny być przypisane do odpowiednich członków zespołu. Uwzględnienie zasobów i ram czasowych pozwala na precyzyjne planowanie i minimalizuje ryzyko opóźnień. Harmonogram stanowi nieodłączny element projektów zarządzanych zarówno w modelu Waterfall, jak i Agile, dostarczając przejrzystość na każdym etapie realizacji.

Pytanie 14

Jaki rodzaj ataku hakerskiego polega na bombardowaniu serwera ogromną ilością żądań, co prowadzi do jego przeciążenia?

A. DDoS
B. Phishing
C. Man-in-the-Middle
D. SQL Injection
Atak DDoS (Distributed Denial of Service) polega na zasypywaniu serwera dużą ilością zapytań, co prowadzi do jego przeciążenia i unieruchomienia. W tym rodzaju ataku, hakerzy wykorzystują sieć skompromitowanych komputerów, znanych jako botnety, aby wysłać ogromne ilości nieautoryzowanych żądań do docelowego serwera w krótkim czasie. Celem DDoS jest spowodowanie, że serwer nie jest w stanie odpowiedzieć na prawidłowe zapytania od autentycznych użytkowników, co skutkuje awarią usługi. Przykłady ataków DDoS obejmują SYN Flood, UDP Flood oraz HTTP Flood, gdzie każdy z tych typów wykorzystuje różne protokoły i metody do zablokowania normalnego ruchu. Standardy takie jak RFC 793 definiują protokół TCP, który może być narażony na ataki SYN Flood. Ważne jest, aby organizacje stosowały odpowiednie środki zabezpieczające, takie jak systemy detekcji intruzów (IDS), firewalle, oraz usługi ochrony DDoS, aby minimalizować ryzyko i skutki tych ataków.

Pytanie 15

Który z poniższych przykładów ilustruje deklarację złożonego typu w języku C++?

A. float ocena = 4.5;
B. int wynik = 100;
C. class Student {};
D. bool status;
Deklaracja `class Student {};` w języku C++ przedstawia przykład tworzenia typu złożonego w postaci klasy. Klasa to podstawowy element programowania obiektowego, który pozwala na łączenie danych (pól) i funkcji (metod) w jednej strukturze. Klasy umożliwiają modelowanie rzeczywistych obiektów i ich zachowań, co prowadzi do bardziej zorganizowanego i skalowalnego kodu. Klasy mogą być rozszerzane przez dziedziczenie, co jest kluczową zaletą programowania obiektowego.

Pytanie 16

Jakie rezultaty pojawią się po uruchomieniu poniższego kodu napisanego w języku C++?

class KlasaBazowa {
    public:
        virtual void metoda() {
            cout << "Bazowa. ";
        }
};

class KlasaPochodna : public KlasaBazowa {
    public:
        void metoda() {
            cout << "Pochodna. ";
        }
};

int main() {
    KlasaBazowa *bazowa = new KlasaPochodna();
    KlasaPochodna *pochodna = new KlasaPochodna();

    bazowa->metoda();
    pochodna->metoda();
    return 0;
}
A. Bazowa. Bazowa.
B. Bazowa. Pochodna.
C. Pochodna. Pochodna.
D. Pochodna. Bazowa.
Kod wyświetla 'Pochodna. Pochodna.', co wskazuje, że metody klasy pochodnej przejęły kontrolę nad tymi z klasy bazowej. To fajny przykład polimorfizmu, jaki mamy w C++. Tutaj metoda w klasie pochodnej jest lepsza od metody w klasie bazowej. To, jakie wywołanie się wykona, zależy od konkretnego obiektu, a nie od tego, jaką metodę zdefiniowaliśmy w klasie bazowej.

Pytanie 17

Które z wymienionych środowisk programistycznych jest rekomendowane do developing aplikacji w języku Python z użyciem frameworka Django?

A. Android Studio
B. XCode
C. Unity
D. PyCharm
PyCharm to jedno z najbardziej zaawansowanych środowisk programistycznych (IDE) dedykowanych do tworzenia aplikacji w języku Python. Jest to narzędzie preferowane przez programistów korzystających z frameworka Django, który jest popularnym rozwiązaniem do budowy aplikacji webowych. PyCharm oferuje rozbudowane wsparcie dla Django, umożliwiając szybkie tworzenie projektów, integrację z bazami danych oraz wygodne debugowanie aplikacji. IDE zapewnia również możliwość uruchamiania serwerów deweloperskich, podglądu zmian w czasie rzeczywistym oraz automatyczne uzupełnianie kodu, co znacząco zwiększa efektywność pracy nad aplikacjami webowymi. Dzięki PyCharm programiści mogą łatwo zarządzać migracjami bazy danych, tworzyć modele i szablony, co sprawia, że jest to narzędzie nieocenione w ekosystemie Django.

Pytanie 18

Który z etapów umożliwia zwiększenie efektywności aplikacji przed jej wydaniem?

A. Tworzenie interfejsu graficznego
B. Optymalizacja kodu
C. Testowanie jednostkowe
D. Dodawanie komentarzy do kodu
Optymalizacja kodu to kluczowy etap poprawy wydajności aplikacji przed jej publikacją. Polega na eliminacji zbędnych operacji, poprawie algorytmów oraz minimalizacji użycia zasobów, co pozwala na szybsze działanie aplikacji i zmniejszenie jej zapotrzebowania na pamięć. Optymalizacja kodu obejmuje również refaktoryzację, czyli przekształcenie kodu w bardziej czytelną i efektywną formę bez zmiany jego funkcjonalności. Dzięki optymalizacji aplikacje działają płynniej, szybciej się ładują i oferują lepsze doświadczenie użytkownika, co ma kluczowe znaczenie dla SEO oraz pozycjonowania aplikacji w wyszukiwarkach. Dodatkowo, zoptymalizowany kod jest łatwiejszy w utrzymaniu i rozwijaniu, co przekłada się na długoterminowe korzyści dla zespołu deweloperskiego.

Pytanie 19

Jakie jest zastosowanie języka XAML przy tworzeniu aplikacji desktopowych?

A. Do optymalizacji działania aplikacji
B. Do zarządzania bazami danych
C. Do projektowania graficznego interfejsu użytkownika
D. Do obsługi zdarzeń klawiatury
XAML (Extensible Application Markup Language) to język znaczników wykorzystywany w technologii WPF (Windows Presentation Foundation) oraz UWP (Universal Windows Platform) do projektowania graficznego interfejsu użytkownika (GUI). XAML pozwala na definiowanie układów, przycisków, etykiet oraz innych elementów interaktywnych w aplikacjach desktopowych. Dzięki XAML, projektowanie interfejsu jest intuicyjne, a kod interfejsu jest oddzielony od logiki aplikacji, co sprzyja przejrzystości projektu. XAML wspiera animacje, style i szablony, co umożliwia budowę nowoczesnych, dynamicznych aplikacji. Jego elastyczność i możliwość współpracy z C# sprawiają, że XAML jest niezastąpiony w środowisku Windows.

Pytanie 20

Jak zrealizować definiowanie własnego wyjątku w języku C++?

A. Automatycznie wywołać funkcję throw
B. Utworzyć klasę, która dziedziczy po std::exception
C. Wykorzystać blok try z pustym blokiem catch
D. Skorzystać z domyślnej metody obsługi błędów
Aby zdefiniować własny wyjątek w języku C++, należy stworzyć klasę dziedziczącą po standardowej klasie 'std::exception' lub jednej z jej pochodnych. Klasa ta może zawierać własne metody i pola, dostosowując obsługę błędów do specyficznych potrzeb aplikacji. Dziedziczenie z 'std::exception' umożliwia korzystanie z funkcji takich jak 'what()', która zwraca opis błędu. Dzięki temu programista może precyzyjnie określić typ i przyczynę wyjątku, co prowadzi do bardziej czytelnego i łatwiejszego w utrzymaniu kodu. Tworzenie własnych wyjątków jest szczególnie przydatne w dużych projektach, gdzie występuje potrzeba kategoryzacji i obsługi różnych typów błędów w zależności od ich źródła.

Pytanie 21

Co należy do zadań interpretera?

A. sprawdzanie składni całego programu przed jego uruchomieniem
B. ulepszanie większej części kodu, aby przyspieszyć jego wykonanie
C. wykonanie skryptu instrukcja po instrukcji
D. przekładanie kodu na kod maszynowy
Interpreter to taki program, który odczytuje kod źródłowy i wykonuje go krok po kroku, instrukcja po instrukcji, bez wcześniejszego tłumaczenia całości na kod maszynowy. W praktyce oznacza to, że interpreter analizuje każdą linię lub blok kodu i natychmiast realizuje odpowiadające im działania na komputerze. Przykładem są języki takie jak Python czy JavaScript – tam właśnie interpreter gra główną rolę. Umożliwia to szybkie testowanie i prototypowanie, bo nie trzeba czekać na kompilację całego programu, wystarczy wpisać polecenie i od razu widzimy efekt. Moim zdaniem to genialne rozwiązanie zwłaszcza do nauki programowania czy pisania prostych skryptów systemowych, gdzie liczy się szybka informacja zwrotna. Warto wiedzieć, że interpreter nie generuje pliku wykonywalnego na stałe – każdy raz trzeba uruchomić kod za jego pośrednictwem. W branży często używa się interpreterów do automatyzacji zadań, analizy danych czy tworzenia narzędzi do testów. Z własnego doświadczenia wiem, że interpreter pozwala łatwo wyłapać błędy logiczne na bieżąco, chociażby w konsoli Pythona. To świetne narzędzie, gdy chcemy eksperymentować z kodem, bo nic nie stoi na przeszkodzie, żeby szybko coś zmodyfikować i od razu zobaczyć rezultat. Trzeba tylko pamiętać, że takie podejście czasem może być wolniejsze niż wykonanie kodu skompilowanego, ale w wielu zadaniach wygoda i elastyczność przeważają nad wydajnością.

Pytanie 22

Jakie korzyści płyną z użycia pseudokodu przy tworzeniu algorytmu?

A. Generowanie dynamicznych struktur danych
B. Łatwość w zmianie kodu maszynowego
C. Możliwość szybkie zrealizowania algorytmu w którymkolwiek języku
D. Zrozumiałość dla osób nieznających się na programowaniu
Zaletą wykorzystania pseudokodu podczas projektowania algorytmu jest jego czytelność i prostota, dzięki czemu jest zrozumiały nawet dla osób, które nie są biegłe w programowaniu. Pseudokod pozwala skupić się na logice działania algorytmu bez konieczności przestrzegania ścisłej składni konkretnego języka programowania. Dzięki temu proces projektowania jest szybszy, a algorytm można łatwo przełożyć na dowolny język programowania. Pseudokod ułatwia również współpracę między programistami i analitykami, wspierając tworzenie i dokumentowanie złożonych rozwiązań.

Pytanie 23

W jaki sposób definiuje się konstruktor kopiujący w ramach klasy?

A. Inicjuje obiekt klasy na podstawie klasy dziedziczącej
B. Generuje nowy obiekt i usuwa wcześniejszy
C. Tworzy nowy obiekt jako wierną kopię innego obiektu
D. Generuje nowy obiekt klasy bez przypisywania wartości
Konstruktor kopiujący to specjalny typ konstruktora, który tworzy nowy obiekt będący dokładną kopią innego obiektu tej samej klasy. Jest to niezwykle przydatne, gdy chcemy zduplikować istniejący obiekt, zachowując jego stan i wartości wszystkich składowych. Konstruktor kopiujący przyjmuje jako argument referencję do obiektu tej samej klasy, co pozwala na kopiowanie zarówno podstawowych typów danych, jak i dynamicznie alokowanych zasobów. Jego zastosowanie jest kluczowe w sytuacjach, gdy musimy pracować z obiektami dynamicznymi lub kopiować obiekty zarządzające wskaźnikami, aby uniknąć problemów związanych z wielokrotnym zwalnianiem tej samej pamięci.

Pytanie 24

Który z poniższych aspektów najdokładniej określa cel realizacji projektu?

A. Ocena postępów w czasie realizacji projektu
B. Zidentyfikowanie technologii, które mogą być zastosowane
C. Stworzenie harmonogramu działań
D. Określenie problemu i metody jego rozwiązania
Określenie problemu i sposobu jego rozwiązania to fundamentalny cel każdego projektu. Bez jasno zdefiniowanego problemu i sprecyzowanej metody jego rozwiązania, projekt może stać się chaotyczny i nieefektywny. Precyzyjna analiza problemu pozwala na wyznaczenie celów, które prowadzą do stworzenia wartościowego produktu lub usługi. Dzięki temu zespół może skupić się na kluczowych zadaniach i efektywnie zarządzać zasobami. Określenie problemu to pierwszy krok w metodykach Agile i Waterfall, który warunkuje sukces całego przedsięwzięcia.

Pytanie 25

Przedstawione logo praw Creative Commons umożliwia bezpłatne użytkowanie dzieła:

Ilustracja do pytania
A. pod warunkiem udostępnienia go na tej samej zasadzie licencyjnej
B. w celu modyfikacji lub remiksowania
C. w działaniach komercyjnych
D. pod warunkiem zachowania go w oryginalnej formie
To, że odpowiedź dotycząca modyfikacji i remiksowania jest poprawna, wynika bezpośrednio z zasad licencji Creative Commons, a w tym przypadku – oznaczenia BY-NC. Licencja ta pozwala na używanie utworów, w tym także ich przerabianie i tworzenie nowych dzieł pochodnych, pod warunkiem podania autora i nieużywania do celów komercyjnych. W praktyce oznacza to, że możesz wziąć na przykład czyjąś grafikę na tej licencji, przerobić ją, dodać coś od siebie, zrobić z tego plakat na szkolną wystawę lub użyć fragmentu w prezentacji – o ile tylko przestrzegasz warunków. Z mojego doświadczenia wynika, że wiele osób myli się co do tego, że modyfikacja jest zabroniona – a właśnie Creative Commons daje tutaj spore pole do popisu. Zasada remiksowania jest wręcz promowana, bo pozwala rozwijać kulturę. Oczywiście, cały czas trzeba pamiętać o atrybucji twórcy i nie używać dzieła do zarabiania, bo wtedy łamiesz warunki licencji. W środowisku technicznym to jest bardzo praktyczne – możesz wzorować się na czyjejś pracy, rozwijać ją i poprawiać, co w branży IT, grafiki czy edukacji jest na porządku dziennym. Warto też zerkać do oficjalnych wytycznych Creative Commons: one wprost potwierdzają, że modyfikacja i adaptacja są dozwolone przy BY-NC, pod warunkiem braku komercji. W sumie – świetna opcja na rozwój własnych projektów!

Pytanie 26

W zaprezentowanym kodzie stworzono abstrakcyjną klasę Figura oraz klasę Prostokąt, która po niej dziedziczy, zawierającą określone pola i konstruktory. Wskaż najprostszą implementację sekcji /* metody klasy */ dla klasy Prostokąt

Ilustracja do pytania
A. Kod 4
B. Kod 2
C. Kod 1
D. Kod 3
Kod 1 jest prawidłowy ponieważ zapewnia implementację abstrakcyjnych metod Pole i Obwod z klasy Figura co jest wymagane dla każdej klasy dziedziczącej po klasie abstrakcyjnej W Javie kiedy klasa dziedziczy po klasie abstrakcyjnej musi zaimplementować wszystkie jej abstrakcyjne metody Kod 1 definiuje metodę Pole która oblicza pole prostokąta jako iloczyn długości boków a i b oraz metodę Obwod która oblicza obwód jako sumę dwóch razy długości a i dwóch razy długości b Jest to zgodne z konwencjami programowania obiektowego które promują enkapsulację i polimorfizm Kod odnosi się bezpośrednio do konkretnego zastosowania jakim jest obliczanie parametrów prostokąta co jest częstym przypadkiem w programowaniu graficznym oraz w aplikacjach matematycznych Implementacja metod w ten sposób zapewnia prostotę oraz czytelność kodu co jest zgodne z dobrymi praktykami w inżynierii oprogramowania Ponadto dzięki poprawnej implementacji można z powodzeniem rozszerzać funkcjonalność obiektową programu umożliwiając jego łatwiejsze modyfikowanie i rozwijanie w przyszłości

Pytanie 27

Jak zostanie przedstawiony poniższy kod XAML?

Ilustracja do pytania
A. Rysunek 3
B. Rysunek 2
C. Rysunek 4
D. Rysunek 1
W przedstawionym kodzie XAML widoczna jest struktura składająca się z kilku elementów UI ułożonych w pionowym StackLayout co skutkuje wyświetleniem ich w pionowej kolejności. Pierwszym elementem jest Entry z placeholderem Imię a kolejnym Entry z placeholderem Nazwisko co determinuje obecność dwóch pól tekstowych tak jak w Rysunku 4. Następnie w kodzie znajduje się poziomy StackLayout z etykietą Zgoda RODO i przełącznikiem ustawionym na wartość true co oznacza że przełącznik jest domyślnie włączony. To również odpowiada widokowi na Rysunku 4. Kolejny element to Slider z ustawionymi kolorami MinimumTrackColor i MaximumTrackColor co pozwala na zmianę koloru paska suwaka co również jest widoczne w Rysunku 4. Na końcu znajduje się Button z tekstem Zapisz i jest to jedyny przycisk w całym układzie co także zgadza się z Rysunkiem 4. Rozumienie kodu XAML i jego renderowania jest kluczowe w tworzeniu aplikacji mobilnych ponieważ pozwala na precyzyjne określenie wyglądu i funkcjonalności interfejsu użytkownika i jest zgodne z najlepszymi praktykami w projektowaniu UI.

Pytanie 28

Które z wymienionych sformułowań najlepiej definiuje oprogramowanie typu ransomware?

A. Oprogramowanie stosowane do realizacji ataków DDoS
B. Oprogramowanie uniemożliwiające dostęp do danych w celu wymuszenia zapłaty
C. Programy zbierające prywatne dane bez zgody użytkownika
D. Złośliwe aplikacje wyświetlające reklamy
Odpowiedzi wskazujące na inne formy złośliwego oprogramowania, takie jak programy zbierające dane osobowe, oprogramowanie do ataków DDoS oraz złośliwe aplikacje wyświetlające reklamy, są niepoprawne w kontekście definicji ransomware. Programy zbierające dane osobowe działają w celu gromadzenia informacji o użytkownikach, często bez ich zgody, lecz nie mają na celu blokowania dostępu do danych ani wymuszania okupu. Z kolei oprogramowanie stosowane do ataków DDoS (Distributed Denial of Service) ma za zadanie zablokować dostęp do serwisów internetowych poprzez ich przeciążenie, a nie szyfrowanie danych użytkowników. Takie ataki są skierowane na infrastruktury sieciowe lub serwery, co różni się od typowych mechanizmów ransomware, które koncentrują się na lokalnych plikach. Złośliwe aplikacje wyświetlające reklamy, znane jako adware, generują dochody poprzez wyświetlanie niechcianych reklam, co nie ma związku z wymuszaniem okupu ani szyfrowaniem danych. Te rodzaje oprogramowania mają różne cele i metody działania, ale nie są zbliżone do funkcji i skutków ataku ransomware.

Pytanie 29

Programista tworzy system zarządzania buforem drukowania dokumentów. Najnowsze zlecenie drukowania dodawane jest na koniec kolejki, a najstarsze z nich są przekazywane do drukarki. Jaką strukturę danych najłatwiej zastosować w tej sytuacji?

A. LIFO
B. Sterta
C. FIFO
D. Stos
FIFO (First In, First Out) to struktura danych idealnie pasująca do implementacji kolejki wydruku, gdzie zadania są przetwarzane w kolejności ich zgłoszenia. Najstarsze zadanie (pierwsze dodane) jest przetwarzane jako pierwsze, co odwzorowuje rzeczywisty sposób działania kolejek drukowania. FIFO znajduje szerokie zastosowanie w wielu dziedzinach informatyki, takich jak programowanie systemów operacyjnych, zarządzanie buforami oraz implementacja kolejek sieciowych. Dzięki temu zadania są obsługiwane w przewidywalnej kolejności, co jest kluczowe dla zachowania porządku i efektywności przetwarzania.

Pytanie 30

Który z operatorów w języku C++ służy do pobierania adresu zmiennej?

A. *
B. &gt;
C. &amp;
D. delete
Wielka sprawa, że wiesz, że operator '&' w C++ jest do przypisywania adresów zmiennych. Dzięki temu możesz stworzyć wskaźnik, który wskazuje na konkretne miejsce w pamięci, co daje ci dużą moc do manipulowania wartościami. Używając tego operatora, możesz naprawdę dobrze zarządzać pamięcią i poprawić wydajność swojego kodu. Jest to kluczowe, zwłaszcza, gdy pracujesz z dynamiczną alokacją pamięci, albo kiedy iterujesz przez tablice czy tworzysz takie struktury jak listy czy drzewa. To narzędzie jest po prostu super ważne w programowaniu!

Pytanie 31

W przedstawionej ramce znajduje się fragment opisu metody compile języka Java wykorzystywanej w kontekście wyrażeń regularnych. Który symbol powinien być użyty, aby znaleźć dopasowanie na końcu tekstu?

MetacharacterDescription
|Find a match for any one of the patterns separated by | as in: cat|dog|fish
.Find just one instance of any character
^Finds a match as the beginning of a string as in: ^Hello
$Finds a match at the end of the string as in: World$
\dFind a digit
\sFind a whitespace character
\bFind a match at the beginning of a word like this: \bWORD, or at the end of a word like this: WORD\b
\uxxxxFind the Unicode character specified by the hexadecimal number xxxx
Źródło https://www.w3schools.com/java/java_regex.asp dostęp 20.08.2020
A. .
B. ^
C. |
D. $
Znak dolara $ w wyrażeniach regularnych w języku Java jest używany do oznaczenia końca ciągu znaków. Jeśli chcemy sprawdzić, czy konkretny wzorzec występuje na końcu danego tekstu, używamy właśnie tego metaznaku. Przykładowo, wyrażenie regularne World$ dopasuje tekst, w którym słowo World pojawia się na samym końcu. Jest to przydatne w wielu scenariuszach, takich jak walidacja struktury tekstu czy filtrowanie logów, gdzie ważna jest pozycja występowania wzorca. Konwencja ta jest zgodna z ogólnymi standardami regex, co czyni ją intuicyjną i uniwersalną w zastosowaniu. Dolar pełni kluczową rolę w automatyzacji procesów w przetwarzaniu tekstu, umożliwiając efektywne dopasowywanie końcowych wzorców w aplikacjach Java. Użycie $ jest zgodne z dobrymi praktykami kodowania, szczególnie w kontekście walidacji danych wejściowych, gdzie określenie końca ciągu jest często wymagane. Jest to także popularne w analizie danych, gdzie dane muszą spełniać określone kryteria co do ich zakończenia, takie jak rozszerzenia plików czy określone etykiety tekstowe.

Pytanie 32

Jaką instrukcję należy wykorzystać do poprawnej deklaracji zmiennej typu string w C++?

A. int name = "Jan"
B. bool name = "Jan"
C. string name = "Jan"
D. float name = "Jan"
Ta deklaracja 'string name = "Jan"' to naprawdę dobry sposób na zdefiniowanie zmiennej łańcuchowej w C++. Wiesz, 'string' to typ danych, 'name' to nazwa tej zmiennej, a 'Jan' to wartość, która jest jej przypisana. Typ 'string' jest częścią biblioteki <string> i daje nam wiele możliwości, gdy pracujemy z tekstem. Możemy łączyć, porównywać i modyfikować różne łańcuchy znaków bez większego problemu. To jest mega ważne w aplikacjach, które mają do czynienia z danymi tekstowymi, interfejsami użytkownika czy analizą danych, które wprowadzamy.

Pytanie 33

Jakie elementy powinny być zawarte w instrukcji dla użytkownika danej aplikacji?

A. Harmonogram realizacji projektu
B. Wyjaśnienie struktur danych wykorzystywanych w kodzie
C. Informacje o narzędziach programistycznych zastosowanych w procesie tworzenia aplikacji
D. Opis instalacji, konfiguracji oraz obsługi oprogramowania
W instrukcji użytkownika aplikacji warto, żeby był opis tego, jak zainstalować, skonfigurować i korzystać z programu. Taka dokumentacja, pisana krok po kroku, pomaga użytkownikowi przejść przez wszystkie etapy, od pobrania oprogramowania, przez instalację, aż po to, żeby w pełni wykorzystać wszystkie funkcje. Dobrze, żeby były tam też info o wymaganiach systemowych, sposobach radzenia sobie z problemami czy aktualizacjach oprogramowania. Moim zdaniem, taka dokładna instrukcja jest mega ważna, bo zmniejsza szanse na napotkanie kłopotów podczas korzystania z aplikacji i sprawia, że łatwiej jest wdrożyć ją w pracy. Jak użytkownicy mają porządnie napisaną instrukcję, to są bardziej zadowoleni i szybciej przyzwyczajają się do nowego narzędzia.

Pytanie 34

Zapis w języku C# przedstawia definicję klasy Car, która:

public class Car: Vehicle { ... }
A. jest klasą podstawową (nie dziedziczy po innej klasie)
B. używa pól prywatnych klasy Vehicle
C. odziedzicza po Vehicle
D. jest zaprzyjaźniona z klasą Vehicle
Słusznie, zapis public class Car : Vehicle { ... } w języku C# oznacza, że klasa Car dziedziczy po klasie Vehicle. To jest tak zwane dziedziczenie, jeden z fundamentalnych mechanizmów programowania obiektowego. Dzięki temu Car odzyskuje wszystkie publiczne i chronione (protected) człony klasy Vehicle, a dodatkowo może wprowadzać własne składowe albo nadpisywać metody bazowe. Przykładowo, jeśli Vehicle ma metodę Start(), to Car również ją posiada, chyba że ją nadpisze słówkiem override. Moim zdaniem, znajomość dziedziczenia ułatwia projektowanie czytelnych oraz rozszerzalnych systemów, zwłaszcza w większych projektach. W praktyce — jeśli tworzysz aplikację zarządzającą różnymi pojazdami, to możesz mieć np. klasę Vehicle z uniwersalnymi funkcjami i kilka pochodnych (takich jak Car, Truck, Motorcycle), co pozwala trzymać wspólną logikę w jednym miejscu. Warto pamiętać, że w C# jest tylko dziedziczenie pojedyncze jeśli chodzi o klasy (w przeciwieństwie do niektórych innych języków). To też zgodne z SOLID, gdzie jedna klasa powinna mieć jasno określoną odpowiedzialność. Ja często spotykam się z tym podejściem w kodzie produkcyjnym – porządek w strukturze to podstawa, a dziedziczenie bardzo w tym pomaga.

Pytanie 35

Jaki jest zasadniczy cel ataku phishingowego?

A. Uniemożliwienie dostępu do usług internetowych
B. Zbieranie danych osobowych za pomocą podszywających się stron lub wiadomości
C. Zakłócanie pracy sieci przez nadmiarowe zapytania
D. Kradzież haseł z pamięci operacyjnej urządzenia
Głównym celem ataku phishingowego jest przejęcie danych osobowych ofiary, co realizowane jest poprzez wykorzystanie fałszywych stron internetowych lub wiadomości. Atakujący tworzą atrakcyjne i wiarygodne kopie legalnych stron, często podszywając się pod znane instytucje bankowe, portale społecznościowe czy serwisy e-commerce. Użytkownik, nieświadomy zagrożenia, wprowadza swoje dane logowania, numery kart kredytowych lub inne wrażliwe informacje, które trafiają w ręce cyberprzestępców. Aby ułatwić ten proces, phisherzy często wykorzystują techniki inżynierii społecznej, takie jak fałszywe powiadomienia o konieczności weryfikacji konta. Przykłady skutecznych ataków phishingowych obejmują kampanie wysyłania e-maili, które informują użytkowników o rzekomych problemach z kontem, kierując ich na podszyte strony. Standardy bezpieczeństwa, takie jak DMARC, SPF i DKIM, są kluczowe dla ochrony przed tego rodzaju atakami, jednak ich brak lub niewłaściwe wdrożenie zwiększa podatność na phishing.

Pytanie 36

W klasie o nazwie samochod przypisano atrybuty: marka, rocznik, parametry[]. Atrybuty te powinny zostać zdefiniowane jako

A. funkcje
B. metody
C. pola
D. interfejsy
Pola w klasie samochod to właśnie te elementy, które przechowują dane, takie jak marka, rocznik czy tablica parametry. To jest absolutna podstawa programowania obiektowego – najczęściej spotyka się to w językach takich jak Java, C# albo nawet w Pythonie, choć tam często nazywamy je po prostu atrybutami. Dla przykładu, jeśli tworzysz klasę Samochod w C#, to pole 'marka' będzie np. typu string, 'rocznik' – int, a 'parametry' możesz zadeklarować jako tablicę albo listę (List<T>) zależnie od potrzeb. Przechowywanie danych w polach pozwala na lepszą organizację, bo każda instancja klasy ma swoje własne wartości tych pól. Tak się właśnie tworzy modele danych, na których potem operuje cała aplikacja – czy to baza samochodów w warsztacie, czy system ubezpieczeń komunikacyjnych. Takie podejście jest zgodne z zasadami hermetyzacji i solidnych, nowoczesnych standardów pisania kodu. Dużo profesjonalnych frameworków i narzędzi (np. Entity Framework, Hibernate) korzysta z takiego podejścia, nawet jeśli potem te pola opakowujesz w właściwości (properties). Krótko mówiąc, pola to nieodłączny element każdej klasy, która coś reprezentuje, i moim zdaniem nie da się dobrze projektować kodu obiektowego bez zrozumienia tej konwencji.

Pytanie 37

W jaki sposób można załadować tylko komponent z biblioteki React?

A. import { Component } from 'react'
B. import Component from 'react'
C. import [ Component ] from 'react'
D. import React.Component from 'react'
Użycie składni import { Component } from 'react' to zdecydowanie najczęściej spotykany i najbardziej rekomendowany sposób importowania tylko wybranego komponentu z biblioteki React. To tzw. import nazwany, czyli dokładnie wskazujesz, który kawałek kodu chcesz wyciągnąć z całego modułu. W praktyce, jest to bardzo czytelne i pozwala na jasne zarządzanie zależnościami w pliku. Moim zdaniem ma to ogromne znaczenie w większych projektach, bo łatwo potem znaleźć, które elementy są faktycznie wykorzystywane w danym pliku. Co ważne, taka technika importowania jest w pełni zgodna ze standardami ES6, właściwie każdy nowoczesny projekt front-endowy na tym bazuje. Przykład praktyczny: jeśli chcesz stworzyć klasowy komponent React, wystarczy napisać import { Component } from 'react', a potem class MyClass extends Component {...}. Jest to nieco bardziej eleganckie niż importowanie całego obiektu React (np. import React from 'react'), zwłaszcza jeśli nie potrzebujesz całej funkcjonalności. Dodatkowo, takie rozwiązanie może wpływać pozytywnie na bundlowanie kodu, bo nie ściągasz do projektu niepotrzebnych fragmentów biblioteki. Swoją drogą, coraz częściej widać, że programiści skupiają się na minimalizowaniu importów i czytelności kodu – właśnie przez wybór takich rozwiązań.

Pytanie 38

Jaką cechą odznacza się framework w porównaniu do biblioteki?

A. Framework stanowi zbiór funkcji, które programista ma możliwość wykorzystania
B. Framework oferuje funkcje użyteczne w konkretnej dziedzinie problemu
C. Framework zapewnia API do szerszego zestawu funkcji
D. Framework określa strukturę aplikacji i zapewnia jej fundament
Framework dostarcza gotowy szkielet aplikacji i narzuca architekturę, zgodnie z którą programista musi budować swoją aplikację. Oferuje zestaw narzędzi i komponentów, które upraszczają rozwój oprogramowania, przy jednoczesnym ograniczeniu swobody działania. Dzięki frameworkowi, programista nie musi tworzyć aplikacji od podstaw – dostaje narzędzia, które integrują się ze sobą, co przyspiesza proces developmentu i zapewnia spójność aplikacji.

Pytanie 39

Czym jest klasa w programowaniu obiektowym?

A. typ danych
B. zmienna
C. instrukcja
D. wskaźnik
Klasa w programowaniu obiektowym to w praktyce taki szablon, według którego tworzymy konkretne obiekty. To coś jak przepis, dzięki któremu programista może zdefiniować własny, złożony typ danych, opisujący realny byt czy problem. Klasa określa, jakie dane (pola, właściwości) oraz zachowania (metody, funkcje) mają mieć obiekty, które potem powstaną na jej podstawie. Programując w językach takich jak Java, C++ czy Python, właśnie klasy pozwalają nam zamknąć logikę i dane w jednym opakowaniu – to jest jeden z filarów OOP (programowania obiektowego). Moim zdaniem nie da się robić sensownych, skalowalnych projektów bez klas, bo to one pozwalają sensownie ogarnąć złożoność. Przykład? W aplikacji bankowej klasa KontoBankowe może mieć pola typu saldo, numer konta i metody do przelewów. Każde nowe konto to osobny obiekt tego typu, ale wszystkie zachowują się spójnie. Warto przy tym pamiętać, że dobra praktyka nakazuje projektować klasy tak, żeby były jak najbardziej uniwersalne, czyli zgodnie z zasadą DRY (Don’t Repeat Yourself) i SOLID. Często spotykam się z opinią, że klasa to „sztywny typ danych”, ale to nieprawda – dzięki dziedziczeniu czy polimorfizmowi można je elastycznie rozszerzać. Podsumowując, klasa to własny, często złożony typ danych stworzony specjalnie pod potrzeby danej aplikacji – i właśnie za to tak się je ceni.

Pytanie 40

W aplikacji mobilnej, aby określić warianty grafiki w zależności od wielkości ekranu, należy (uwaga: odpowiedzi wariantowe dla dwóch systemów - sugerować się systemem omawianym na zajęciach)

A. iOS: utworzyć katalogi hdpi, lhpi, xhpi i dodać do nich grafiki. Android: utworzyć katalogi 32x32, 64x64, 96x96 i dodać do nich grafiki
B. iOS: dodać do nazw sufiksy oznaczające rozdzielczość, np. 32ppi. Android: umieścić grafikę w odpowiednich katalogach: 32ppi, 64ppi, 96ppi
C. iOS: dodać do nazw sufiksy #2x, #3x. Android: dodać do nazw sufiks rozdzielczości: -32x32, -64x64, -96x96
D. iOS: dodać do nazw plików sufiksy @2x, @3x. Android: umieścić grafikę w odpowiednich folderach drawable: -hdpi, -xhpi, xxhdpi
Lepiej nie używać oznaczeń w stylu 32ppi czy 64ppi, bo to nie pasuje do żadnej z tych platform. To bardziej pasuje do druku, a nie aplikacji mobilnych. Foldery 32x32 czy 64x64 też nie mają sensu w kontekście Androida czy iOS. Jak stworzysz foldery o nazwach lhpi czy 32x32 to może być problem z wyświetlaniem grafiki na różnych urządzeniach. Z mojego doświadczenia, lepiej trzymać się ustalonych standardów, żeby uniknąć błędów.