Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 8 czerwca 2026 08:54
  • Data zakończenia: 8 czerwca 2026 09:25

Egzamin zdany!

Wynik: 30/40 punktów (75,0%)

Wymagane minimum: 20 punktów (50%)

Nowe
Analiza przebiegu egzaminu- sprawdź jak rozwiązywałeś pytania
Pochwal się swoim wynikiem!
Szczegółowe wyniki:
Pytanie 1

Która z poniższych technologii służy do tworzenia aplikacji mobilnych za pomocą języków webowych?

A. ASP.NET Core
B. Spring Boot
C. React Native
D. Django
Spring Boot, ASP.NET Core oraz Django to technologie związane z tworzeniem aplikacji webowych, ale każda z nich ma swoje unikalne zastosowania i nie służy do tworzenia aplikacji mobilnych z użyciem języków webowych. Spring Boot jest frameworkiem opartym na Javie, który upraszcza rozwój aplikacji opartych na architekturze mikroserwisów oraz aplikacji webowych. Jego głównym celem jest uproszczenie procesu konfiguracji i uruchamiania aplikacji backendowych, a nie tworzenie interfejsów użytkownika w środowisku mobilnym. ASP.NET Core to framework od Microsoftu, który umożliwia tworzenie aplikacji internetowych i API w języku C#. Choć jest bardzo elastyczny i może być używany do tworzenia różnych typów aplikacji, nie jest zaprojektowany z myślą o mobilnych interfejsach użytkownika. Z kolei Django to framework oparty na języku Python, który skupia się na szybkim rozwoju aplikacji webowych z wykorzystaniem architektury Model-View-Template. Każda z tych technologii ma swoje miejsce w ekosystemie tworzenia oprogramowania, ale ich zastosowanie w kontekście aplikacji mobilnych jest ograniczone. Typowym błędem myślowym jest mylenie frameworków działających w środowisku serwerowym z technologiami dedykowanymi do rozwoju aplikacji mobilnych. W praktyce, do rozwoju aplikacji mobilnych należy wykorzystywać technologie, które są specjalnie dostosowane do tego celu, takie jak React Native, Flutter czy Xamarin, które oferują nativne rozwiązania i lepszą integrację z platformami mobilnymi.

Pytanie 2

Które z poniższych twierdzeń najlepiej charakteryzuje metodę wirtualną?

A. Metoda, która może być przesłonięta w klasie dziedziczącej
B. Metoda, która może być wywoływana tylko przez klasę nadrzędną
C. Metoda, która jest zawsze stosowana w konstruktorach danej klasy
D. Metoda, która działa wyłącznie dla statycznych pól danej klasy
Metoda, która może być wywoływana tylko przez klasę bazową to raczej metoda prywatna lub chroniona, a nie wirtualna. Metody statyczne są związane z klasą, a nie z konkretnymi obiektami, więc nie można ich tak po prostu nadpisać w klasie pochodnej. A tak w ogóle, metody w konstruktorach zazwyczaj nie są wirtualne, bo wywołanie metod wirtualnych w konstruktorze może prowadzić do dziwnych rzeczy – w konstruktorze klasy bazowej składowe klasy pochodnej jeszcze nie są gotowe.

Pytanie 3

Jakie są kluczowe zasady WCAG 2.0?

A. Ewolucyjna, interaktywna, efektywna
B. Dostosowana, błyskawiczna, mobilna, dostępna
C. Elastyczna, prosta, przejrzysta, trwała
D. Percepcyjna, operacyjna, zrozumiała, solidna
Niepoprawne odpowiedzi nie odzwierciedlają kluczowych zasad WCAG 2.0. Pierwsza z nich, określająca elementy jako postępowe, responsywne, efektywne, nie ujęła fundamentalnych wymogów dotyczących dostępności. Postępowe i responsywne odnoszą się bardziej do designu i wydajności strony, a nie do jej dostępności dla osób z różnymi niepełnosprawnościami. Wymagania dotyczące percepcji i interakcji z treścią są kluczowe dla WCAG 2.0, ale nie są poruszane w tej opcji. Kolejna odpowiedź wskazuje na cechy: dostosowana, szybka, mobilna, dostępna, co również nie odpowiada zasadom WCAG. Użyte terminy nie koncentrują się na dostępności treści, a bardziej na wydajności i dostosowywaniu do urządzeń mobilnych, pomijając kluczowe aspekty związane z percepcją i interaktywnością. Ostatnia niepoprawna odpowiedź, która zawiera elastyczność, prostotę, przejrzystość i trwałość, również nie odpowiada rzeczywistym zasadom WCAG. Choć te cechy są pożądane w projektowaniu stron internetowych, nie są częścią formalnych zasad WCAG, które koncentrują się na konkretnej dostępności treści dla osób z ograniczeniami. W rezultacie, te odpowiedzi nie spełniają wymaganych kryteriów dostępności.

Pytanie 4

Co to jest SPA (Single Page Application)?

A. Aplikacja webowa działająca na jednej stronie, dynamicznie aktualizująca treść bez przeładowywania całej strony
B. Metoda projektowania interfejsu użytkownika dla aplikacji mobilnych
C. Format pliku używany w aplikacjach do przetwarzania danych
D. Technika optymalizacji kodu w aplikacjach JavaScript
Single Page Application (SPA) to typ aplikacji internetowej, która działa na jednej stronie, umożliwiając dynamiczne ładowanie treści bez konieczności przeładowania całej witryny. W tradycyjnych aplikacjach webowych, każda interakcja użytkownika, która wymagała zmiany treści, wiązała się z odświeżeniem strony. W przypadku SPA, korzysta się z technologii takich jak AJAX, WebSockets czy API, co pozwala na asynchroniczne pobieranie danych z serwera. Przykłady SPA to popularne frameworki i biblioteki, takie jak React, Angular czy Vue.js. Dzięki tym technologiom, użytkownicy mogą doświadczyć płynniejszego i bardziej responsywnego interfejsu. Dobrą praktyką w projektowaniu SPA jest stosowanie wzorców projektowych, takich jak MVC (Model-View-Controller), co ułatwia zarządzanie kodem oraz jego modułowość. SPA są szczególnie przydatne w aplikacjach wymagających intensywnej interakcji, takich jak platformy e-commerce czy aplikacje społecznościowe, gdzie kluczowa jest szybkość i komfort użytkowania.

Pytanie 5

Który z faz cyklu życia projektu wiąże się z identyfikacją wymagań użytkownika?

A. Analiza
B. Wdrażanie
C. Przeprowadzanie testów
D. Etap planowania
Analiza to etap cyklu życia projektu, podczas którego określane są wymagania użytkownika. W tej fazie zespół projektowy przeprowadza badania, konsultacje i warsztaty, aby zrozumieć potrzeby klienta i użytkowników końcowych. Wynikiem analizy jest szczegółowa specyfikacja funkcjonalna i niefunkcjonalna, która stanowi podstawę do projektowania i implementacji. Prawidłowo przeprowadzona analiza minimalizuje ryzyko nieporozumień oraz zapewnia, że finalny produkt będzie odpowiadał na realne potrzeby użytkowników.

Pytanie 6

Aby wykorzystać framework Django, należy pisać w języku

