Wymagania formalne:
Sprawozdanie z Modułu 2 musi zawierać analizę obiektową przedstawionych problemów. Od każdego studenta oczekuje się poprawnego wydzielenia logiki do klas oraz dbałości o hermetyzację danych (prywatne pola, publiczne właściwości). Niezbędne jest dołączenie strona tytułowa, treści zadań, skomentowanego kodu źródłowego oraz dokumentacji zrzutowej prezentującej poprawne działanie napisanych klas w aplikacji konsolowej.
D2.1
E-commerce: Klasa Produktu z Walidacją
Cel

Celem zadania jest przećwiczenie tworzenia klas z właściwościami posiadającymi pełne akcesory get i set. Student uczy się implementować logikę sprawdzającą poprawność danych (walidację) bezpośrednio wewnątrz składowych obiektu.

Scenariusz

Wyobraź sobie, że budujesz backend dla prostego sklepu internetowego. Musisz przygotować klasę "Produkt", która będzie opisywać towary znajdujące się w asortymencie. Klasa powinna zawierać informacje o nazwie produktu, jego unikalnym kodzie (tylko do odczytu po utworzeniu) oraz cenie netto. Bardzo ważnym elementem jest zapewnienie stałej stawki VAT (np. 23%) jako pola tylko do odczytu, dostępnego dla wszystkich egzemplarzy klasy.Twoim zadaniem jest stworzenie właściwości CenaNetto w taki sposób, aby uniemożliwić ustawienie wartości ujemnej – w przypadku próby wpisania takiej ceny, system powinien pozostawić poprzednią wartość lub ustawić zero. Program główny ma pozwolić na utworzenie obiektu produktu z danymi pobranymi od użytkownika. Na koniec aplikacja powinna wyświetlić pełną kartę produktu zawierającą cenę netto, obliczoną cenę brutto oraz informację o naliczonym podatku. Taka struktura klasy gwarantuje, że dane finansowe obiektu będą zawsze spójne i bezpieczne przed przypadkowym uszkodzeniem. Jest to fundamentalna technika stosowana w profesjonalnych systemach ERP i portalach zakupowych.

Sugerowane kroki do wykonania
  1. Zdefiniuj klasę o nazwie Produkt.
  2. Dodaj prywatne pole do przechowywania ceny netto typu decimal.
  3. Zadeklaruj publiczną auto-właściwość Nazwa typu string.
  4. Dodaj właściwość CenaNetto z jawnie zdefiniowanym akcesorem set, zawierającym instrukcję if.
  5. Wewnątrz akcesora set dodaj walidację sprawdzającą czy podana wartość jest nieujemna.
  6. Dodaj właściwość CenaBrutto (tylko z get), która dynamicznie oblicza cenę z podatkiem 23%.
  7. Wstaw auto-właściwość KodProduktu, którą można ustawić tylko w konstruktorze (modyfikator init lub brak seta).
  8. W Main pobierz od użytkownika nazwę i cenę towaru.
  9. Utwórz obiekt klasy Produkt i przypisz mu pobrane wartości.
  10. Wyświetl sformatowane podsumowanie wszystkich danych produktu na konsoli.
D2.2
Matematyka Biznesowa: Biblioteka Statyczna
Cel

Utworzenie narzędzia typu utility class z wykorzystaniem modyfikatora static dla całej klasy i jej składowych. Student uczy się projektowania funkcji bezstanowych, które nie przechowują danych, a jedynie wykonują obliczenia na parametrach.

Scenariusz

Każdy system księgowy potrzebuje zestawu uniwersalnych funkcji do obliczeń finansowych, których nie trzeba za każdym razem przypisywać do konkretnego dokumentu. Twoim zadaniem jest zaprojektowanie statycznej klasy "Finanse", która będzie pełniła rolę centralnego kalkulatora w Twojej aplikacji. Klasa ta powinna oferować statyczne metody do wyliczania prostego zysku z lokaty na podstawie kwoty i czasu, a także do przeliczania kwot między netto i brutto dla różnych wariantów podatkowych. Dodatkowo umieść w klasie statyczną stałą określającą aktualną stopę bazową, która jest wykorzystywana w wielu różnych algorytmach finansowych firmy. Użytkownik w programie konsolowym wybiera jeden z typów obliczeń, podaje niezbędne parametry wejściowe i natychmiast otrzymuje wynik bez konieczności tworzenia obiektu klasy Finanse. Taki wzorzec projektowy jest niezwykle wydajny i ułatwia porządkowanie kodu w dużej aplikacji. Musisz zadbać o to, aby metody statyczne były proste w obsłudze i zwracały wyniki o wysokiej precyzji finansowej. Program musi obsłużyć sytuację, gdy użytkownik poda nieprawidłowe dane (np. czas trwania lokaty jako zero). Finalnie pochwal się zestawem autorskich narzędzi matematycznych zamieszczonych w Twojej sprawozdawczej dokumentacji.

