\chapter{Možnosti implementácie}

\label{kap:moznosti_implementacie}

Každý softvér si musí určiť, pre aké platformy je vyvíjaný. Samozrejme, čím väčšiu škálu platforiem pokryje,
tým je dostupnejší pre väčšie množstvo používateľov. Dnes drvivá väčšina používateľov používa istú podmnožinu
zo systémov Android, Linux, Windows, iOS a MacOS X. Spoločnou črtou týchto platforiem je, že medzi nimi neexistuje taká dvojica,
z ktorej by jedna platforma natívne podporovala programy napísané pre druhú platformu. Vyvíjať aplikáciu päťkrát,
pre každú platformu v jej natívnom prostredí, však nie je veľmi efektívne. 

Namiesto toho dnes existuje niekoľko riešení umožňujúcich zdieľať časti zdrojového kódu medzi riešeniami pre rôzne systémy.
Ako príklad môžme uviesť prostredia Flutter, React Native alebo MAUI pre .NET.

Ako univerzálne riešenie sa dnes používajú webové aplikácie.
Takéto aplikácie majú niekoľko dôležitých výhod, ako napríklad rýchla dostupnosť, žiadna nutnosť inštalácie a jednoduché spustenie
na všetkých platformách, na ktorých je dostupný webový prehliadač (napríklad Firefox, Chrome alebo Opera).
Webové aplikácie zvyknú mávať dve oddelené časti - frontend, bežiaci vo webovom prehliadači klienta a backend,
bežiaci na serveri. Tieto dve časti spolu komunikujú pomocou siete, najčastejšie pomocou protokolov HTTP(S) alebo WebSocket.
Úlohou frontendu je poskytovať prívetivé rozhranie s ktorým môže používateľ pracovať, úlohou backendu je zase spracovávať dáta,
komunikovať s databázou a poskytovať dáta frontendu. Práve pre takýto model som sa rozhodol.

\section{Možnosti vývoja frontendového riešenia}

Programovanie webových stránok sa dnes nezaobíde bez programovacieho jazyka JavaScript, ktorý používajú webové prehliadače. Alternatívne 
sa dajú použiť prekladače iných jazykov do WebAssembly (napríklad prostredie Blazor pre .NET) alebo jazyk TypeScript, ktorý je rozšírením JavaScriptu o typový 
systém a iné užitočné konštrukcie, zároveň je plne kompatibilný s JavaScriptom (je jeho nadmnožinou) a vo webových prehliadačoch sa spúšťa pomocou 
prekladu do JavaScriptu. Na vývoj webového frontendu je možnosť používať webové prostredia, ktoré umožňujú delenie stránok na moduly, 
ktoré sa dajú jednotlivo znovupoužívať a parametrizovať na rôznych podstránkach aplikácie, čím zjednodušujú spravovanie a čitateľnosť aplikácie. 
V súčasnej dobe sú najpopulárnejšie prostredia React, Vue a Angular. Kým React a Vue umožňujú prácu v JavaScripte ale volitelne je možné vyvíjať 
aj v TypeScripte, Angular prácu v TypeScripte vyžaduje. Tieto prostredia sú podporované vo všetkých nových verziách moderných prehliadačov. 
Keďže všetky tieto prostredia fungujú na veľmi podobnom princípe, je veľmi ťažké povedať, ktorý by bola pre našu aplikáciu najvhodnejší. Vzhľadom 
na to sme sa rozhodli pre Angular, v ktorom máme naviac praktických skúseností.

\section{Možnosti vývoja backendového riešenia}

Pre vývoj backendového riešenia je vhodné vybrať taký programovací jazyk, pre ktorý existuje prostredie umožňujúci vývoj API, ktoré bude podporovať 
protokol HTTP(s). Takýchto jazykov existuje veľmi veľa, dokonca pre niektoré jazyky existuje viacero rôznych knižníc umožňujúcich výstavbu 
takýchto API. Ako príklad môžme uviesť jazyk Python a knižnice FastAPI alebo Flask a mnohé iné, jazyk Java a prostredie Spring Boot, jazyk C\# a 
prostredie ASP.NET Core a mnohé iné. Všetky tieto možnosti majú dostatočné nástroje a je ťažké určiť, ktorý z nich je objektívne najvhodnejší, 
preto sme sa rozhodli pre jazyk C\# a ASP.NET Core, s ktorým máme najviac skúseností.

\subsection{Možnosti implementácie vo vybranom jazyku}

Najprv sa musíme rozhodnúť, ktorú verziu prostredia .NET použijeme. Momentálne sú podporované dve verzie - .NET 6.0 a .NET 7.0. Kým .NET 6.0 
používa verziu jazyka C\# 10, .NET 7.0 používa verziu jazyka C\# 11. Verzia jazyka C\# 11 obsahuje oproti verzii 10 viaceré nové funkcionality,
ako napríklad generické atribúty, povinné členy alebo vylepšenú prácu s konštantnými reťazcami. .NET 6.0 je však LTS verzia kým .NET 7.0 nie je, 
čo má za následok, že podpora .NET 6.0 časovo prekračuje podporu .NET 7.0 (máj 2024 oproti novembru 2024). Keďže sa viem zaobísť bez nových 
funkcionalít, rozhodol som sa použiť C\# 10 a .NET 6.0.