A. C#
B. Python
C. JavaScript
D. Java
Czasami można się pomylić, bo widząc te wszystkie języki jak Java, C# czy JavaScript, łatwo założyć, że każdy framework webowy działa podobnie i może bazować na różnych technologiach. Jednak Django to nie jest uniwersalny framework na każdą platformę czy język. C# i Java są oczywiście bardzo popularne w środowiskach enterprise, służą do tworzenia rozbudowanych aplikacji biznesowych, ale mają swoje własne frameworki, jak ASP.NET dla C# czy Spring dla Javy. Próba wykorzystania Django z C# lub Javą to jak próba włożenia okrągłego klocka do kwadratowego otworu – po prostu nie pasuje, bo Django ma zupełnie inne API i korzysta z mechanizmów charakterystycznych dla Pythona. JavaScript natomiast, choć jest niezbędny we front-endzie i pozwala budować dynamiczne interfejsy użytkownika (szczególnie przy użyciu Reacta, Angulara czy Vue), nie jest wykorzystywany do pisania logiki serwera w Django. Owszem, istnieje Node.js, który pozwala na backend w JavaScript, ale to zupełnie inna bajka. Typowym błędem myślowym jest też zakładanie, że frameworki webowe są zamienne i można je „przełączyć” między językami – praktyka pokazuje, że każdy framework jest głęboko zintegrowany z konkretnym językiem, jego bibliotekami i narzędziami. Django powstał dla Pythona i tylko w tym języku można w pełni wykorzystać jego możliwości. Uważam, że warto zagłębić się w dokumentację i zobaczyć, jak wygląda kod przykładowych aplikacji – szybko widać, że całość bazuje na Pythonie, łącznie z konfiguracją, obsługą modeli i migracjami bazy danych. W profesjonalnych projektach przestrzega się tej zasady i nie próbuje się na siłę mieszać środowisk, tylko korzysta z narzędzi zgodnych z wybranym językiem.

Pytanie 7

Co zostanie wyświetlone po wykonaniu poniższego kodu?

function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  return `Hello, ${this.name}!`;
};

const person = new Person('John');
console.log(person.sayHello());
A. Hello, undefined!
B. Hello, [object Object]!
C. TypeError: person.sayHello is not a function
D. Hello, John!
Wynik działania podanego kodu to 'Hello, John!'. Dzieje się tak, ponieważ tworzony jest obiekt 'person' z konstruktora 'Person', który przypisuje wartość 'John' do właściwości 'name'. Metoda 'sayHello' zdefiniowana w prototypie klasy 'Person' wykorzystuje szablon literowy (template literal), aby zwrócić powitanie, wstawiając wartość 'name' obiektu. To podejście jest zgodne z dobrymi praktykami programowania w JavaScript, ponieważ wykorzystuje prototypy do dzielenia się metodami pomiędzy instancjami obiektów. W praktyce, takie rozwiązania pozwalają na oszczędność pamięci i zwiększają wydajność, gdyż wszystkie instancje korzystają z tej samej metody, a nie mają osobnych kopii. Przykładowo, jeśli chcielibyśmy dodać więcej osób, wystarczy utworzyć nowe instancje 'Person' bez konieczności powielania kodu metody 'sayHello'.

Pytanie 8

Zasada programowania obiektowego, która polega na ukrywaniu elementów klasy tak, aby były one dostępne wyłącznie dla metod tej klasy lub funkcji zaprzyjaźnionych, to

A. dziedziczenie
B. hermetyzacja
C. wyjątki
D. polimorfizm
W programowaniu obiektowym często pojawiają się takie pojęcia jak wyjątki, polimorfizm czy dziedziczenie, ale żadne z nich nie opisuje procesu ukrywania danych wewnątrz klasy. Wyjątki to mechanizm obsługi błędów, który pozwala na reagowanie na nieprzewidziane sytuacje w trakcie działania programu, ale nie ma on nic wspólnego z kontrolą dostępu do danych czy zabezpieczaniem pól klasy. Polimorfizm z kolei polega na tym, że obiekty różnych klas mogą być traktowane jako obiekty wspólnej klasy bazowej – tu chodzi o możliwość wywoływania metod w taki sam sposób na różnych typach, co ułatwia projektowanie elastycznego kodu, ale nie dotyka kwestii ukrywania szczegółów przed użytkownikiem klasy. Dziedziczenie umożliwia tworzenie nowych klas na podstawie już istniejących, co pozwala na przejmowanie właściwości i metod, ale samo w sobie nie ogranicza dostępu do danych – wręcz przeciwnie, nieumiejętne użycie dziedziczenia może prowadzić do nadmiernego ujawnienia szczegółów implementacji. Typowym błędem myślowym jest mylenie hermetyzacji z samą ochroną przed błędami (czyli wyjątkami) lub utożsamianie jej z mechanizmami dziedziczenia – tymczasem hermetyzacja to przede wszystkim kontrola dostępu i świadome ograniczanie widoczności danych oraz metod. W codziennej praktyce programistycznej hermetyzacja jest kluczowa dla bezpieczeństwa, utrzymania i rozwoju oprogramowania, dlatego warto rozróżniać te koncepcje i wiedzieć, do czego służy każda z nich.

Pytanie 9

Modyfikator dostępu, który znajduje się przed definicją metody Dodaj() w klasie Kalkulator, powoduje, że

protected void Dodaj() {}
A. jest ona dostępna w programie głównym i może być wywoływana na rzecz instancji klasy Kalkulator
B. nie jest ona dostępna z poziomu klas zaprzyjaźnionych z klasą Kalkulator
C. nie jest ona dostępna w klasach, które dziedziczą po klasie Kalkulator
D. jest ona dostępna zarówno wewnątrz klasy, jak i w klasach dziedziczących po klasie Kalkulator
Modyfikator dostępu protected jest kluczowym elementem programowania obiektowego, umożliwiającym kontrolę nad widocznością i dostępem do składników klasy. Gdy metoda jest oznaczona jako protected, jak w przypadku metody Dodaj() w klasie Kalkulator, oznacza to, że jest ona dostępna nie tylko w ramach tej klasy, ale również w dowolnych klasach, które dziedziczą po klasie Kalkulator. To podejście wspiera koncepcję dziedziczenia, umożliwiając klasom potomnym korzystanie z funkcjonalności klasy bazowej bez konieczności ponownego definiowania metod. Na przykład, jeśli stworzymy klasę DziecięcyKalkulator dziedziczącą po Kalkulator, metoda Dodaj() będzie dostępna w tej klasie potomnej. Takie rozwiązanie jest często stosowane w projektach, gdzie istnieje potrzeba rozszerzania funkcjonalności bazowych klas bez naruszania ich enkapsulacji. Dobre praktyki programistyczne sugerują stosowanie protected tam, gdzie chcemy umożliwić dziedziczenie oraz uniknąć nadmiernego udostępniania elementów klasy zewnętrznym użytkownikom. Dzięki temu kod staje się bardziej modularny i elastyczny, co jest istotne w dużych projektach programistycznych. Zrozumienie roli modyfikatorów dostępu, takich jak protected, jest kluczowe dla efektywnego projektowania i implementacji systemów obiektowych.

Pytanie 10

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

A. string name = "Jan"
B. bool name = "Jan"
C. float name = "Jan"
D. int 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 11

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

Ilustracja do pytania
A. w celu modyfikacji lub remiksowania
B. w działaniach komercyjnych
C. pod warunkiem zachowania go w oryginalnej formie
D. pod warunkiem udostępnienia go na tej samej zasadzie licencyjnej
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 12

Co to jest CSS Grid?