Sugerowane kroki do wykonania
  1. Zdefiniuj klasę z modyfikatorem static o nazwie Finanse.
  2. Dodaj publiczną, stałą (const) wartość stopy procentowej (np. 0.0575m).
  3. Zaimplementuj statyczną metodę ObliczOdsetki przyjmującą kwotę i liczbę dni.
  4. Zaimplementuj statyczną metodę NettoNaBrutto, która przyjmuje kwotę i stawkę VAT.
  5. Upewnij się, że każda metoda w tej klasie posiada modyfikatory public oraz static.
  6. W Main wywołaj wybraną metodę używając składni: decimal wynik = Finanse.NettoNaBrutto(...).
  7. Pobierz dane od użytkownika i przekonwertuj je bezpiecznie na typ decimal.
  8. Wyświetl wynik z wykorzystaniem formatowania walutowego :c2.
  9. Spróbuj wywołać drugą metodę dla innych przykładowych danych.
  10. Brak konstruktora instancyjnego potwierdź krótkim komentarzem w kodzie źródłowym.
D2.3
Globalny Rejestr Użytkowników: Statyczny Licznik
Cel

Zastosowanie pola statycznego i konstruktora statycznego do zarządzania globalnym stanem aplikacji. Student uczy się śledzenia liczby aktywnych obiektów oraz inicjalizacji wspólnych danych dla wszystkich instancji klasy.

Scenariusz

Projektujesz system uwierzytelniania dla nowej sieci społecznościowej, gdzie każdy zarejestrowany profil otrzymuje unikalny numer seryjny przypisywany automatycznie w momencie tworzenia konta. Musisz stworzyć klasę "Uzytkownik", która w sposób bezpieczny i niezależny od zewnątrz śledzi całkowitą liczbę utworzonych kont. Każdy nowo powstały obiekt powinien w swoim konstruktorze pobrać aktualną wartość licznika globalnego i przypisać go do swojej prywatnej właściwości ID, a następnie zwiększyć ten licznik dla kolejnego użytkownika. Dodatkowo wykorzystaj konstruktor statyczny do przypisania nazwy serwera, na którym przechowywane są profile (wartość ta powinna być wspólna i stała dla wszystkich). Użytkownik Twojego programu ma możliwość dodania seryjnie kilku kont o różnych nazwach. Na koniec aplikacja wyświetla listę wszystkich zarejestrowanych osób wraz z ich automatycznie wygenerowanymi identyfikatorami oraz informacją o łącznej populacji serwera. To zadanie uczy, jak projektować obiekty, które wiedzą o istnieniu "całego zbioru" i poprawnie współdzielą pewne zasoby. Jest to przykład mechanizmu, który można spotkać w bazach danych przy generowaniu kluczy głównych (auto-increment). Finalnie sprawdź, czy identyfikatory są rzeczywiście unikalne dla każdego utworzonego obiektu.

Sugerowane kroki do wykonania
  1. Zdefiniuj klasę Uzytkownik z prywatnym polem statycznym licznikInstancji.
  2. Dodaj publiczną właściwość Id (tylko z get), która będzie unikalna dla każdego obiektu.
  3. Opracuj właściwość Login oraz Email stosując auto-properties.
  4. Dodaj konstruktor statyczny, który ustawia licznik na wartość początkową (np. 1000).
  5. Zaimplementuj konstruktor instancyjny przyjmujący login i email.
  6. W konstruktorze instancyjnym przypisz Id korzystając z aktualnej wartości licznika statycznego.
  7. Inkrementuj licznik statyczny (licznik++) wewnątrz konstruktora, aby przygotować go dla następnej osoby.
  8. W Main utwórz tablicę lub listę trzech obiektów klasy Uzytkownik.
  9. Przejdź przez tablicę pętlą i wypisz dane każdego użytkownika wraz z jego unikalnym ID.
  10. Na końcu wyświetl statyczną informację o tym, ile kont łącznie zostało utworzonych (użyj nazwy klasy do dostępu).
D2.4
System Obsługi Zamówień: Łańcuch Konstruktorów
Cel

Praktyczne wykorzystanie kaskadowego wywoływania konstruktorów (constructor chaining) za pomocą słowa kluczowego this. Student uczy się unikać redundancyjnego kodu i poprawnie inicjalizować obiekty przy różnej liczbie danych wejściowych.

Scenariusz

