Skip to content

Commit becb9a5

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents 76a0437 + 952a283 commit becb9a5

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

Repository/IRepository.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace Repository
66
// TODO comments
77
public interface IRepository<T>
88
{
9+
// TODO remove from IRepository
910
public object ToRow(T entry);
1011

1112
public int Add(T entry);
@@ -35,4 +36,4 @@ public interface IPortfolioEntryRepository : IRepository<PortfolioEntry>
3536

3637
public int DeletePortfolioEntries(int portfolioId);
3738
}
38-
}
39+
}

doc/doc.tex

Lines changed: 75 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,15 +160,85 @@ \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+
\noindent 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+
\subsubsection{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+
208+
\subsection{Služba pro výpočet výkonu jednotlivých entit}
209+
Aby bylo možné vypočítat výkon (výdělek či ztráta) jednotlivých entit (portfólio, položka portfólia či uskutečněný obchod), byla vytvořeno rozhraní \texttt{ISummaryService} a jeho implementace \texttt{SummaryServiceImpl}.
210+
168211
\section{Framework pro grafické rozhraní}
169212
\textit{Frontend realizovaný pomocí Blazor frameworku, zabalený do Electron wrapperu}
170213

214+
\section{Oveření kvality vytvořeného software}
215+
216+
Pro ověření kvality vytvořeného software pro sledování obchodního portfólia s kryptoměnami byly vytvořeny desítky jednotkových a integračních testů ověřující funkčnost základních modulů. Tyto testy se nachází v projektu \texttt{Tests}. Jako testovací framework byl zvolen framework \texttt{XUnit}\footnote{\url{https://github.com/xunit/xunit}}.
217+
218+
Knihovna \texttt{moq}\footnote{\url{https://github.com/moq/moq4}} byla použita pro vytvoření \textbf{mock} objektů datové vrstvy při testování kódu služeb \texttt{PortfolioService}, \texttt{PortfolioEntryService} a \texttt{MarketOrderService} (jednotkové testy).
219+
220+
Během integračních testů repozitářů datové vrstvy není použita databáze umístěná na souborovém systému, nýbrž databáze uložená v operační paměti z důvodu urychlení vykonávání testů. Připojení k databázi umístěné v operační paměti slouží řetězec \texttt{Data Source=:memory:}.
221+
222+
Vytvořené integrační testy ověřují funkčnost datové vrstvy a datového zdroje pro získvání informací o aktuálním stavu trhu s kryptoměnami.
223+
224+
\begin{lstlisting}[caption={Struktura projektu \texttt{Tests} obsahující integrační a jednotkové testy}, captionpos=b]
225+
|-- Integration
226+
| |-- CryptoStatsSource
227+
| | |-- CryptoNameResolverTest.cs
228+
| | `-- CryptoStatsSourceTest.cs
229+
| `-- Repository
230+
| |-- MarketOrderTest.cs
231+
| |-- PortfolioEntryTest.cs
232+
| `-- PortfolioTest.cs
233+
`-- Unit
234+
`-- Service
235+
|-- MarketOrderServiceTest.cs
236+
|-- PortfolioEntryServiceTest.cs
237+
|-- PortfolioServiceTest.cs
238+
`-- SummaryServiceTest.cs
239+
\end{lstlisting}
240+
241+
171242

172243
\printbibliography
173244

0 commit comments

Comments
 (0)