A. Metoda optymalizacji plików CSS dla lepszej wydajności strony
B. Biblioteka komponentów wizualnych dla aplikacji webowych
C. Dwuwymiarowy system układu elementów na stronie opary na siatkach
D. Format plików graficznych obsługiwany przez CSS3
CSS Grid to nowoczesny, dwuwymiarowy system układu elementów na stronie internetowej, który umożliwia projektantom i deweloperom łatwe i elastyczne tworzenie skomplikowanych układów. Dzięki CSS Grid możemy definiować zarówno kolumny, jak i wiersze, co pozwala na precyzyjne umieszczanie elementów w kontekście całego układu. Przykładem zastosowania CSS Grid może być stworzenie responsywnej galerii zdjęć, gdzie można łatwo zmieniać liczbę kolumn w zależności od szerokości ekranu. CSS Grid jest zgodny z najnowszymi standardami W3C i stał się kluczowym elementem w nowoczesnym web designie. Dzięki właściwościom takim jak grid-template-areas, grid-template-columns, czy grid-auto-rows, projektanci mogą w intuicyjny sposób organizować treści, co poprawia zarówno estetykę, jak i użyteczność stron. Ponadto, korzystanie z CSS Grid pozwala na zmniejszenie zależności od zewnętrznych bibliotek JavaScript do układania elementów, co podnosi wydajność i usprawnia proces tworzenia stron.

Pytanie 13

Który z wymienionych typów stanowi przykład typu znakowego?

A. boolean
B. string
C. char
D. float
Typ 'string' to struktura lub klasa, która przechowuje sekwencję znaków, a nie pojedynczy znak. 'Boolean' przechowuje wartości logiczne 'true' lub 'false', a nie znaki. 'Float' przechowuje liczby zmiennoprzecinkowe i jest używany w operacjach matematycznych, a nie w przetwarzaniu tekstu czy znaków. Typ 'char' różni się od 'string' tym, że przechowuje dokładnie jeden znak, podczas gdy 'string' może zawierać wiele znaków.

Pytanie 14

Który z poniższych przypadków stanowi test niefunkcjonalny?

A. Sprawdzenie obsługi formularza rejestracji
B. Weryfikacja poprawności logowania użytkownika
C. Testowanie wydajności aplikacji pod dużym obciążeniem
D. Sprawdzenie działania przycisku
Testowanie wydajności aplikacji pod dużym obciążeniem to przykład testu niefunkcjonalnego. Jego celem jest ocena, jak aplikacja zachowuje się przy dużej liczbie użytkowników lub operacji jednocześnie. Testy te pozwalają na identyfikację wąskich gardeł i optymalizację kodu oraz infrastruktury serwerowej. W ramach testów obciążeniowych analizowane są parametry takie jak czas odpowiedzi, zużycie zasobów (CPU, RAM) oraz stabilność aplikacji w warunkach skrajnego obciążenia. Testowanie wydajności jest kluczowe w aplikacjach webowych, e-commerce oraz systemach o dużej liczbie transakcji, gdzie każdy przestój może generować straty finansowe i negatywnie wpływać na doświadczenia użytkownika.

Pytanie 15

Jakie kwestie związane z percepcją są uwzględnione w rekomendacjach standardu WCAG 2.0?

A. zapewnienia odpowiedniego czasu na zapoznanie się i przetworzenie informacji
B. prezentacji elementów interfejsu użytkownika
C. jasności i dokładności w dostarczonych treściach na stronie
D. umożliwienia interakcji między elementami użytkownika za pomocą klawiatury
Prezentacja elementów interfejsu użytkownika to kluczowy aspekt rekomendacji WCAG 2.0 związanych z percepcją. Standard ten mocno akcentuje, by każdy użytkownik, niezależnie od swoich możliwości, miał szansę prawidłowo odbierać to, co się wyświetla na stronie. Jeśli coś jest przedstawione tylko kolorem albo opiera się wyłącznie na bodźcach wizualnych, to osoby niewidome albo z zaburzeniami wzroku po prostu nie będą w stanie tego odebrać. W praktyce chodzi o takie rzeczy jak odpowiedni kontrast tekstu do tła, jasność przekazu ikon, czy czytelność nawigacji, nawet jeśli ktoś korzysta z czytnika ekranu. Moim zdaniem, naprawdę dobrym przykładem są formularze: jeżeli pole błędnie wypełnione jest tylko podświetlone na czerwono, to nie każdy to zauważy, więc trzeba też dodać np. komunikat tekstowy. Dobrze, jeśli projektant myśli o wszystkich użytkownikach, nie tylko o tych, którzy widzą i słyszą idealnie. WCAG podpowiada, by nie polegać na samych kolorach, stosować czytelne czcionki, zapewniać jasną strukturę nagłówków – wszystko po to, by każdy mógł się połapać w tym, co widzi na stronie. Z mojego doświadczenia wynika, że uwzględnienie tych zasad nie tylko poprawia dostępność, ale ogólnie podnosi jakość user experience. Warto o tym pamiętać nawet przy najprostszych projektach.

Pytanie 16

Która z poniższych informacji o pojęciu obiekt jest prawdziwa?

A. obiekt pozwala na zdefiniowanie klasy
B. obiekt jest instancją klasy
C. obiekt oraz klasa są identyczne
D. obiekt to typ złożony
W programowaniu obiektowym pojęcie obiektu i klasy jest często mylone, co prowadzi do różnych nieporozumień w kodowaniu. Często spotykam się z poglądem, że obiekt to typ złożony – i choć obiekt może agregować wiele pól oraz metod, to sam w sobie nie jest typem, a instancją konkretnego typu, czyli klasy. Klasa określa strukturę i zachowania, natomiast obiekt to jej 'żywa' realizacja w pamięci komputera. Z kolei pomysł, że obiekt oraz klasa są identyczne, to moim zdaniem jeden z najbardziej mylących błędów – klasa to definicja, a obiekt jest konkretnym bytem utworzonym na jej podstawie. To trochę jak przepis na ciasto i upieczone ciasto – przepis możesz mieć wiele razy, ale każdy wypiek jest osobny. Wreszcie, przekonanie, że obiekt pozwala na zdefiniowanie klasy, odwraca naturalną hierarchię tej koncepcji. To klasa jest tworzona najpierw, a obiekty powstają później, jako jej instancje. Takie odwrócenie kolejności myślenia może prowadzić do niepraktycznego podejścia w projektowaniu oprogramowania. Typowym błędem jest też traktowanie obiektów jak statycznych struktur danych, bez zrozumienia, że to one nadają żywotność programowi, korzystają z polimorfizmu czy enkapsulacji. W realnych projektach, prawidłowe rozumienie rozróżnienia pomiędzy klasą a obiektem jest kluczowe do osiągania elastyczności, skalowalności i czytelności kodu. Z mojego punktu widzenia, błędne utożsamianie tych pojęć często prowadzi do trudnych do utrzymania aplikacji oraz nieefektywnego wykorzystania zalet paradygmatu obiektowego.

Pytanie 17

Jakie wartości jest w stanie przechować zmienna o typie logicznym?

A. Jedną z dwóch opcji: true lub false
B. Dowolną liczbę rzeczywistą
C. Tylko ciąg znaków
D. Wartość w reprezentacji binarnej
Zmienna typu logicznego (boolean) może przechowywać jedną z dwóch wartości: 'true' lub 'false'. Są to podstawowe wartości wykorzystywane w operacjach warunkowych i pętlach, które decydują o przepływie sterowania w programach. Wartości logiczne są kluczowe w konstrukcjach takich jak 'if-else', pętlach 'while' oraz w porównaniach. W wielu językach programowania 'true' jest równoznaczne z 1, a 'false' z 0, co pozwala na łatwą integrację z typami całkowitymi. Typ boolean jest niezbędny w programowaniu, umożliwiając implementację decyzji, walidacji danych i automatyzacji procesów.

Pytanie 18

