Skip to content

Commit

Permalink
Fix typos in chapters 3, 4 and in conclusion
Browse files Browse the repository at this point in the history
  • Loading branch information
josefdolezal committed May 12, 2017
1 parent 5030f7a commit 521356b
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 38 deletions.
2 changes: 1 addition & 1 deletion chapters/conclusion.tex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
\bigskip

Během implementace jsem se snažil většinu pozornosti věnovat architektuře aplikace.
Mnoho částí jsem proto v průběmu implementace několikrát přepsal.
Mnoho částí jsem proto v průběhu implementace několikrát přepsal.

Velkou výzvou bylo implementovat aplikaci reaktivně.
S reaktivním programování jsem doposud neměl žádné zkušenosti.
Expand Down
6 changes: 3 additions & 3 deletions chapters/implementation-add-printer.tex
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ \section{Přidání nové tiskárny}

Obrazovka přidání tiskárny slouží pro případ, kdy uživatel chce ovládat novou tiskárnu a nenalezl ji v seznamu síťových tiskáren.
Pro úspěšné přidání tiskárny je nutné zadat její název, \acrshort{url} či IP adresu a přístupový token.
Volitelně je možné také přidat url adresu na které se vyskytuje video stream z web kamery natáčející průběh tisku.
Volitelně je možné také přidat url adresu, na které se vyskytuje video stream z web kamery natáčející průběh tisku.

\subsection{Validace formuláře}

Jako u každé aplikace, která přijímá uživatelské vstupy i v mé implementaci je nutné ověřit platnost zadaných údajů.
Jelikož se jedná o logiku, je validace umístěna ve ViewModelu.
Text zadaný uživatelem se při každé změně odešle ViewModelu, který všechny vstupy zvaliduje.
Na základě platnosti kombinace vstupů vyšle ViewModel boolean hodnotu Controlleru.
Na základě platnosti kombinace vstupů vyšle ViewModel booleanovskou hodnotu Controlleru.
Controller pomocí UI bindigs sváže tuto hodnotu s blokací tlačítka \uv{Přihlásit}.

Je-li formulář platný, tlačítko je povolené.
Expand All @@ -33,7 +33,7 @@ \subsection{Uložení tiskárny}
ViewModel ani ViewController seznamu nemusí být o výsledku přidání tiskárny nijak notifikovány, o propagaci této informace se postará datová vrstva aplikace.

V případě selhání požadavku je vytvořena chybová hláška.
Díky reaktivním rozšířením, které jsem vytvořil pro ViewController třídu je možné v Controlleru obrazovky chybu zobrazit pomocí UI bindings.
Díky reaktivním rozšířením, které jsem vytvořil pro ViewController třídu chybu zobrazit pomocí UI bindings.

Ukázka \ref{code:add-printer-login-request} zjednodušeně implementuje vytvoření požadavku a následné zpracování odpovědi od tiskárny.

Expand Down
2 changes: 1 addition & 1 deletion chapters/implementation-files.tex
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ \subsection{Nahrávání souborů}
Nahrávání souborů k tisku je z mého pohledu důležitou funkcí této aplikace.
Systém iOS je ale bohužel uzavřený a nedovoluje uživateli přistupovat k souborovému systému \cite{imobile-access-fs}.
Umožňuje ale otevírat soubory z jiných aplikací.
Tyto aplikace musí funkci poskytování soubory explicitně povolit.
Tyto aplikace musí funkci poskytování souborů explicitně povolit.

Při implementaci této funkce stačilo v nastavení projektu zvolit jaký typ souborů aplikace umí otevřít.
Systém se následně postará o zobrazení dialogu uživateli a provede ho výběrem souboru.
Expand Down
2 changes: 1 addition & 1 deletion chapters/implementation-printer-detail.tex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ \subsection{Připojení tiskárny}
OctoPrint se může nacházet ve stavu, kdy je připravený k použití, ale není připojen k tiskárně.
V tuto chvíli nelze získat informace o aktuálním tisku ale ani o tiskárně samotné.

Z tohoto důvodu jsem implementoval \uv{prázdnou obrazovku}, která uživatele upozorňuje na odpojenou tiskárnu a vyzývá uživatele k jejímu připojení.
Z tohoto důvodu jsem implementoval \uv{prázdnou obrazovku}, která uživatele upozorňuje na odpojenou tiskárnu a vyzývá ho k jejímu připojení.
Fakt, že data nejsou dostupná se propaguje z ViewModelu.
Ten vysílá signál nazvaný \textit{contentIsAvailable} booleanovského typu.
Obrazovka s výzvou k připojení tiskárny je dostupná právě když hodnota signálu je \textit{false}.
Expand Down
24 changes: 12 additions & 12 deletions chapters/implementation-printer-list.tex
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
\section{Seznam dostupných tiskáren}

