Skip to content

Commit a2f99c6

Browse files
committed
Added documentation of the database layer
1 parent 18467ff commit a2f99c6

File tree

1 file changed

+45
-4
lines changed

1 file changed

+45
-4
lines changed

doc/doc.tex

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
\usepackage[sorting=nyt,style=ieee]{biblatex}
3030
\addbibresource{literatura.bib}
3131

32+
\lstdefinestyle{sharpc}{language=[Sharp]C, frame=lr, rulecolor=\color{blue!80!black}}
33+
3234
\lstdefinestyle{flex}{
3335
frame=tb,
3436
aboveskip=3mm,
@@ -45,7 +47,7 @@
4547
breakatwhitespace=true,
4648
tabsize=3
4749
}
48-
50+
\lstset{style=sharpc}
4951
\lstset{
5052
frame=tb,
5153
language=XML,
@@ -149,8 +151,7 @@ \subsection{Webový zdroj CoinGecko}
149151
Aktuální i historický kurz drtivé většiny všech existujících kryptoměn bez nutnosti registrace nabízí pomocí REST rozhraní webová služba CoinGecko\cite{coingecko2021}. Jediným omezením tohoto API je počet provedených požadavků za minutu, který je stanoven na 100, což je pro aplikaci určenou ke sledování kryptoměnového portfólia více než dostačující.
150152

151153
\begin{lstlisting}
152-
$ curl -X GET "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_cur
153-
rencies=usd" -H "accept: application/json"
154+
\$ curl -X GET "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd" -H "accept: application/json"
154155

155156
{
156157
"bitcoin": {
@@ -159,16 +160,56 @@ \subsection{Webový zdroj CoinGecko}
159160
}
160161
\end{lstlisting}
161162

162-
\section{Výběr databáze pro implementaci datové vrstvy aplikace}
163+
\subsection{Výběr databáze pro implementaci datové vrstvy aplikace}
163164

164165
Jelikož vytvářená aplikace není určená pro použití vícero uživateli najednou, ale pouze pro jednoho uživatele na jednom zařízení, tak pro ukládání dat aplikace je vhodná lokální databáze.
165166

166167
V úvahu připadá ukládat portfólia a transakce ve formátu JSON či XML přímo na souborový systém, ale z důvodu relace M:N mezi portfólii a kryptoměnami nejsou tyto typy databází příliš vhodné. Jako lepší volba tedy jeví nějaká relační databáze, např. SQLite, která je často používána při tvorbě desktopových aplikací a ukládá se ve formě jednoho souboru na souborový systém zařízení.
167168

169+
170+
171+
\section{Popis architektury vytvořené aplikace}
172+
\subsection{Databázová vrstva}
173+
Ve vytvořené aplikaci je datová vrstva implementována pomocí tzv. \textit{repozitářů}, kdy každý repozitář představuje perzistentní úložiště dané entity, do kterého lze zapisovat a následně z něj číst.
174+
175+
Kontrakt generického rozhraní repozitáře se skládá z následujících definic metod:
176+
\begin{itemize}
177+
\item \texttt{public int Add(T entry)} -- přidá daný objekt do perzistentního úložiště a vrátí vygenerované ID
178+
\item \texttt{public T Get(int id)} -- vyhledá a případně vrátí objekt z perzistentního úložiště dle předaného identifikátoru \texttt{id}
179+
\item \texttt{List<T> GetAll()} -- vyhledá a případně vrátí seznam všech objektů z perzistentního úložiště
180+
\item \texttt{public bool Update(T entry)} -- nahraje do perzistentního úložiště aktualizovanou verzi objektu, který se zde již nachází. Vrátí \texttt{true}, pokud aktualizace proběhla úspěšně nebo \texttt{false}, pokud během této operace došlo k nějaké chybě.
181+
\item \texttt{public bool Delete(T entry)} -- smaže předaný objekt z úložiště a vrátí \texttt{true}, pokud smazání proběhlo úspěšně nebo \texttt{false}, pokud během této operace došlo k nějaké chybě.
182+
183+
\end{itemize}
184+
185+
Ve vytvořené aplikaci jsou definovány následující repozitáře:
186+
\begin{itemize}
187+
\item \texttt{IPortfolioRepository} -- úložiště objektů představujících jednotlivá portfólia spravované v aplikaci
188+
\item \texttt{IPortfolioEntryRepository} -- úložiště objektů představujících položky existujících portfólií
189+
\item \texttt{IMarketOrderRepository} -- úložiště objektů představujících uskutečněné obchody dané položky portfólia
190+
\end{itemize}
191+
192+
\subsection{Generování SQL dotazů}
193+
K jednoduchému a intuitivnímu generování SQL dotazů je použita knihovna \textbf{SqlKata Query Builder}\footnote{\url{https://github.com/sqlkata/querybuilder}}, kdy lze SQL dotazy vytvářet pomocí řetězení volání metod poskytovaných touto knihovnou.
194+
195+
\begin{lstlisting}[language=Java, caption={Příklad generování SQL dotazu pro výběr všech transakcí dané položky portfólia pomocí knihovny SqlKata Query Builder.},captionpos=b, label={lst:sm-showcase}]
196+
Db.Get().Query(tableName).Where("portfolio_entry_id", portfolioEntryId).Get()
197+
\end{lstlisting}
198+
199+
Tato knihovna přímo umožňuje nad předaným databázovým spojením vygenerovaný SQL dotaz přímo vykonat, kdy k této činnosti využívá knihovnu \textbf{Dapper}\footnote{\url{https://github.com/DapperLib/Dapper}}. Výsledkem metod pro vykonání generovaných dotazů jsou objekty typu \texttt{dynamic}, které je třeba mapovat na instance tříd dle modelu entity se kterou pracujeme.
200+
201+
\begin{lstlisting}[language=Java,caption={Příklad mapování objektu typu \texttt{dynamic} na instanci třídy \texttt{Portfolio}.},captionpos=b, label={lst:sm-mapping}]
202+
public override Portfolio FromRow(dynamic d) =>
203+
new Portfolio((string) d.name, (string) d.description, (Currency) d.currency_code, (int) d.id);
204+
\end{lstlisting}
205+
206+
Jelikož velká část kódu pro implementaci metod repozitáře je pro všechny možné typy stejná, tak je tato část kódu sdílena pomocí abstraktní třídy \texttt{SqlKataRepository}. Implementace pro konkrétní třídy modelu musí akorát implementovat kód pro vytvoření instance dané třídy z objektu typu \texttt{dynamic} a naopak. V aplikaci se nachází implementace \texttt{SqlKataPortfolioRepository}, \texttt{SqlKataPortfolioEntryRepository} a \texttt{SqlKataMarketOrderRepository}.
207+
168208
\section{Framework pro grafické rozhraní}
169209
\textit{Frontend realizovaný pomocí Blazor frameworku, zabalený do Electron wrapperu}
170210

171211

212+
172213
\printbibliography
173214

174215

0 commit comments

Comments
 (0)