Wykorzystując React.js oraz Angular, stworzono funkcjonalnie równoważne kody źródłowe. Aby móc w metodzie handleSubmit pokazać zawartość kontrolki input w miejscu oznaczonym ???, należy odwołać się do atrybutu o nazwie:
React.js:

nazwa1 = React.createRef();
handleSubmit = e => {
    console.log(this.???.current.value);
}
...
<form onSubmit={this.handleSubmit}>
    <input ref={this.nazwa1} name="nazwa2" id="nazwa3" for="nazwa4" />
Angular:
<form #f="ngForm" (ngSubmit) = "handleSubmit(f)">
    <input ngModel name="nazwa1" id="nazwa2" class="nazwa3" for="nazwa4" >
...
handleSubmit(f) {
    console.log(f.value.???);
}
A. nazwa4
B. nazwa1
C. nazwa3
D. nazwa2
To właśnie nazwa1 jest właściwym atrybutem, do którego trzeba się odwołać, żeby wyciągnąć wartość inputa zarówno w React, jak i w Angularze. W React, kiedy chcemy pobrać wartość z inputa przez refa, to przekazujemy ref={this.nazwa1}, a potem w handleSubmit robimy this.nazwa1.current.value. To po prostu dokładnie ta sama nazwa, którą przypisałeś do refa, nie ma tu żadnej magii. W Angularze z kolei input posiada ngModel oraz name="nazwa1" – i to name jest kluczowe, bo obiekt f.value generowany przez ngForm zawiera wszystkie pola po kluczach odpowiadających atrybutom name. Dzięki temu możesz potem użyć f.value.nazwa1 i dostajesz wartość inputa. W praktyce zawsze warto pilnować, żeby atrybut name był sensowny i jednoznaczny, bo to na nim opierają się frameworki przy serializacji danych formularza i obsłudze ich stanu. Moim zdaniem to jest jedna z bardziej praktycznych umiejętności przy pracy z dynamicznymi formularzami – jeśli ktoś nie dba o spójność nazw atrybutów name, to łatwo o błędy, które są potem trudne do wykrycia. Warto jeszcze pamiętać, że atrybuty typu id, class czy for mają zupełnie inne zastosowanie – służą do stylowania, powiązań z labelkami, itd. Name natomiast to podstawa logicznej obsługi wartości pól formularza. Często spotykam się z sytuacjami, że ktoś próbuje pobierać dane po id czy class, ale to nie jest zgodne z dobrymi praktykami – dla czytelności kodu i łatwości refaktoryzacji o wiele lepiej korzystać z name. Takie rozwiązania są też zalecane w oficjalnej dokumentacji zarówno React, jak i Angulara.

Pytanie 19

Który z poniższych metod najlepiej zabezpiecza dane karty płatniczej podczas zakupów online?

A. Podawanie informacji o karcie w odpowiedzi na wiadomość e-mail od nieznajomego
B. Udostępnianie danych karty na platformach internetowych
C. Przechowywanie numeru karty w przeglądarce internetowej
D. Używanie wirtualnych kart płatniczych lub jednorazowych kodów
Korzystanie z wirtualnych kart płatniczych lub jednorazowych kodów to skuteczny sposób na ochronę danych karty płatniczej podczas transakcji internetowych. Wirtualne karty mają ograniczony okres ważności i są powiązane z określoną kwotą, co minimalizuje ryzyko kradzieży całego konta bankowego. Jednorazowe kody płatności wygasają po jednorazowym użyciu, co uniemożliwia ich ponowne wykorzystanie przez osoby trzecie. Dzięki tym metodom użytkownicy znacznie redukują ryzyko oszustw i nieautoryzowanych transakcji.

Pytanie 20

Przedstawiony na filmie kod napisany w języku C++ nie kompiluje się. Co należy zmienić w tym kodzie, aby proces kompilacji wykonał się bez błędów?

A. dodać deklarację funkcji sprawdz przed funkcją main
B. zadeklarować zmienną sprawdz przed jej wykorzystaniem w linii 11
C. poprawnie zapisać warunek w instrukcji if w linii 11, np. sprawdz(x)==true
D. naprawić błąd w funkcji sprawdz, który polega na braku nawiasów {} w pętli for
Odpowiedź jest trafna, bo w języku C++ kompilator musi wiedzieć o istnieniu funkcji zanim zostanie ona użyta w kodzie, np. w funkcji main. Bez wcześniejszej deklaracji, kompilator nie zna sygnatury funkcji i nie potrafi zweryfikować wywołania, co skutkuje błędem typu 'implicit declaration of function'. Deklaracja funkcji to taki sygnał informujący kompilator „hej, taka funkcja będzie i będzie przyjmować takie argumenty, a zwracać taki typ”. Praktycznie rzecz biorąc, przed funkcją main wystarczy wpisać np. 'bool sprawdz(int x);', żeby wszystko grało. To szczególnie ważne przy większych projektach czy pracy w zespołach, gdzie pliki nagłówkowe z deklaracjami funkcji są standardem. Pozwala to na lepszą czytelność i porządek w kodzie – kompilator wie, czego się spodziewać, a Ty unikasz dziwnych, trudnych do znalezienia błędów. Moim zdaniem taka organizacja kodu to podstawa, szczególnie jeśli kiedyś będziesz korzystać z bibliotek lub cudzych funkcji – deklaracje są wtedy wręcz obowiązkowe. To zasada, której trzyma się większość zespołów programistycznych i, szczerze mówiąc, sam kilka razy w młodości zapomniałem o deklaracji, przez co debugowanie trwało wieki. Warto od razu wyrobić sobie taki nawyk, bo to oszczędza sporo nerwów i czasu, a kod staje się solidniejszy i bardziej profesjonalny.

Pytanie 21

Jakiego kodu dotyczy treść wygenerowana w trakcie działania programu Java?

Ilustracja do pytania
A. Kodu 3
B. Kodu 1
C. Kodu 4
D. Kodu 2
W przypadku kodu 4 mamy do czynienia z operatorem modulo zastosowanym na zmiennych x i y. Wiąże się to z próbą podziału przez zero co w języku Java skutkuje wygenerowaniem wyjątku java.lang.ArithmeticException. Przykładowo jeśli y wynosi zero to operacja x % y jest niedozwolona i spowoduje wyjątek. Rozumienie jak bezpiecznie wykonywać operacje arytmetyczne w Javie jest kluczowe dla unikania takich błędów. Zgodnie z dobrymi praktykami należy zawsze sprawdzać wartości zmiennych przed wykonaniem operacji matematycznych które mogą prowadzić do błędów wykonania programu. Ważne jest aby stosować techniki obsługi wyjątków try-catch które pozwalają na przechwycenie i odpowiednie zarządzanie błędami. Używanie odpowiednich testów jednostkowych może pomóc w wcześniejszym wykryciu takich problemów co jest standardem w branży programistycznej. Zrozumienie obsługi błędów w programowaniu pozwala na tworzenie bardziej niezawodnych i odpornych na błędy aplikacji co jest istotnym aspektem pracy profesjonalnego programisty.

Pytanie 22

Który z poniższych opisów najlepiej charakteryzuje Node.js?