Aplikace jsem navrhl tak, aby klíčové funkcionality byly dostupné s co nejkratším průchodem aplikace.
Aplikaci jsem navrhl tak, aby klíčové funkcionality byly dostupné s co nejkratším průchodem aplikace.
Jako úvodní obrazovku jsem zvolil seznam tiskáren.
V případě, že již uživatel aplikace dříve používal, zobrazí se v seznamu na prvních místech tiskárny, které si uživatel uložil.
V případě, že již uživatel aplikaci dříve používal, zobrazí se v seznamu na prvních místech tiskárny, které si dříve uložil.
Na dalších místech jsou pak tiskárny dostupné na stejné síti, které aplikace automaticky nalezla.

Pokud aplikace požadovanou tiskárnu nenalezla, je ze seznamu tiskáren možné přejít na obrazovku pro manuální přidání tiskárny.
Expand All @@ -29,7 +29,7 @@ \subsubsection*{Sekce seznamu}
\subsubsection*{Uložené tiskárny}

První sekce zobrazuje tiskárny načtené z lokální databáze.
Při sestavování seznamu si pomocí \textit{delegate pattern} CollectionView nejdříve vyžádá počet prvků pro tuto sekci.
Při sestavování seznamu si CollectionView pomocí delegate pattern nejdříve vyžádá počet prvků pro tuto sekci.
Controller tedy využije výstup ViewModelu a vrátí hodnotu jeho proměnné nazvané \textit{storedPrintersCount}.
Implementace této metody je vidět v ukázce \ref{code:printer-list-number-of-rows}.

Expand All @@ -39,7 +39,7 @@ \subsubsection*{Uložené tiskárny}
K tomu je opět využit delegate pattern.
Pro správné dodržení \acrshort{mvvm} architektury nesmí Controller využívat modelové objekty.
Pro každou buňku je tedy potřeba vytvořit ViewModel, který ji bude obsluhovat.
Controller si pro řádkový index vyžádá od svého ViewModelu nový ViewModel buňky a ten jí.
Controller si pro řádkový index vyžádá od svého ViewModelu nový ViewModel buňky a ten jí předá.
Buňka se následně sama z ViewModelu nakonfiguruje.
Vyžádání ViewModelu buňky zachycuje ukázka \ref{code:printer-list-cell-viewmodel}.

Expand All @@ -60,7 +60,7 @@ \subsubsection*{Síťové tiskárny}
\subsection{Automatické nalezení tiskáren}

Pro zlepšení uživatelského zážitku jsem se snažil minimalizovat nutnost konfigurace aplikace.
Jako uživatelsky nejméně přívětivé se jeví přidávání aplikace.
Jako uživatelsky nejméně přívětivé se jeví přidávání tiskárny.
Uživatel musí zjistit IP nebo \acrshort{url} adresu OctoPrintu, jeho port a přístupový token.

Z tohoto důvodu je v aplikaci dostupné automatické hledání tiskáren.
Expand All @@ -73,7 +73,7 @@ \subsection{Automatické nalezení tiskáren}
Rozhodne-li se uživatel přidat síťovou tiskárnu, jejím výběrem otevře obrazovku pro přihlášení.
Na obrazovce jsou předvyplněné údaje, které aplikace o tiskárně zjistila.
Konkrétně se jedná o její síťový název a adresu s portem.
Pro dokončení přidání stačí pouze zadat přístupový.
Pro dokončení přidání stačí pouze zadat přístupový token.

\subsubsection*{Technologie Bonjour}

Expand All @@ -92,18 +92,18 @@ \subsubsection*{Reaktivní rozšíření}
Třída je implementována jako \textit{Singleton} \cite{thatthinginswift-singletons} poskytující pouze metodu \textit{searchServices}.

Tato metoda spustí vyhledávání síťových zařízení (které je asynchronní) a vrátí signál, na kterém budou jako hodnoty posílány \textit{BonjourService}, tedy objekty reprezentující tiskárny.
Uvnitř třídy se nejprve proběhne nalezení všech dostupných hostname (názvů síťových zařízení).
Uvnitř třídy nejprve proběhne nalezení všech dostupných hostname (názvů síťových zařízení).
Ve chvíli kdy systém ohlásí, že prohledal celou síť, spustí se překlad hostname na IP adresu.