Napriek tomu, že už sme si vybrali jazyk, stále máme niekoľko rôznych možností, ako poňať vývoj aplikácie, najmä čo sa týka organizácie kódu 
alebo knižníc. Na komunikáciu s databázou sa dá použiť buď priamo knižnica ADO.NET, ktorá umožňuje manuálne vykonávanie SQL dotazov a ich ručné 
mapovanie do objektov, alebo knižnice typu ORM (Object Relational Mapping), ktoré pôsobia ako wrapper pre ADO.NET a sú schopné istú časť mapovania 
vykonať za nás. Najpoužívanejšie ORM v C\# sú Entity Framework Core (ďalej len EFC) a Dapper. Kým Dapper mapuje len výsledky dopytov na objekty (tzv. micro-ORM), 
EFC je schopné mapovať kód v jazyku C\# a knižnici LINQ na SQL príkazy, čím v jednoduchších aplikáciách dokáže úplne odbúrať nutnosť písania 
SQL dopytov ručne.

\begin{lstlisting}[float,language={[Sharp]C},caption={Ukážka kódu pre ten istý dopyt pomocou rôznych knižníc - ADO.NET},label=alg:Ukazka_ADO]
    private NpgsqlConnection CreateConnection()
    {
        return new NpgsqlConnection(_connectionString);
    }

    public async Task<IEnumerable<IpAddressInfo>> GetIpAddresses(int offset = 0, int limit = int.MaxValue)
    {
        await using var connection = CreateConnection();
        await connection.OpenAsync();
        var command = connection.CreateCommand();
        command.CommandText = "SELECT * FROM IpAddresses LIMIT @limit OFFSET @offset";
        command.Parameters.AddWithValue("@limit", limit);
        command.Parameters.AddWithValue("@offset", offset);
        var reader = await command.ExecuteReaderAsync();
        var result = new List<IpAddressInfo>();
        while (await reader.ReadAsync())
        {
            result.Add(new IpAddressInfo()
            {
                City = reader["City"] as string,
                CountryCode = reader["CountryCode"] as string,
                Id = Convert.ToInt32(reader["Id"]),
                IpStringValue = reader["IpStringValue"] as string,
            });
        }

        return result;
    }
\end{lstlisting}
\begin{lstlisting}[float,language={[Sharp]C},caption={Ukážka kódu pre ten istý dopyt pomocou rôznych knižníc - Dapper},label=alg:Ukazka_Dapper]
    private NpgsqlConnection CreateConnection()
    {
        return new NpgsqlConnection(_connectionString);
    }

    public async Task<IEnumerable<IpAddressInfo>> GetIpAddresses(int offset = 0, int limit = int.MaxValue)
    {
        await using var connection = CreateConnection();
        return await connection.QueryAsync<IpAddressInfo>("SELECT * FROM IpAddresses LIMIT @limit OFFSET @offset", new { limit, offset });
    }
\end{lstlisting}
\begin{lstlisting}[float,language={[Sharp]C},caption={Ukážka kódu pre ten istý dopyt pomocou rôznych knižníc - EFC},label=alg:Ukazka_EFC]
    private ApplicationDbContext _dbContext;

    public async Task<IEnumerable<IpAddressInfo>> GetIpAddresses(int offset = 0, int limit = int.MaxValue)
    {
        return await _dbContext.IpAddresses.Skip(offset).Take(limit).ToListAsync();
    }
\end{lstlisting}

Vzhľadom na možnú zložitosť dopytov sme sa rozhodli nepoužiť EFC, no použijeme Dapper ako skratku pre odbúranie opakujúceho sa kódu vznikajúceho 
pri používaní ADO.NET (otváranie a zatváranie spojenia, definície paramterov, mapovanie výsledkov na objekty).

Pri štruktúre kódu je nutné sa rozhodnúť, či budeme endpointy deliť do kontrolerov alebo nie (tzv. minimal API). Kým výhodou kontrolerov je lepšia 
štrukturovateľnosť a väčšia prehľadnosť pri väčšom množstve endpointov, výhodou mimal API je mierne menej kódu a potenciálny kratší čas písania. Keďže 
aplikácia môže mať väčšie množstvo endpointov, rozhodli sme sa použiť kontrolery.

\subsection{Databáza}

S backendovým riešením úzko súvisí aj výber databázového poskytovateľa pre ukladanie spracovaných dát. V dnešnej dobe sa používajú dva základné typy databáz 
- SQL a NoSQL. Keďže naše dáta budú mať jasnú štruktúru, bude vhodné použiť jedného z mnohých SQL providerov, napríklad PostgreSQL, MySQL, MS SQL, SQLite atď. 
Keďže databáza s údajmi o meraniach je PostgreSQL, rozhodli sme sa použiť tiež PostgreSQL pre zachovanie uniformity.