A. System zarządzania bazami danych NoSQL
B. Biblioteka do tworzenia interfejsów użytkownika w aplikacjach webowych
C. Framework do budowania aplikacji mobilnych przy użyciu JavaScript
D. Środowisko uruchomieniowe JavaScript poza przeglądarką, używające silnika V8 z Chrome
Node.js to środowisko uruchomieniowe JavaScript, które działa na serwerze, a nie tylko w przeglądarkach. Jest zbudowane na silniku V8, który jest również używany w przeglądarce Google Chrome. Dzięki temu, Node.js pozwala na wykonywanie kodu JavaScript na serwerze, co otwiera nowe możliwości dla programistów. Aplikacje napisane w Node.js są zazwyczaj asynchroniczne i oparte na zdarzeniach, co sprawia, że są one wydajne i responsywne. Przykłady zastosowania Node.js obejmują tworzenie serwisów webowych, API oraz aplikacji w czasie rzeczywistym, jak czaty czy gry online. Node.js zapewnia również bogaty ekosystem bibliotek i frameworków, takich jak Express.js, co pozwala na szybkie i efektywne tworzenie aplikacji. Zastosowanie standardów, takich jak RESTful API, w połączeniu z architekturą mikroserwisów, jest przykładami dobrych praktyk przy używaniu Node.js w projektach komercyjnych.

Pytanie 23

Co będzie wynikiem działania poniższego kodu SQL?

SELECT COUNT(*)
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
A. Liczba pracowników z najwyższą pensją
B. Liczba pracowników z pensją powyżej średniej
C. Błąd składni SQL
D. Średnia pensja wszystkich pracowników
Odpowiedź, że wynik działania zapytania SQL to liczba pracowników z pensją powyżej średniej, jest całkowicie poprawna. Zapytanie to korzysta z funkcji agregującej COUNT(*), która zlicza liczbę rekordów spełniających określony warunek. W tym przypadku warunkiem jest, że pensja pracownika jest większa od średniej pensji wszystkich pracowników, którą obliczamy za pomocą wewnętrznego zapytania (subquery). Tego rodzaju operacje są powszechnie stosowane w analizie danych w bazach danych, gdzie często musimy wykonać porównania względem wartości agregatów, takich jak średnia, mediana czy suma. Przykładowo, w analizie wynagrodzeń w danej firmie, można użyć podobnych zapytań do oceny, jaki odsetek pracowników jest wynagradzanych powyżej średniej, co może być istotne z punktu widzenia polityki płacowej oraz budżetowania. Pamiętaj, że dobre praktyki w pracy z bazami danych obejmują optymalizację zapytań oraz unikanie niepotrzebnych obliczeń, co może wpłynąć na wydajność systemu.

Pytanie 24

Co to jest XSS (Cross-Site Scripting)?

A. Technika optymalizacji kodu JavaScript do zwiększenia wydajności strony
B. Protokół komunikacyjny używany w aplikacjach internetowych
C. Framework do tworzenia responsywnych stron internetowych
D. Luka bezpieczeństwa pozwalająca na wstrzyknięcie złośliwego kodu do stron przeglądanych przez innych użytkowników
Cross-Site Scripting (XSS) to luka bezpieczeństwa, która umożliwia atakującym wstrzykiwanie złośliwego kodu JavaScript do stron internetowych, które są następnie przeglądane przez innych użytkowników. W wyniku tego ataku, złośliwy kod może być wykonany w kontekście przeglądarki ofiary, co może prowadzić do kradzieży sesji, danych osobowych, czy też przejęcia kontroli nad kontem użytkownika. Aby zapobiegać XSS, programiści powinni stosować techniki takie jak walidacja i oczyszczanie danych wejściowych, a także korzystanie z nagłówków HTTP, takich jak Content Security Policy (CSP). Przykładem może być sytuacja, gdy aplikacja webowa przyjmuje dane w formularzach bez odpowiedniego sprawdzenia, co pozwala na umieszczenie skryptu, który zyskuje dostęp do cookies użytkownika. Zrozumienie i zabezpieczenie się przed XSS jest kluczowe w kontekście budowania bezpiecznych aplikacji webowych, co jest zgodne z najlepszymi praktykami branżowymi.

Pytanie 25

Przedstawione kody zawierają realizację funkcji oraz jeden zdefiniowany test automatyczny, który weryfikuje działanie funkcji w przypadku, gdy argumentem jest liczba ujemna. W miejsce kropek należy dodać drugi test, który sprawdzi funkcjonalność funkcji, kiedy argumentem jest liczba dodatnia. Który z poniższych kodów jest odpowiedni do tego testu?

export function fun1(number) {
    if (number < 0)
        number = number * (-1);
    return number;
}
describe('fun1', () => {
    it('test1', () => {
        const result = fun1(-1);
        expect(result).toBe(1);
    })
    ...
})
it('test2', () => {
    const result = fun1(1);
    expect(result).toBe(result+1);
})
A.
it('test2', () => {
    const result = fun1(2);
    expect(result).toBe(-2);
})
B.
it('test2', () => {
    const result = fun1(2);
    expect(result).toBe(2);
})
C.
it('test2', () => {
    const result = fun1(1);
    expect(result).toBe(-1);
})
D.
A. Odpowiedź A
B. Odpowiedź B
C. Odpowiedź D
D. Odpowiedź C
Poprawna odpowiedź to C ponieważ funkcja fun1 zwraca liczbę taką jaka jest z wyjątkiem sytuacji gdy liczba jest ujemna wtedy zwraca jej wartość bezwzględną Test C sprawdza wartość dodatnią 2 gdzie rezultat jest zgodny z oczekiwaniami i funkcja zwraca 2 co jest poprawnym wynikiem To testowanie zgodne z zasadą jednostkowych testów gdzie ważne jest aby funkcje były testowane na różne przypadki brzegowe w tym na wartości ujemne i dodatnie Implementacja jednostkowych testów pozwala na automatyczne sprawdzanie poprawności działania kodu co jest dobrą praktyką w programowaniu Szczególnie ważne jest aby testować funkcje krytyczne i te które mają potencjał do wystąpienia błędów związanych z nieoczekiwanymi danymi wejściowymi Przykład ten pokazuje jak ważne jest aby testy były dokładne i pokrywały różnorodne scenariusze użytkowania co pozwala na wczesne wychwycenie błędów i zapewnienie stabilności aplikacji W tej sytuacji testując wartość 2 zapewniamy że funkcja zachowuje się poprawnie dla wartości dodatnich co jest zgodne z oczekiwaniami programistycznymi

Pytanie 26

Jaką wydajność posiada sieć, która przesyła 500 MB danych w czasie 10 sekund?

A. 40 Mbps
B. 50 Mbps
C. 400 Mbps
D. 500 Mbps
Na pierwszy rzut oka mogłoby się wydawać, że 50 Mbps to rozsądny wynik, ponieważ 500 MB w 10 sekund to duża ilość danych, ale jeśli przeliczymy jednostki poprawnie, szybko zauważymy błąd. Wynik 50 Mbps oznaczałby, że w ciągu 10 sekund przesyłamy jedynie 500 megabitów, czyli około 62,5 MB danych. To znacznie mniej niż 500 MB, więc taka przepustowość byłaby zdecydowanie zbyt mała, aby przesłać taką ilość danych w podanym czasie. Z kolei odpowiedź 500 Mbps sugeruje przepustowość większą niż w rzeczywistości. Gdyby sieć miała taką wydajność, to w ciągu 10 sekund przesłałaby aż 625 MB danych (500 Mb/s × 10 s = 5000 Mb = 625 MB), czyli więcej niż w zadaniu. Oznacza to, że taka prędkość byłaby zawyżona w stosunku do faktycznej wartości. Natomiast 40 Mbps jest niepoprawne, gdyż oznaczałoby możliwość przesłania jedynie 400 megabitów w 10 sekund, co odpowiada zaledwie 50 MB danych. To prawie dziesięć razy mniej niż rzeczywista ilość danych w zadaniu, więc sieć o takiej przepustowości nie byłaby w stanie wykonać transmisji w podanym czasie. Wszystkie te błędne odpowiedzi wynikają z nieprawidłowego przeliczenia jednostek lub braku uwzględnienia faktu, że bajty należy zamienić na bity przed obliczeniem przepustowości. Tylko wynik 400 Mbps jest zgodny z zasadami i poprawnym przeliczeniem danych.