Systém projde po jednom nalezená zařízení a pokusí se zjistit jeho IP adresu.
Systém po jednom projde nalezená zařízení a pokusí se zjistit jeho IP adresu.
Pokud je překlad úspěšný, zařízení se přidá do pole nalezených tiskáren a celé pole se odešle signálem.

Díky reaktivnímu přístupu tak Controller dostane informaci o novém prvku, který je nutné zobrazit a překreslí seznam.

\subsection{Automatické aktualizace}

Abych zajistil přijemnou uživatelskou zkušenost z aplikace, rozhodl jsem se seznam tiskáren implementovat jako \textit{push-based}.
Tato strategie uvádí, že při změně dat jejich vlastník (např. ViewModel) upozorní své odběratele (Controller).
Tato strategie udává, že při změně dat jejich vlastník (např. ViewModel) upozorní své odběratele (Controller).
Každý odběratel se sám rozhodne, jakým způsobem informaci využít.
V mé konkrétní implementaci lze vidět rozdíl od \textit{pull-based} strategie v automatických aktualizacích.

Expand All @@ -129,7 +129,7 @@ \subsection{Automatické aktualizace}

\subsection{Přidání tiskárny}

V momentě kdy nebude požadavaná tiskárna automaticky nalezena a zároveň ji uživatel dříve nepřidal, je možné tiskárnu přidat ručně.
V momentě kdy nebude požadovaná tiskárna automaticky nalezena a zároveň ji uživatel dříve nepřidal, je možné tiskárnu přidat ručně.
Přidání tiskárny se odehrává na nové obrazovce.
Na tu se uživatel dostane stisknutím tlačítka \uv{+} na obrazovce se seznamem tiskáren.

Expand All @@ -140,8 +140,8 @@ \subsection{Přidání tiskárny}
Coordinator má předem definováno jakým způsobem na interakce reagovat.
Průběh je vidět v ukázce \ref{code:printer-list-coordinator-flow}.

Na základě notifikace Coordinator vytvoří potřebné objekty k sestavení obrazovky a ovrazovku prezentuje uživateli.
Až do ukončí tohoto flow je seznam tiskáren neaktivní.
Na základě notifikace Coordinator vytvoří potřebné objekty k sestavení obrazovky a prezentuje ji uživateli.
Až do ukončení tohoto flow je seznam tiskáren neaktivní.

Pokud uživatel tiskárnu úspěšně přidá, seznam je automaticky aktualizovaný díky push-based strategii.

Expand Down
23 changes: 12 additions & 11 deletions chapters/implementation-technologies.tex
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ \subsection{Architektura aplikace}\label{technologie-architektura}
K otestování logiky aplikace navíc není potřeba vizuální vrstva aplikace.

Neméně podstatným argumentem je čitelnost kódu.
Vrstva View Controller obsahuje mnohem méně kódu a lze se v něm snáze orientovat.
ViewModel naopak neobsahuje žádné prvky uživatelského rozhraní a znázorňuje tak pouze způsob jakým daná část aplikace chová.
Vrstva Controller obsahuje mnohem méně kódu a lze se v něm snáze orientovat.
ViewModel naopak neobsahuje žádné prvky uživatelského rozhraní a znázorňuje tak pouze způsob, jakým se daná část aplikace chová.
Jednotlivé vrstvy jsou od sebe striktně odděleny a dodržují princip jedné odpovědnosti \cite{toptal-srp}.

\subsubsection*{Implementace ViewModelu}
Expand All @@ -29,7 +29,7 @@ \subsubsection*{Implementace ViewModelu}

Vstupem označuji uživatelskou interakci, na základě které je potřeba vyžádat nová data nebo zobrazit jinou obrazovku.
Výstupem jsou zobrazovaná data, která jsou ViewModelem předformátovaná aby je Controller mohl přímo zobrazit pomocí View vrstvy.
Jiným výstupem pak může být informace o stavu dat či o jejich počtu (počet polože v seznamu).
Jiným výstupem pak může být informace o stavu dat či o jejich počtu (počet položek v seznamu).

Každá obrazovka vlastní svůj ViewModel.
Pro ten jsou dostupné tři protokoly: \textit{ViewModelInputs}, \textit{ViewModelOutputs} a \textit{ViewModelType}.
Expand All @@ -49,7 +49,7 @@ \subsubsection*{Implementace Controlleru}

Uživatelské vstupy jsou implementovány pomocí funkcí.
Controller sleduje uživatelskou interakci a volá patřičné funkce ViewModelu.
Výstupy z ViewModelu jsou pomocí UI bindigs napojeny na View v metodě \textit{bindViewModel}, která je volána těsně po načtení View vrstvy do paměti.
Výstupy z ViewModelu jsou pomocí UI bindings napojeny na View v metodě \textit{bindViewModel}, která je volána těsně po načtení View vrstvy do paměti.