W systemie zarządzania magazynem "OrderMaster" zamówienia mogą wpływać różnymi kanałami i posiadać różny stopień szczegółowości. Część zamówień zawiera od razu pełne dane o kliencie, produkcie i dacie, podczas gdy inne są tworzone jako puste szkice z samym numerem referencyjnym. Twoim celem jest stworzenie klasy "Zamowienie", która poradzi sobie z trzema scenariuszami tworzenia obiektów. Pierwszy konstruktor przyjmuje tylko unikalny identyfikator zamówienia, ustawiając status na "Nowe" i datę na bieżącą. Drugi konstruktor dopisuje informację o nazwie klienta, a trzeci – najpełniejszy – przyjmuje również listę towarów oraz wyliczoną kwotę całkowitą. Kluczowe jest, aby dwa prostsze konstruktory przekazywały sterowanie do tego najbardziej rozbudowanego za pomocą słowa kluczowego "this", zamiast powielać kod przypisywania wartości do tych samych pól. Taka architektura pozwala na łatwiejszą konserwację programu – gdy zmieni się sposób zapisu identyfikatora, poprawisz go tylko w jednym miejscu. Program w konsoli powinien stworzyć przykłady zamówień każdego typu i zaprezentować ich stan początkowy. Zwróć uwagę na to, jak domyślne wartości są „wstrzykiwane” w łańcuchu wywołań. Jest to wzorcowy sposób implementacji elastycznych konstruktorów w języku C#.

Sugerowane kroki do wykonania
  1. Opracuj klasę o nazwie Zamowienie z polami odpowiadającymi danym w scenariuszu.
  2. Zidentyfikuj, które cechy obiektu są zawsze obecne i stwórz dla nich najbardziej kompletny konstruktor.
  3. Zaimplementuj konstruktor przyjmujący tylko numer zamówienia, używając : this(...) do przekazania danych.
  4. W tym przejściowym wywołaniu podaj domyślne stringi dla klienta i statusu.
  5. Zaimplementuj kolejny konstruktor pośredni (np. numer i nazwa klienta) również z użyciem : this(...).
  6. Dodaj publiczną metodę do wyświetlania skróconej informacji o zamówieniu.
  7. W metodzie Main stwórz obiekt klasy Zamowienie stosując każdy z trzech wariantów (konstruktorów).
  8. Sprawdź, czy obiekty utworzone prostszymi konstruktorami posiadają poprawnie ustawione wartości domyślne.
  9. Wyświetl wszystkie zamówienia w konsoli, używając separatorów dla lepszej czytelności.
  10. Przeanalizuj i opisz w sprawozdaniu, dlaczego takie podejście redukuje ryzyko błędów (DRY principle).
D2.5
Geolokalizacja: Klasa Punktu z Autowłaściwościami
Cel

Zastosowanie minimalistycznej składni auto-właściwości oraz modyfikatorów dostępu w celu modelowania lekkich struktur danych. Student uczy się, kiedy warto stosować skrótowy zapis { get; set; } oraz jak chronić składowe przed niepowołaną zmianą.

Scenariusz

Tworzysz moduł dla mapy cyfrowej, który operuje na punktach geograficznych określonych przez szerokość i długość geograficzną. Każdy "PunktMapy" to prosty element danych, który po utworzeniu musi być stabilny – raz nadana nazwa lokalizacji nie powinna ulec zmianie (użyj właściwości tylko do odczytu lub z modyfikatorem init). Natomiast współrzędne X i Y mogą być aktualizowane w trakcie ruchu obiektu na mapie, jednak muszą mieścić się w określonym zakresie wartości (walidacja). Twoim zadaniem jest stworzenie klasy PunktMapy wykorzystującej nowoczesną składnię C# (auto-properties) wszędzie tam, gdzie nie jest wymagana dodatkowa logika. Przygotuj konstruktor, który przyjmuje wszystkie trzy parametry startowe i inicjalizuje profil punktu. Następnie dodaj metodę, która oblicza uproszczoną odległość od środka układu współrzędnych (0,0) przy użyciu znanych wzorów matematycznych (klasa Math). Użytkownik Twojej aplikacji powinien móc zdefiniować swój punkt, przesunąć go za pomocą właściwości i sprawdzić aktualne położenie. Program ma stanowić przykład czytelnego i zwięzłego kodowania obiektów o charakterze "data-containers". Finalnie zaprezentuj historię przemieszczenia punktu w oknie tekstowym. Taki moduł świetnie sprawdza się jako element silnika nawigacyjnego lub systemu śledzenia zasobów GPS.

Sugerowane kroki do wykonania
  1. Zdefiniuj klasę o nazwie PunktMapy.
  2. Zastosuj auto-właściwość Nazwa z modyfikatorem { get; init; } lub tylko { get; }.
  3. Dodaj publiczne właściwości Szerokosc i Dlugosc typu double z akcesorami { get; set; }.
  4. Zaprojektuj konstruktor wypełniający wszystkie trzy składowe podczas tworzenia instancji.
  5. Zaimplementuj metodę OdlegloscOdSrodka(), korzystając z funkcji Math.Sqrt() i Math.Pow().
  6. W metodzie Main utwórz punkt o nazwie "Uczelnia" i podanych współrzędnych.
  7. Wyświetl aktualną pozycję punktu używając interpolacji stringów.
  8. Zmień współrzędne punktu za pomocą ich właściwości publicznych.
  9. Oblicz i wyświetl nową odległość od środka układu współrzędnych.
  10. Spróbuj zmienić Nazwę punktu po jego utworzeniu i zobacz jak reaguje kompilator (powinien zgłosić błąd).