Pytanie 27

Jakie znaczenie ma termin "przesłanianie metody" w kontekście programowania obiektowego?

A. Tworzenie nowej metody w klasie bazowej
B. Zmiana metody prywatnej na metodę publiczną
C. Zastosowanie tej samej nazwy metody w klasie bazowej i pochodnej, ale z inną implementacją w klasie pochodnej
D. Przenoszenie metod z jednej klasy do drugiej
Przesłanianie metody to mechanizm, w którym metoda w klasie pochodnej ma taką samą nazwę, typ zwracany i listę parametrów jak metoda w klasie bazowej, ale zawiera inną implementację. To kluczowy element polimorfizmu, umożliwiający dostosowanie zachowania klasy pochodnej do jej specyficznych potrzeb, przy zachowaniu spójnego interfejsu. Przesłanianie metod pozwala na elastyczne projektowanie kodu i jest szeroko stosowane w dużych projektach, aby umożliwić rozszerzalność oraz ponowne wykorzystanie istniejącej logiki. W C++ przesłanianie osiąga się za pomocą słowa kluczowego 'virtual' w klasie bazowej, a następnie redefinicji metody w klasie pochodnej.

Pytanie 28

Wskaż uproszczoną wersję kodu XAML dla elementów w pokazanym oknie dialogowym?

Ilustracja do pytania
A. Kod 3
B. Kod 1
C. Kod 4
D. Kod 2
Dobrze jest znać podstawowe różnice pomiędzy ListBox, ComboBox, CheckBox, RadioButton oraz Label w XAML. W tym oknie dialogowym widać wyraźnie, że po lewej stronie użytkownik ma możliwość wyboru gatunku zwierzęcia spośród kilku opcji wyświetlonych jednocześnie. Takie zadanie najlepiej spełnia ListBox, bo umożliwia wygodną selekcję z widocznej listy. U góry po prawej jest pole tekstowe do wpisania imienia zwierzaka, więc TextBox jak najbardziej pasuje. Poniżej mamy dwa pola wyboru – „Zaszczepiony?” i „Na diecie?” – to są typowe przypadki na CheckBoxy: można zaznaczyć dowolne lub oba naraz. Kluczowe jest to, że CheckBox pozwala użytkownikowi wybrać dowolną kombinację, a nie tylko jedną opcję jak RadioButton. Z mojego doświadczenia często początkujący mylą ComboBox z ListBoxem, ale tu akurat lista jest zawsze widoczna, co jest typowe dla ListBoxa. Stosowanie CheckBoxów dla takich dwustanowych opcji też jest zgodne z dobrymi praktykami UX i standardami opisu formularzy w XAML. W pracy zawodowej często się to wykorzystuje, bo kod jest czytelny i łatwo go rozszerzać. Właśnie taki zestaw – ListBox, TextBox, CheckBox – jest najbardziej przejrzysty i zgodny z zamysłem projektanta interfejsów. Fajnie jest to zapamiętać, bo ta kombinacja pojawia się w wielu firmowych projektach.

Pytanie 29

Co to jest wskaźnik w języku C?

A. Funkcja do dynamicznej alokacji pamięci
B. Zmienna przechowująca adres pamięci
C. Zmienna przechowująca wartość logiczną
D. Typ danych do zapisywania tekstów
Wskaźnik w języku C to zmienna przechowująca adres pamięci innej zmiennej. Umożliwia bezpośrednią manipulację pamięcią, co czyni wskaźniki niezwykle potężnym narzędziem w programowaniu niskopoziomowym. Dzięki wskaźnikom można dynamicznie alokować pamięć, przekazywać duże struktury danych do funkcji bez ich kopiowania oraz implementować struktury danych, takie jak listy, drzewa czy grafy. Wskaźniki umożliwiają także iterowanie po tablicach i efektywne zarządzanie zasobami systemowymi, co czyni je kluczowym elementem w programowaniu systemowym.

Pytanie 30

Jaką wartość przyjmie etykieta label po wykonaniu poniższego kodu, gdy zostanie on uruchomiony po naciśnięciu przycisku w aplikacji?

private void Button_click(object sender, routedEventArgs e) {
    int tmp = 0;
    for (int i=0; i<=100; i+=2) {
        tmp += i;
    }
    label.Content = tmp;
}
A. suma liczb parzystych z przedziału od 0 do 100
B. liczby parzyste z przedziału od 0 do 100
C. liczby z przedziału od 0 do 100
D. suma liczb z przedziału od 0 do 100
Kod, który został podany w pytaniu, wykorzystuje pętlę for do obliczenia sumy wszystkich liczb parzystych z przedziału od 0 do 100 włącznie. Zmienna tmp pełni tutaj rolę akumulatora, który z każdą iteracją powiększa swoją wartość o kolejną liczbę parzystą. Startujemy od zera, a dzięki i+=2 pętla przechodzi tylko przez liczby parzyste (0, 2, 4, ..., 100). To bardzo typowy sposób, żeby wyliczyć sumę konkretnego zbioru liczb – w tym przypadku parzystych z określonego zakresu. Moim zdaniem warto zauważyć, że takie podejście świetnie sprawdza się w prostych kalkulatorach, prostych analizach danych czy nawet w grach, gdzie czasem trzeba sumować tylko wybrane wartości. W praktyce, szczególnie w większych projektach, lepiej opakować takie operacje w osobne metody lub korzystać np. z funkcji agregujących LINQ w C#. Ale zasada jest ta sama – najpierw określamy, co konkretnie chcemy sumować (tutaj: liczby parzyste), a potem realizujemy to w pętli. Ten fragment kodu jest też niezłym przykładem, jak optymalnie można przechodzić przez dane, jeśli nie musimy analizować wszystkich możliwych wartości (tutaj: wystarczy co drugi krok). Takie sumowanie przydaje się w pracy z raportami, zestawieniami i w miejscach, gdzie liczy się wydajność przetwarzania danych.

Pytanie 31

Który z poniższych elementów HTML5 służy do rysowania grafiki?

A. &lt;graphic&gt;
B. &lt;canvas&gt;
C. &lt;svg&gt;
D. &lt;draw&gt;
Element HTML5 &lt;canvas&gt; jest kluczowym narzędziem do rysowania grafiki w przeglądarkach internetowych. Umożliwia programistom tworzenie dwuwymiarowych i trójwymiarowych grafik w sposób dynamiczny, wykorzystując JavaScript. Przykładem zastosowania &lt;canvas&gt; jest tworzenie gier, animacji, wizualizacji danych oraz interaktywnych wykresów. Dzięki API dla elementu canvas, programiści mają możliwość rysowania kształtów, linii, tekstu oraz obrazów, co otwiera szerokie możliwości w zakresie projektowania interfejsów użytkownika. Warto również zwrócić uwagę na to, że stosowanie &lt;canvas&gt; zgodnie z najlepszymi praktykami programistycznymi, takimi jak efektywne zarządzanie pamięcią i optymalizacja renderowania, pozwala na osiąganie płynnych animacji i wysokiej jakości grafik. Co więcej, &lt;canvas&gt; jest wspierany przez wszystkie nowoczesne przeglądarki, co zapewnia dużą zgodność i dostępność.

Pytanie 32

Wartości składowych RGB koloru #AA41FF zapisane w systemie szesnastkowym po przekształceniu na system dziesiętny są odpowiednio