Controller vyžaduje v konstruktoru instanci implementující protokol vstupů a výstupů, nikoli konkrétní třídu.

Expand All @@ -62,7 +62,7 @@ \subsubsection*{Coordinator}
Coordinator má také na starosti vytvoření ViewModelu a předání jeho instance Controlleru.

Flow obrazovky se spustí metodou \textit{start}.
Po ukončení flow (uživatel chce zavří obrazovku), volá Coordinator metodu \textit{completed} kde se uvolní naalokované zdroje.
Po ukončení flow (uživatel chce zavřít obrazovku) volá Coordinator metodu \textit{completed} kde se uvolní naalokované zdroje.

S Coordinatorem spolupracuje ViewModel metodou delegate pattern.

Expand All @@ -73,14 +73,14 @@ \subsection{Synchronizace vláken}

S využitím knihovny ReactiveCocoa od verze 5.0 lze navíc využít tkzv. \textit{UI bindings}.
Ty zaručují, že hodnoty signálů jsou vždy zpracovány na hlavním vlákně a to i v momentě, kdy jsou odeslány z vlákna v pozadí.
ReactiveSwift pak zaručuje konzistency dat mezi vlákny.
ReactiveSwift pak zaručuje konzistenci dat mezi vlákny.
Dohromady tak tyto knihovny zamezují vzniku \textit{race condition} za běhu aplikace.
Více o těchto knihovnách lze zjistit z oficiální dokumentace \cite{github-reactiveswift} a \cite{github-reactivecocoa}.

Neméně podstatným faktorem byla i velmi dobrá integrace v architektuře \acrshort{mvvm}.
Pomocí operátorů nad signály lze formátovat vlastnosti modelových objektů (přidání jednotek, standardizace čísel, zástupné texty).
Takto naformátované signály zaručí, že kdykoliv se aktualizuje modelový objekt, jeho vlastnosti budou správně naformátovány.
ViewController tak vždy dostane data ve správném formátu bez ohledu na to, jakým způsobem byly změny na modelu aplikovány.
ViewController tak vždy dostane data ve správném formátu bez ohledu na to, jakým způsobem byly změny na Modelu aplikovány.

\subsection{Síťová vrstva}

Expand All @@ -106,15 +106,15 @@ \subsubsection*{Implementace Provider objektu}

Má implementace Provider objektu využívá tento nový protokol pro vytvoření požadavku.
Abych mohl využít třídu, od které můj objekt DynamicTarget dědí, musel jsem ještě vytvořit strukturu DynamicTarget, která implementuje rozhraní TargetType a využaduje tedy URL serveru.
Tu jí ale může poskytnout v konstruktutoru Dynamic provider spolu s TargetPart koncovým bodem.
Tu jí ale může poskytnout v konstruktutoru DynamicProvider spolu s TargetPart koncovým bodem.

Tím jsem dosáhl stejného rozhraní pro požadavky jako má nadtřída, jediným rozdílem je možnost dodat URL až při běhu aplikace.

\subsubsection*{Síťové požadavky mimo OctoPrint}

Pro umožnění zobrazení video streamu jsem opět potřeboval dynamickou URL, ale tentokrát pro každý požadavek (uživatel zadává pouze URL, nejsou žádné koncové body).
Tato implementace nebyla složitá, využil jsem standardních tříd knihovny Moya.
Vytvořil jsem nový objekt spravující koncové body a v něm pouze jeden bod \textit{get}.
Vytvořil jsem nový objekt spravující koncové body a v něm definoval pouze jeden bod \textit{get}.
Ten pro zkonstruování využaduje koncovou URL a chová se tedy velmi podobně jako kdyby URL byla známá už v čase kompilace.

Při využití je ale nutné pro každý požadavek explicitně URL zadat.
Expand All @@ -123,14 +123,15 @@ \subsubsection*{Síťové požadavky mimo OctoPrint}
\subsection{Datová vrstva}

Jak vyplývá z části \ref{analyza-datova-vrstva} kde popisuji datovou vrstvu, rozhodl jsem se využít knihovnu Realm.
Díky jejím reaktivním rozšíření se skvěle hodí nejen k architektuře, ale i síťové vrstvě.
Díky jejím reaktivním rozšířením se skvěle hodí nejen k architektuře, ale i k síťové vrstvě.

Při implementaci jsem dospěl k závěru, že standardní cestou využití Realmu opakuji spoustu kódu.
Vytvořil jsem proto rozšíření pro ReactiveCocoa a její Cold signál.

