Warning
This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

Domácí úkol 2

Tento domácí úkol se týká témat: UML, návrhový vzor Adaptér, Template Method a drobné opakování na Git a práci s null hodnotami.

Zadání

Vaše společnost implementuje systém umožňující provádět platby pomocí platební brány. Dlouhou dobu systém fungoval vůči starému rozhraní, které poskytovala platební brána. Dodavatel platební brány vydal novou verzi, kterou by Váš systém měl začít podporovat. Zároveň poměrně rozsáhlá část Vašeho řešení závisí na původní verzi.

Váš kolega dostal za úkol rozšířit existující systém o podporu nové platební brány. Váš kolega neprošel předmětem OMO a proto výsledek můžete vidět v Merge Requestu, který pro Vás připravil k revizi:

https://gitlab.fel.cvut.cz/B231_B6B36OMO/hw02_internal/-/merge_requests/1

Co byste kolegovi při Code Review připomínkovali?

Zkuste si položit následující otázky:

  • Co se stane v případě, že vznikne nová verze platební brány pro kterou budete potřebovat udržovat podporu?
  • Je správné, že musím zasahovat do třídy, která obsahuje logiku pro starou platební bránu, když se něco změní na té nové?

Refactoring - Adaptér

Na základě konzultace s kolegy přijdete s novým návrhem, jak systém upravit tak, aby splňoval vlastnosti správného návrhu.

Při návrhu využijete hned několik postupů a návrhových vzorů. Hlavním z návrhových vzorů je takzvaný Adaptér. Ve zkratce vytvoříme pro každou verzi platební brány samostatnou třídu.

Společné vlastnosti

Třída by neměla míchat metody, třídní proměnné ani konstruktory specifické pro danou verzi. Z kolegova návrhu není na první pohled jasné čím se jednotlivé verze liší a co mají společné.

Rozdělením jednotlivých verzí platební brány do samostatných tříd / adaptérů bude jasně vidět, čím se dané verze liší. Tím že každý adaptér bude dědit od jedné abstraktní třídy a/nebo implementovat jedno společné rozhraní je zřejmé co mají třídy společné.

Duplikování kódu

Aby třída fungovala pro více verzí, tak typicky často duplikuje opakující se kusy kódu. Vezměte si například následující:

if (useModernGateway) {
      // DO something for modern gateway
} else {
     // DO something for legacy gateway
}

Jednoduchost

Když třída musí podporovat různé nekompatibilní verze, tak bude málokdy jednoduchá a čitelná.

Cílové řešení

Vaším cílem je implementovat systém dle následujícího UML Class Diagramu:

Pozor! Musíte dodržet úplně přesně předpis tříd, včetně atributů, metod, vztahů mezi třídami a modifikátorů přístupu.

Dále je nutné dodržet strukturu projektu dle následujících názvů Java packages:

Tip: V UML Class Diagramu mají abstraktní třídy/metody název kurzívou.

Refactoring je často iterativní, v zadání sice máte již hotové zadání, k tomu často ale dojdete postupně.

Například při tomto příkladu by šlo postupovat následovně:

  1. Identifikujete třídu, která míchá podporu pro různé verze platební brány.
  2. Protože třída TransactionSystem nemá žádné potomky, rozhodnete se vytvořit třídu pro každou podporovanou verzi. (Extract Subclass)
  3. Pro obě nové třídy do nich přidáme, vše co potřebují pro fungování. (Push Down Method / Push Down Field)
  4. Zjistíte, že metoda executeTransaction() se obou třídách vykonává podobně, proto vytvoříte novou Abstraktní třídu kam ji přemístíte. (Template method)
  5. Aby nebylo nutné (tolik) měnit klienty využívající třídu TransactionSystem, tak vytvoříte nový Interface, který se bude jmenovat TransactionSystem. (Extract Interface)

Refactoring - Template Method

Při refaktoringu si také všimnete, že metoda executeTransaction() sestává pro obě verze ze shodných kroků:

  1. Sestavení transakce.
  2. Kontrola jestli sestavení nevrátilo prázdnou transakci.
  3. Vykonání transakce.
  4. V případě, že sestavení vrátilo prázdnou transakci, tak návrat chybového kódu.

Použijeme tedy návrhový vzor, který se jmenuje Template Method a který nám umožní pomocí abstraktních metod vytvořit ,,předpis'' pro metodu executeTransaction() a implementaci jednotlivých kroků necháme na potomcích.

Refactoring - Null hodnoty

Protože si všimnete, že kolega také trochu nebezpečně pracuje s null hodnotami a víte, jak dokáže takový NullPointerException potrápit. (Zvláště u nováčků je to jedna ze základních chyb a měli byste se na ni proto zaměřit již při code review).

Věděli jste, že sám autor null reference Tony Hoare nazval svůj návrh jako billion-dollar mistake?

Proto se snažíme psát defensivní kód a pracujeme raději s Java 8 Optional, než s null referencemi. Upravíme tedy i odpovídajícím způsobem kolegův kód.

Odevzdání

Odezvdávejte prosím pouze třídy z balíčku cz.cvut.fel.omo.homeworks.refactor.transaction v .zip souboru zbytek tříd odevzdávací systém již obsahuje.

courses/b6b36omo/hw02.txt · Last modified: 2023/10/10 14:31 by vankejan