A. 170, 65, 255
B. 170, 64, 255
C. 160, 65, 255
D. 160, 64, 255
Przy przekształcaniu wartości szesnastkowych RGB na system dziesiętny łatwo popełnić błąd, bo wystarczy źle podstawić którąś cyfrę albo zmieszać kolejność. W przypadku koloru #AA41FF każda para znaków odpowiada jednej składowej: AA to czerwona, 41 to zielona, a FF to niebieska. Najczęściej błędy pojawiają się, gdy niepoprawnie zinterpretujemy cyfry szesnastkowe jako dziesiętne lub po prostu pomylimy kolejność składowych. Przykładowo, '160' w odpowiedzi zamiast '170' wynika być może z błędnego odczytania AA – bo łatwo pomylić literę A (10) z cyfrą 6 czy 0, zwłaszcza jeśli ktoś nie jest przyzwyczajony do liczb szesnastkowych. Podobnie, '64' zamiast '65' dla 41 to typowy efekt nieuwagi w liczeniu: 4*16+1 daje 65, a nie 64, co pokazuje, jak ważna jest precyzja w prostych działaniach matematycznych. Z kolei zamiana AA na 160 może świadczyć o mechanicznej zamianie liter na liczby bez uwzględnienia ich pozycji w zapisie szesnastkowym. Powszechnym błędem jest też zamiana kolejności składowych lub skupianie się tylko na końcowych cyfrach, przez co mylnie przyjmuje się, że na przykład AA to 160, bo pierwsza cyfra to 1, a nie 10. W praktyce branżowej takie niedokładności prowadzą do złych efektów wizualnych – np. kolor na stronie mocno różni się od zamierzonego lub nie pasuje do reszty projektu. Moim zdaniem takie błędy wynikają zwykle z braku nawyków w przeliczaniu systemów liczbowych. Warto zawsze pamiętać, że każda cyfra szesnastkowa ma swoją wagę, a zamiana wymaga precyzyjnego policzenia: pierwsza cyfra razy 16 plus druga cyfra. W codziennej pracy z grafiką cyfrową czy webdesignem taka pomyłka bardzo rzuca się potem w oczy użytkownikowi, więc lepiej od początku ćwiczyć dokładność niż potem szukać, gdzie zniknęła ta właściwa barwa.

Pytanie 33

Który z wymienionych algorytmów sortowania jest najskuteczniejszy w przypadku dużych zbiorów danych w przeważającej liczbie sytuacji?

A. Sortowanie szybkie (QuickSort)
B. Sortowanie przez wstawianie
C. Sortowanie przez zliczanie
D. Sortowanie bąbelkowe
QuickSort to algorytm sortowania, który jest najbardziej efektywny dla dużych zbiorów danych, osiągając średnią złożoność obliczeniową O(n log n). Wykorzystuje strategię 'dziel i zwyciężaj', co pozwala na szybkie podzielenie tablicy na mniejsze części wokół elementu zwanego pivotem. Dzięki temu QuickSort jest wyjątkowo szybki, nawet w przypadku dużych i losowo rozłożonych zbiorów danych. Jego zaletą jest niskie zużycie pamięci oraz możliwość sortowania w miejscu (in-place), co oznacza, że nie wymaga dodatkowej przestrzeni poza rekurencyjnym stosowaniem wywołań. Algorytm ten jest szeroko stosowany w aplikacjach bazodanowych, systemach operacyjnych i analizie danych.

Pytanie 34

W jaki sposób można zmniejszyć liczbę danych zbieranych przez aplikacje mobilne?

A. Udostępniać aplikacjom wszystkie niezbędne informacje
B. Weryfikować i regulować uprawnienia aplikacji w ustawieniach
C. Używać aplikacji bez sprawdzania ich źródła
D. Nie blokować aplikacjom dostępu do lokalizacji oraz kontaktów
Dostosowanie uprawnień aplikacji w ustawieniach swojego telefonu to naprawdę dobry sposób na ograniczenie tego, co aplikacje mogą o nas wiedzieć. Wiele z nich, jak np. te do robienia zdjęć, prosi o dostęp do lokalizacji czy kontaktów, ale nie zawsze jest to potrzebne. Warto co jakiś czas sprawdzić, czy jakieś aplikacje nie mają za dużo uprawnień. Dzięki temu lepiej zabezpieczymy swoją prywatność i zmniejszymy ryzyko, że nasze dane wyciekną. Lepiej też unikać aplikacji z nieznanych źródeł, bo mogą one zbierać więcej informacji, niż byśmy chcieli.

Pytanie 35

Wskaż kod, który jest funkcjonalnie równoważny zaprezentowanemu poniżej:

switch(nrTel) {
    case 999: opis = "Pogotowie"; break;
    case 998: opis = "Straż"; break;
    case 997: opis = "Policja"; break;
    default: opis = "Inny numer";
}
Kod 1.
with nrTel {
    if (999) opis = "Pogotowie";
    if (998) opis = "Straż";
    if (997) opis = "Policja";
    else opis = "Inny numer";
}
Kod 2.
if (nrTel == 999)
    opis = "Pogotowie";
else if (nrTel == 998)
    opis = "Straż";
else if (nrTel == 997)
    opis = "Policja";
else opis = "Inny numer";
Kod 3.
if (nrTel == 999)
    opis = "Pogotowie";
if (nrTel == 998)
    opis = "Straż";
if (nrTel == 997)
    opis = "Policja";
else
    opis = "Inny numer";
Kod 4.
Opis =
    if (nrTel == 999) => "Pogotowie";
    else if (nrTel == 998) => "Straż";
    else if (nrTel == 997) => "Policja";
    else => "Inny numer";
A. Kod 2.
B. Kod 1.
C. Kod 3.
D. Kod 4.
W tym przypadku Kod 2 jest dokładnym odpowiednikiem funkcjonalnym dla przedstawionej instrukcji switch. To, co tu widać, to klasyczna zamiana konstrukcji switch-case na strukturę if-else if-else, co jest bardzo częstą praktyką w programowaniu, szczególnie w językach, które nie zawsze posiadają rozbudowaną wersję switch. Kod 2 najpierw sprawdza, czy nrTel to 999, jeśli tak – przypisuje "Pogotowie" i nie sprawdza dalszych warunków. Jeśli nie, przechodzi do kolejnego warunku, czyli nrTel == 998, potem 997, w końcu domyślnie daje "Inny numer". Dokładnie tak samo to działało w switchu – tylko jeden warunek się wykonuje i reszta jest ignorowana, co ma znaczenie np. gdybyśmy później rozbudowywali logikę. Takie podejście jest czytelne, uniwersalne i zgodne z dobrymi praktykami kodowania – łatwo to refaktoryzować, debugować i utrzymywać. W wielu firmowych projektach spotkałem się z preferencją dla if-else zamiast switcha, jeśli liczba przypadków nie jest ogromna, bo łatwiej potem dołożyć dodatkowe warunki (np. złożone, nie tylko proste porównanie wartości). Fajnie też wiedzieć, że takie zamiany to podstawa przy migracji kodu między różnymi językami – nie każdy język ma identycznie działający switch. Moim zdaniem, umiejętność takiego przełożenia to dobra baza do nauki algorytmiki i lepszego rozumienia logiki sterowania przepływem kodu.

Pytanie 36

Na równoważnych pod względem funkcjonalnym listingach fragmentów aplikacji Angular oraz React.js utworzono listę punktowaną, która zawiera:

Definicja typu:

books = ["Harry Potter", "Hobbit", "Władca pierścieni"];