Pro SignalProducer, který jako hodnotu nese Realm objekt jsem přidal dvě metody.
První z nich, \textit{fetch(collectionOf:)} umožňuje z databáze načíst kolekci.
Druhou metodou je \textit{fetch(classType:, forPrimaryKey:)} vybere z databáze prvek podle primárního klíče.
Druhou metodou je \textit{fetch(classType:, forPrimaryKey:)}.
Ta vybere z databáze prvek podle primárního klíče.
Využití metod je vidět v ukázce \ref{code:realm-extensions}.

\swiftcode{code:realm-extensions}{Reaktivní rozšíření pro Realm}{assets/code/realm-extensions.swift}
Expand Down
2 changes: 1 addition & 1 deletion chapters/implementation.tex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ \chapter{Implementace}\label{implementace}

V této kapitole se budu podrobně věnovat použitým technologiím a implementaci jednotlivých funkcionalit.
V první části shrnu jaké technologie analyzované v kapitole \ref{analyza} jsem zvolil.
V dalších částech se věnuji konkrétním funkcionalitám navrženým podle analýzy \acrshort{api} v kapitole \ref{analyza-api}.
V dalších částech se věnuji konkrétním funkcionalitám navrženým podle analýzy \acrshort{api} v části \ref{analyza-api}.

\input{chapters/implementation-technologies}

Expand Down
12 changes: 6 additions & 6 deletions chapters/testing-behavior-tests.tex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
\section{Testy chování}\label{testovani-bdd}

Chování modolu aplikace lze otestovat pomocí otestovat tak, že se zkoumá plnění jeho závazků.
Chování modolu aplikace lze otestovat tak, že se zkoumá plnění jeho závazků.
Testované objekty mají definované rozhraní a závisloti, tím mají také deklarovány i závazky.
Závazky určují, jakým způsobem by měl objekt působit na zbylé části aplikace a jaké schopnosti a funkce má.
Ze schopností a funkcí lze odvodit jakým způsobem se má objekt chovat.
Expand All @@ -14,13 +14,13 @@ \subsection{Testování komponent}

\subsection{DSL}

Testy jsou popisovány takzvaným \acrshort{mdns} jazykem.
Testy jsou popisovány takzvaným \acrshort{dsl} jazykem.
To je jazyk který pomocí kombinace klíčových slov a textového popisu definuje jak se komponenta má v určitou chvíli chovat.
Více o \acrshort{mdns} lze zjistit na \cite{petrikainulainen-dsl}.
Více o \acrshort{dsl} lze zjistit na \cite{petrikainulainen-dsl}.

V běžném testovacím rozhraní prostředí Xcode tento jazyk nenabízí.
Rozhodl jsem pro to využí dvou knihoven.
Pomocí Knihovny \textit{Quick} jsem mohl \acrshort{mdns} v projektu využít.
Pomocí Knihovny \textit{Quick} jsem mohl \acrshort{dsl} v projektu využít.
Očekávané hodnoty jsem ověřoval pomocí \textit{Nimble}.

\subsection{Testování ViewModelu}
Expand All @@ -29,14 +29,14 @@ \subsection{Testování ViewModelu}
Díky dostatečnému rozsahu testů logiky aplikace lze usuzovat, že v produkčním nasazení se vyskytne jen nepatrné množství chyb.
View vrstvu následně není samostatně nutné testovat, protože z testů ViewModelu je téměř jisté, že data jsou správně připravena k zobrazení.

U ViewModelu jsem podle zvoleného scénáře navrh \acrshort{mdns}.
U ViewModelu jsem podle zvoleného scénáře navrhl \acrshort{dsl}.
Tímto jazykem jsem definoval jak očekávám, že s objektem bude pracovat.
Pomocí Nimble knihovny jsem dále ověřoval, jestli na vytvořené vstupy vytváří ViewModel očekávané výstupy jak je vidět v ukázce \ref{code:bdd-dsl}.

Během implementace jsem vytvořil bez mála sto testů, díky kterým jsem odchytil velké množství chyb.
Tyto chyby jsem často do aplikace zanesl v momentě, kdy jsem k již hotové obrazovce implementoval novou funkcionalitu.

\swiftcode{code:bdd-dsl}{Použití \acrshort{mdns} pro definici testu}{assets/code/bdd-dsl.swift}
\swiftcode{code:bdd-dsl}{Použití \acrshort{dsl} pro definici testu}{assets/code/bdd-dsl.swift}

\subsection{Vývoj řízený testováním chování}

Expand Down
Loading

0 comments on commit 521356b

Please sign in to comment.