Kod Angular:
<ul>
    <li *ngFor = "let book of books"> {{book}} </li>
</ul>

Kod React.js:
<ul>
    {this.books.map(book => <li key={book}> book </li>)}
</ul>
A. Jedynie jeden element o treści Harry Potter.
B. Taką liczbę elementów, ile znajduje się w tablicy books; w każdym punkcie listy umieszczony jest jeden element tablicy.
C. Tyle elementów, ile znajduje się w tablicy books; w każdym punkcie listy widnieje element o treści {book}.
D. Wyłącznie jeden element o treści Harry Potter, Hobbit, Władca pierścieni.
Dokładnie tak właśnie działa iteracja po tablicy w Angularze i React.js. Zarówno Angularowy *ngFor, jak i funkcja map() w Reactcie to narzędzia do dynamicznego generowania elementów listy na podstawie danych z tablicy – w tym przypadku books. Każdy element tablicy tworzy osobny <li>, a więc liczba elementów na stronie zawsze odpowiada długości tablicy. To jest bardzo praktyczne, bo pozwala wyświetlać listy o dowolnej długości, zależnie od zawartości danych, bez przepisywania kodu – wystarczy zmienić dane źródłowe. W Angularze taki sposób budowania widoków jest zgodny z podejściem deklaratywnym – opisujesz, co ma się pojawić, a nie jak dokładnie to zrobić krok po kroku. React „mapuje” dane na elementy JSX, przy okazji warto pamiętać o kluczach (key), bo to pomaga w optymalizacji pracy wirtualnego DOM-u. Takie podejście to dzisiaj absolutny standard w branży – ułatwia utrzymanie kodu, testy i reużywalność komponentów. Moim zdaniem, kiedy raz się to opanuje, ciężko wyobrazić sobie inne podejście do budowy dynamicznych interfejsów. Zauważ, że każdy <li> wyświetla dokładny tekst z tablicy, a nie jakieś szablony czy placeholdery – to bardzo czytelne i naturalne dla użytkownika. W realnych projektach często tak renderuje się np. listy produktów, komentarzy czy zadań do wykonania. Dodatkowo, jeśli zmodyfikujesz tablicę, to widok automatycznie się odświeży – nie musisz ręcznie aktualizować DOM. To ogromne ułatwienie i podstawa nowoczesnego frontendu.

Pytanie 37

Zaznaczone elementy w przedstawionych obramowaniach mają na celu:
Fragment kodu w WPF/XAML:

<Windows Title="Tekst"...>
Fragment kodu w Java:
public class Okno extends JFrame {
    ...
    public Okno() {
        super();
        this.setTitle("Tekst");
    }
    ...
A. uzyskanie nazwy obiektu obrazującego okno aplikacji
B. ustawienie tytułu okna na "Tekst"
C. przypisanie nazwy obiektu obrazującego okno aplikacji
D. zapisanie tytułu okna do obiektu Tekst
Odpowiadając na to pytanie, łatwo pomylić pojęcia związane z nazwą obiektu a tytułem okna aplikacji. Fragmenty kodu, które są tu pokazane, nie mają nic wspólnego z uzyskaniem czy przypisaniem nazwy obiektu programistycznego – chodzi wyłącznie o to, co użytkownik zobaczy na pasku tytułu okna po uruchomieniu programu. W językach takich jak Java, nazwa obiektu (np. instancji JFrame) to coś, co ustalamy we własnym kodzie i nie jest to tożsame z tym, co widać na ekranie. W przypadku XAML, a konkretnie atrybutów jak Title, nie przypisujemy żadnej nazwy programistycznej, lecz tylko wyświetlany tekst. Innym błędem jest sądzenie, że kod zapisuje tytuł do obiektu o nazwie „Tekst” – nie ma tu żadnej referencji do obiektu o tej nazwie; to po prostu wartość tekstowa, która będzie widoczna dla użytkownika. Takie błędne rozumowanie często wynika z mylenia pojęć 'nazwa obiektu' i 'wyświetlany tytuł', co niestety bywa źródłem nieporozumień na egzaminach. W praktyce, operując na GUI, tytuł okna nadajemy, żeby użytkownik rozpoznawał aplikację lub jej aktualny stan, a nie po to, żeby zarządzać obiektami w kodzie. Jest to raczej kwestia interfejsu użytkownika, nie stricte struktury programu. Z punktu widzenia dobrych praktyk, ważne jest, żeby pamiętać o tym rozróżnieniu i nie traktować tekstów wyświetlanych użytkownikowi jako nazw czy zmiennych w kodzie. Takie myślenie może prowadzić do niejasności i błędów, zwłaszcza przy rozbudowanych aplikacjach okienkowych, gdzie zarządzanie nazwami obiektów i elementami interfejsu powinno być jasno rozdzielone.

Pytanie 38

W języku Python, jak nazywa się funkcja, która jest wykonywana automatycznie, gdy obiekt jest niszczony?

A. __del__
B. __str__
C. __init__
D. __repr__
W Pythonie funkcja <code>__del__</code> to metoda destruktora, która jest wywoływana, gdy obiekt jest niszczony. Jest to część procesu zarządzania pamięcią, gdzie interpreter Pythona automatycznie usuwa obiekty, które nie są już potrzebne, aby zwolnić pamięć. <code>__del__</code> pozwala na wykonanie dodatkowych czynności przed ostatecznym usunięciem obiektu, takich jak zamknięcie plików czy połączeń sieciowych. Warto jednak pamiętać, że użycie <code>__del__</code> nie jest zalecane do zarządzania zasobami, ponieważ może prowadzić do trudnych do zdiagnozowania błędów, szczególnie gdy obiekty są usuwane w nieprzewidywalnym momencie. Zamiast tego, lepiej jest używać menedżerów kontekstu (z instrukcją <code>with</code>), które zapewniają bardziej kontrolowane i bezpieczne zwalnianie zasobów. Przykładowo, otwierając plik za pomocą <code>with open('plik.txt', 'r') as f:</code>, masz pewność, że plik zostanie zamknięty poprawnie po zakończeniu bloku kodu, niezależnie od tego, czy wystąpił błąd.

Pytanie 39

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
Kiedy chcemy, żeby grafiki w aplikacjach mobilnych wyglądały dobrze na różnych ekranach, musimy zastosować odpowiednie strategie, które zależą od platformy. Na iOS używa się przyrostków @2x lub @3x, co oznacza, że grafiki są przygotowane dla ekranów Retina, które mają wyższą gęstość pikseli. Na Androidzie z kolei, grafiki umieszcza się w folderach drawable z takimi nazwami jak -hdpi, -xhdpi czy -xxhdpi. Dzięki temu system wie, jaką wersję grafiki wybrać w zależności od rozdzielczości urządzenia. Moim zdaniem, taki system pozwala na super jakość obrazów i lepszą wydajność aplikacji.

Pytanie 40

Który z wymienionych algorytmów działających na tablicy jednowymiarowej ma złożoność obliczeniową \( O(n^2) \)?

A. Sortowanie szybkie
B. Wyszukiwanie metodą binarną
C. Sortowanie bąbelkowe
D. Wyświetlenie elementów
Sortowanie bąbelkowe to taki klasyczny algorytm, który ma złożoność \( O(n^2) \). Chociaż jest dość prosty w zrozumieniu, to nie za bardzo sprawdza się w większych zbiorach danych. Działa tak, że porównuje sąsiadujące ze sobą elementy i zamienia je miejscami, jeśli są w złej kolejności. Trochę to czasochłonne, ale warto znać ten algorytm, bo pokazuje podstawy sortowania.