From f9ea0dc6a9efb6c80b33ddb817a82c4539decf65 Mon Sep 17 00:00:00 2001 From: Petr Nymsa Date: Wed, 27 May 2020 16:24:05 +0200 Subject: [PATCH] FINAL --- FITthesis.cls | 2 +- chapters/00_introduction.tex | 8 +-- chapters/01_flutter.tex | 15 +++-- chapters/02_analysis.tex | 14 ++--- chapters/03_implementation.tex | 54 ++++++++-------- chapters/04_deploy.tex | 8 +-- chapters/_conclusion.tex | 12 ++-- dp_nymsa.tex | 19 +++--- ref.bib | 109 ++++++++++++++++----------------- 9 files changed, 118 insertions(+), 123 deletions(-) diff --git a/FITthesis.cls b/FITthesis.cls index 503f2e4..e3d8b12 100644 --- a/FITthesis.cls +++ b/FITthesis.cls @@ -236,7 +236,7 @@ a~z\'arove\v n sa zav\"azuje spr\'\i stupni\v t zdrojov\'y k\'od tak\'eho diela }\else{% I hereby declare that the presented thesis is my own work and that I have cited all sources of information in accordance with the Guideline for adhering to ethical principles when elaborating an academic final thesis. - I acknowledge that my thesis is subject to the rights and obligations stipulated by the Act No.\,121/2000~Coll., the Copyright Act, as amended. In accordance with Article~46~(6) of the Act, I hereby grant a nonexclusive authorization (license) to utilize this thesis, including any and all computer programs incorporated therein or attached thereto and all corresponding documentation (hereinafter collectively referred to as the ``Work''), to any and all persons that wish to utilize the Work. Such persons are entitled to use the Work in any way (including for-profit purposes) that does not detract from its value. This authorization is not limited in terms of time, location and quantity. However, all persons that makes use of the above license shall be obliged to grant a license at least in the same scope as defined above with respect to each and every work that is created (wholly or in part) based on the Work, by modifying the Work, by combining the Work with another work, by including the Work in a collection of works or by adapting the Work (including translation), and at the same time make available the source code of such work at least in a way and scope that are comparable to the way and scope in which the source code of the Work is made available. + I acknowledge that my thesis is subject to the rights and obligations stipulated by the Act No.\,121/2000~Coll., the Copyright Act, as amended. In accordance with Article~46~(6) of the Act, I hereby grant a nonexclusive authorization (license) to utilize this thesis, including any and all computer programs incorporated therein or attached thereto and all corresponding documentation (hereinafter collectively referred to as the ``Work''), to any and all persons that wish to utilize the Work. Such persons are entitled to use the Work in any way (including for-profit purposes) that does not detract from its value. This authorization is not limited in terms of time, location and quantity. However, all persons that makes use of the above license shall be obliged to grant a~license at least in the same scope as defined above with respect to each and every work that is created (wholly or in part) based on the Work, by modifying the Work, by combining the Work with another work, by including the Work in a collection of works or by adapting the Work (including translation), and at the same time make available the source code of such work at least in a~way and scope that are comparable to the way and scope in which the source code of the Work is made available. }\fi\fi }\@declarationOptionSelectedtrue\fi \ifx5#1 \DeclareRobustCommand{\thedeclarationofauthenticity}{\if\@lang1{% diff --git a/chapters/00_introduction.tex b/chapters/00_introduction.tex index 735eda8..c1b018b 100644 --- a/chapters/00_introduction.tex +++ b/chapters/00_introduction.tex @@ -5,14 +5,14 @@ \begin{figure}[htp] \centering - \includegraphics[width=0.9\linewidth]{img/introduction/so-flutter-trend.pdf} + \includegraphics[width=0.88\linewidth]{img/introduction/so-flutter-trend.pdf} \caption{Flutter Trend Against Other Popular Frameworks~\cite{so-flutter-trend}.} \label{fig:so-flutter-trend} \end{figure} During~2017, the~concept of another approach was proposed, where the~application uses low-level platform API to draw over the whole screen with keeping high performance and access to native features. Later on, from this concept open-source framework Flutter, made by Google, was created~\cite{flutter}. -The Flutter for the last three years until now (first half of 2020) started to gain developers attention, and it was highly promoted by Google. One indication of its growing popularity is \textit{Stack~Overflow Developer Survey~2019}~\cite{so-2019-survey} where it took third place of ``Most Loved'' framework directly after \textit{.NET Core} and \textit{Torch/PyTorch} and highly growing trend among questions created during the last years (\Cref{fig:so-flutter-trend}). However, like with every new technology, the Flutter can become well-known and well used or will be left as a dead-end. +Flutter for the last three years until now (first half of 2020) started to gain developers attention, and it was highly promoted by Google. One indication of its growing popularity is \textit{Stack~Overflow Developer Survey~2019}~\cite{so-2019-survey} where it took third place of ``Most Loved'' framework directly after \textit{.NET Core} and \textit{Torch/PyTorch} and highly growing trend among questions created during the last years (\Cref{fig:so-flutter-trend}). However, like with every new technology, the Flutter can become well-known and well used or will be left as a dead-end. \section{Motivation} There are many reasons why the author chose this topic for the thesis. First of all, his bachelor thesis~\cite{nymsap-bp} already focused on mobile application development, although it used different cross-platform technology -- Xamarin. During his ongoing studies, the author discovered and started to use new, by his opinion, promising framework Flutter. So his first goal and motivation was to study Flutter more in-depth and bring comprehensive study material of this framework for others. The second reason was to conclude if Flutter can become a framework which can be used to create production-ready applications or if it is still an experimental framework. Last reason was motivation to create complex, and yet, simple to use mobile application for everyone who seeks to find new cafes to visit. @@ -21,8 +21,8 @@ \section{Structure} The thesis is divided to four chapters: \begin{itemize} \item \Cref{ch:flutter} deals with introduction to Flutter framework, its concept~and internal functionality. -\item \Cref{ch:analysis} introduce proposed Coffee Time application. Describes the~created prototype and its user testing. The~analysis of back-end services is described. -\item \Cref{ch:implementation} describes process of back-end implementation as well of Coffee Time application. In the chapter, details how its implemented, which approaches was taken and how development process was done. +\item \Cref{ch:analysis} introduces proposed Coffee Time application. It describes the~created prototype and its user testing. The~analysis of back-end services is also described. +\item \Cref{ch:implementation} describes a~process of back-end implementation as well as of Coffee Time application implementation. In the~chapter, details how its implemented, which approaches was taken and how development process was done. \item \Cref{ch:testing} describes final application release and its testing. \end{itemize} In conclusion, the results are compared with the goals of this thesis. diff --git a/chapters/01_flutter.tex b/chapters/01_flutter.tex index 0050e69..e471f07 100644 --- a/chapters/01_flutter.tex +++ b/chapters/01_flutter.tex @@ -66,7 +66,7 @@ \subsection{Reactive Programming} \subsubsection{The Notion of Streams} A Stream can be described as ``A pipe with two ends, only one allowing to insert something into it. When something is inserted into the pipe, it flows inside the pipe and goes out by the other end''~\cite{reactive-didier}. The~Stream can convey any~data type, from simple values to~events, complex object or even another stream. The~data can come to the~Stream, for example, from an external data source such as server connection or from events such as user interactions. In~Dart, the Streams support manipulating them, filtering, re-grouping, modify data before they are send and~much more. This functionality can be used to build reactive \gls{ui}. Flutter has several widgets supporting streams to rebuild part of the~\gls{ui} whenever new data arrived into the~Stream. -The answer to the question ``What is reactive programming$?$'' could be ``Reactive programming is programming with asynchronous data streams``~\cite{reactive-didier}\cite{reactive-red-hat}. Within Flutter framework, anything from an~interaction event (a~tap, a~gesture), changes of a~variable, messages, everything that may change is conveyed and triggered by streams. +The answer to the question ``What is reactive programming$?$'' could be ``Reactive programming is programming with asynchronous data streams`` \cite{reactive-didier}\cite{reactive-red-hat}. Within Flutter framework, anything from an~interaction event (a~tap, a~gesture), changes of a~variable, messages, everything that may change is conveyed and triggered by streams. It means that with reactive programming, according to~\cite{reactive-didier}, the~application: @@ -263,14 +263,14 @@ \subsection{Case Study Note} Following lines in this section introduce some used patterns and solutions for state management. Every solution will use the same case study but with appropriate implementation. Each solution's full code is available as an~appendix. The design and functionality remain the same as introduced before. % --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # \subsection{Inherited Widget} -One solution offered by \textit{Flutter} framework is the concept of \textit{InheritedWidget}~\cite{flutter-inherited-widget}~\cite{notion-widget-didier}. This concept is used across the framework -- for example, obtaining current \textit{Theme} or screen device information through \textit{MediaQuery} object. Both can be accessed through convention ``of'' method -- \verb|Theme.of(context)| returns \textit{Theme} object. Internally these objects makes usage of InheritedWidget. InheritedWidget has two features: +One solution offered by \textit{Flutter} framework is the concept of \textit{InheritedWidget}~\cite{flutter-inherited-widget}~\cite{notion-widget-didier}. This concept is used across the framework -- for example, obtaining current \textit{Theme} or screen device information through \textit{MediaQuery} object. Both can be accessed through convention ``of'' method -- \verb|Theme.of(context)| returns \textit{Theme} object. Internally these objects makes usage of an~\textit{InheritedWidget}. The~\textit{InheritedWidget} has two features: \begin{itemize} \item It can be accessed from any widget directly. \item Whenever the widget changes, the accessing widget is automatically rebuilt. \end{itemize} -The second implies that, for example, whenever widget access the~\textit{MediaQuery} and it is changed (the device is rotated, resolution changed,\ldots ), the~widget is rebuilt to handle these changes. +The~second implies that, for example, whenever widget access the~\textit{MediaQuery} and it is changed (the device is rotated, resolution changed,\ldots ), the~widget is rebuilt to handle these changes. \begin{listing}[ht] \begin{minted}{dart} @@ -645,9 +645,7 @@ \subsection{Notion of Keys} \label{listing:keys_page_stateless} \end{listing} -The~problem can occur when some widget uses a~collection of widgets of the~same type that holds some state. Consider a~concrete example where \verb|SquarePage| holds a~list of \verb|Square| widgets~(\Cref{listing:keys_page_stateless}). Each \verb|Square| (as a~\textit{StatelessWidget}) has defined random colour through a~constructor. After a~button is clicked, the~squares are swapped. With \verb|Square| as \textit{StatelessWidgets}, everything works as expected. - -\begin{listing}[ht] +\begin{listing}[!htb] \begin{minted}{dart} class Square extends StatefulWidget { Square({Key key}) : super(key: key); @@ -672,8 +670,9 @@ \subsection{Notion of Keys} \label{listing:keys_square_stateful} \end{listing} -However, if the~\verb|Square| becomes \textit{StatefulWidget}~(\Cref{listing:keys_square_stateful}) and the~button is clicked, it seems like nothing happened -- squares stay on the same place. When the~widget is marked to rebuilt, it walks through \textit{Elements} and if the~widget type and the~\textit{Key} match, the~\textit{Element} updates its reference to new Widget. In the~case of \textit{StatefulWidget}, the~associated state is linked to the~\textit{Element} object~(\Cref{fig:keys_start}). When squares are shifted, the~\textit{Element} is marked as dirty. It walks through square's \textit{StatefulElement} and checks if the~widget type and the~\textit{Key} match. They match because no \textit{Keys} are assigned to them. Hence, the~\textit{Element} updates its widget reference, but the~associated state remains the~same~(\Cref{fig:keys_wrong}). -The~key is to add \textit{Key}. There are several types of Keys such as \textit{ValueKey}, where some unique value can be assigned (for example article's id). For \verb|Square| example, the~\textit{UniqueKey} which generates unique identification is enough for usage. After the~\textit{Keys} are assigned, \mint{dart}|final squares = [Square(key: UniqueKey()),Square(key: UniqueKey())]| the example works again as expected. The~full example code is available as~before within appendix. +The~problem can occur when some widget uses a~collection of widgets of the~same type that holds some state. Consider a~concrete example where \verb|SquarePage| holds a~list of \verb|Square| widgets~(\Cref{listing:keys_page_stateless}). Each \verb|Square| (as a~\textit{StatelessWidget}) has defined random colour through a~constructor. After a~button is clicked, the~squares are swapped. With \verb|Square| as \textit{StatelessWidgets}, everything works as expected. +However, if the~\verb|Square| becomes \textit{StatefulWidget}~(\Cref{listing:keys_square_stateful}) and the~button is clicked, it seems like nothing happened --~squares stay on the same place. When the~widget is marked to rebuilt, it walks through \textit{Elements} and if the~widget type and the~\textit{Key} match, the~\textit{Element} updates its reference to new Widget. In the~case of \textit{StatefulWidget}, the~associated state is linked to the~\textit{Element} object~(\Cref{fig:keys_start}). When squares are shifted, the~\textit{Element} is marked as dirty. It walks through square's \textit{StatefulElement} and checks if the~widget type and the~\textit{Key} match. They match because no \textit{Keys} are assigned to them. Hence, the~\textit{Element} updates its widget reference, but the~associated state remains the~same~(\Cref{fig:keys_wrong}). +The~key is to add \textit{Key}. There are several types of Keys such as \textit{ValueKey}, where some unique value can be assigned (for example article's id). For \verb|Square| example, the~\textit{UniqueKey} which generates unique identification is enough for usage. After the~\textit{Keys} are assigned, \mint{dart}|final squares = [Square(key: UniqueKey()),Square(key: UniqueKey())]| the example works again as expected. The~full example code is available as~before within appendix. The keys should be put to the most top widget, which is used as a~root widget of collection. Otherwise, the rebuilding algorithm fails once again, and wrong behaviour will occur. In practice, \textit{Key} should be used when stateful widgets are used within collections (such as \textit{ListView}, \textit{Row} or \textit{Column}) and they are manipulated -- moved, removed and similar. Moreover, sometimes the \textit{GlobalKey} can be used to manage some widget's state ``outside''. This approach is often used with managing text inputs. % --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # diff --git a/chapters/02_analysis.tex b/chapters/02_analysis.tex index 0b4f06e..fd3cacd 100644 --- a/chapters/02_analysis.tex +++ b/chapters/02_analysis.tex @@ -413,12 +413,12 @@ \subsubsection{Low Fidelity Prototype} As a~task graph was defined, the~\textit{Lo-Fi} prototype could be made. Although the application is considered as multi-platform application, the~prototype was focused on Android, and its Material design \cite{material-design}. The~inspiration was taken from typical Material layouts, such as \textit{AppBar} with title and subsequent actions or tabs the bottom of the screen. First of all, the rough prototype was drawn on paper. Its purpose was to come up with some ideas and considered layout. After that, the~\textit{Balsamiq} \cite{balsamiq} prototyping software was used. The~\textit{Balsamiq} tries to mimic pencil and paper. The~prototype is created with a~set of components which looks like they are drawn by hand. -The~most important feature was the~ability to create deep links between screens or components. With a~few clicks, the prototype was able to handle actions such as the open application menu or navigate to detail. With that tool, the clickable prototype focused on essential app's features was created. As a result, the PDF was exported. The PDF is enclosed as part of the thesis located at \verb|prototype/lofi.pdf|. The portion of the result is shown in~\Cref{fig:lofi}. +The~most important feature was the~ability to create deep links between screens or components. With a~few clicks, the~prototype was able to handle actions such as the~open application menu or navigate to detail. With that tool, the~clickable prototype focused on essential app's features was created. As a result, the PDF was exported. The~PDF is enclosed as part of the thesis located at \verb|prototype/lofi.pdf|. The portion of the result is shown in~\Cref{fig:lofi}. \begin{figure}[htp] \centering \includegraphics[width=0.75\textwidth]{img/analysis/lofi.png} - \caption{\gls{lofi} prototype. Cafe list (left) and Detail Screen (right).} + \caption{\gls{lofi} Prototype. Cafe List (Left) and Detail Screen (Right).} \label{fig:lofi} \end{figure} @@ -453,7 +453,7 @@ \subsubsection{Low Fidelity Prototype} \end{questions} \subsubsection{High Fidelity Prototype} -The \gls{hifi} prototype was created as Flutter application. Because of that, in the future, the already written code could be reused. The aim was to create a fully functional prototype for Android devices. As was said earlier in this chapter, the aim of \gls{hifi} is to provide an application so it behaves as real one, which is mainly focused on user interface interaction. That means that the~application does not have any real communication with back-end services. For Coffee Time there was prepared local JSON data source with randomly generated cafe names and their data. Besides that, a~few, real one cafes were added to be less general and more known for potential testers. The~\gls{hifi} focused on all earlier described use cases. The cafe list screen and cafe's detail screen is shown~in~\Cref{fig:hifi}. The prototype's source code can be found at~\verb|https://github.com/petrnymsa/coffee-time/releases/tag/prototype|~\cite{hifi-prototype}. +The \gls{hifi} prototype was created as Flutter application. Because of that, in the future, the already written code could be reused. The aim was to create a fully functional prototype for Android devices. As was said earlier in this chapter, the aim of \gls{hifi} is to provide an application so it behaves as real one, which is mainly focused on user interface interaction. That means that the~application does not have any real communication with back-end services. For Coffee Time there was prepared local JSON data source with randomly generated cafe names and their data. Besides that, a~few, real one cafes were added to be less general and more known for potential testers. The~\gls{hifi} focused on all earlier described use cases. The cafe list screen and cafe's detail screen is shown~in~\Cref{fig:hifi}. The prototype's source code can be found at \verb|https://github.com/petrnymsa/coffee-time/releases/tag/prototype|~\cite{hifi-prototype}. \begin{figure}[htp] \centering @@ -706,10 +706,10 @@ \subsubsection{Nearby Search} \hline \textbf{Parameter} & \textbf{Usage} \\ \hline key & API key \\ \hline -location & latitude,longtitude \\ \hline -radius & circular radius in meters, max 50 000m \\ \hline +location & latitude, longtitude \\ \hline +radius & circular radius in meters, max 50 000~m \\ \hline language & language code \\ \hline -opennow & place should be open. If place does not have this field, it is omitted from results \\ \hline +opennow & place is currently open; if place does not have this field, it is omitted from results \\ \hline type & place type, always set to \textit{cafe} \\ \hline pagetoken & token for next page \\ \hline \end{tabularx} @@ -854,4 +854,4 @@ \subsubsection{Firebase Authentication} % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % \section{The Conclusion} -In this chapter, the considered application Coffee Time was introduced. The~analysis of existing alternatives was made to obtain inspiration for how each application behaves. The~prototype was created to propose user interface and tested it with users. In the~end, the~analysis of Coffee Time API was made along with analysis of chosen technology to build this API. \ No newline at end of file +In this chapter, the considered application Coffee Time was introduced.\\ The~analysis of existing alternatives was made to obtain inspiration for how each application behaves. The~prototype was created to propose user interface and tested it with users. In the~end, the~analysis of Coffee Time API was made along with analysis of chosen technology to build this API. \ No newline at end of file diff --git a/chapters/03_implementation.tex b/chapters/03_implementation.tex index b20d630..f6aae7f 100644 --- a/chapters/03_implementation.tex +++ b/chapters/03_implementation.tex @@ -1,6 +1,6 @@ \chapter{Implementation} \label{ch:implementation} -When the~Coffee Time specification was created and the~prototype was tested, the~implementation itself could begin. In this chapter, the implementation details are covered. In the beginning, the proposed architecture of the~application is introduced and explained. Next section describes how the~Coffee Time API is designed and implemented. Which framework for creating REST~API was chosen and how it can be connected to \textit{Firebase} services. Detailed section of the mobile application implementation follows. In this section, used techniques and packages are described to achieve desired functionality. +When the~Coffee Time specification was created and the~prototype was tested, the~implementation itself could begin. In this chapter, the implementation details are covered. In the beginning, the proposed architecture of the~application is introduced and explained. Next section describes how the~Coffee Time API is designed and implemented. This section also covers which framework for creating REST~API was chosen and how it can be connected to \textit{Firebase} services. Detailed section of the mobile application implementation follows. In this section, used techniques and packages are described to achieve desired functionality. % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % \section{Clean Architecture} In order to have easy to write, maintainable and testable code, some overall architecture should be considered. The~architecture should follow these rules: @@ -14,34 +14,34 @@ \section{Clean Architecture} \begin{figure}[ht] \centering \includegraphics[width=0.75\linewidth]{img/implementation/CleanArchitecture.jpg} - \caption{Clean Architecture defined by B.~Martin~\cite{clean-architecture-article}.} + \caption{Clean Architecture Defined By \textit{B.C.~Martin}~\cite{clean-architecture-article}.} \label{fig:clean-arch-bmartin} \end{figure} -There are several attempts and approaches on how to design such architecture~\cite{clean-architecture-article}. The inspiration for chosen architecture comes from \textit{Clean Architecture}, initially proposed by \textit{Bob C. Martin}~\cite{clean-architecture-book}. In the~basic form the~\textit{Clean Architecture} (\cref{fig:clean-arch-bmartin}) consists of four layers organised as circles. Architecture defines dependency rule where each layer should be dependent only on the~inner circles. Accordingly to \textit{Bob C. Martin}~\cite{clean-architecture-article} layers can be described as: +There are several attempts and approaches on how to design such architecture~\cite{clean-architecture-article}. The inspiration for chosen architecture comes from \textit{Clean Architecture}, initially proposed by \textit{Bob C. Martin}~\cite{clean-architecture-book}. In the~basic form the~\textit{Clean Architecture} (\cref{fig:clean-arch-bmartin}) consists of four layers organised as circles. Architecture defines dependency rule where each layer should be dependent only on the~inner circles. Accordingly to \textit{Bob C. Martin}~\cite{clean-architecture-article}, layers can be described as: \begin{quote} \textbf{Entities} encapsulate Enterprise-wide business rules. These entities, which can be simple objects or hierarchical structure of objects are the least likely to change when something external changes. \textbf{Use Cases} are application-specific business rules. They encapsulate all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities and direct those entities to use their enterprise-wide business rules to achieve the goals of the use case. Changes within the use case do not affect entities and similarly, changes of outer layers (such as interchanging database provider) do not affect the use cases. -\textbf{Interface Adapters} converts data from the format most convenient for the use cases and entities to the format most convenient for some external agency such as database or API. The application presentation (UI) should be here. Data models in this layer most likely consist only of data that are passed down to the use cases and then back from use cases to the view. This layer is also responsible for converting any data from external forms into an internal form used by the use cases. +\textbf{Interface Adapters} converts data from the format most convenient for the use cases and entities to the format most convenient for some external agency such as database or API. The~application presentation (UI) should be here. Data models in this layer most likely consist only of data that are passed down to the use cases and then back from use cases to the view. This layer is also responsible for converting any data from external forms into an internal form used by the use cases. \textbf{Frameworks and Driver} contain any external frameworks and tools. This layer typically exposes interfaces to glue the external framework wit the rest of the application. \end{quote} -This architecture was chosen for its simplicity of dependencies, easy testability and extendability. +This architecture was chosen for its simplicity of dependencies, easy \\ testability and extendability. % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % ----- % \section{Coffee Time API} The Coffee Time API is served through \textit{Firebase Cloud Functions} services. Each function can run the~backend code in response to events triggered by \textit{Firebase} features and~HTTPS requests. Functions can be written with \\\textit{JavaScript} or \textit{Typescript} language. For implementation, the~\textit{Typescript} was chosen due to the safer typing system, and due to the fact, that author has more experience with \textit{Typescript} than with plain \textit{JavaScript}. Functions are written under \textit{Node.js}~\cite{node-js}, and every function that is exported is considered as ``Cloud function'' and can be accessed through HTTPS request. This can be used to build fully functional REST API. For the implementation, \textit{Express.js} framework~\cite{express-js} was selected as popular and easy to use solution. Developers define routes, which HTTP method can be used and how the request should be processed. -\textit{Express.js} has a simple yet powerful mechanism of middlewares, where each request can be pre-processed before sending to the next processing. For example, it can be used to check if the user is authorised to make the request. With this setup, nothing prevented to create Coffee Time API. Furthermore, as~\textit{Express.js} allows to define REST~API, only one cloud function can be exported -- ``the api'' function. All requests are processed through this function. However, before implementation itself, it had to be defined what API will offer and how it can be consumed. +\textit{Express.js} has a simple yet powerful mechanism of middlewares, where each request can be pre-processed before sending to the next processing. For example, it can be used to check if the user is authorised to make the request. With this setup, nothing prevented to create Coffee Time API. Furthermore, as~\textit{Express.js} allows to define REST~API, only one cloud function can be exported -- ``the API'' function. All requests are processed through this function. However, before implementation itself, it had to be defined what API will offer and how it can be consumed. % --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # \subsection{The API Endpoints} The~API has endpoints divided into three categories -- places, tags and photos. As a~client is considered to be multilingual, the~API is too. The~Places API accepts, as was described earlier, language parameter to specify how the~response should be localised. The~API is designed with language parameter as a~mandatory part of the~URL for places related requests. The~tags category has endpoints for obtaining and manipulating tags. Lastly, photo category gives access to downloading the place's photo. Every response coming from \gls{gpa} which returns places are modified such that each ``place'' entry contains additional \verb|tags| field which is an~array of the~\verb|tag| model. -The~\cref{table:cta-places} describes each API endpoint and its usage. Mandatory parameters within the~URL are highlighted as \verb||. Each URL is shown without prefix \verb|http[s]://domain/api| (the hosting URL and \verb|/api| suffix). +\Cref{table:cta-places} describes each API endpoint and its usage. Mandatory parameters within the~URL are highlighted as \verb||. Each URL is shown without prefix \verb|http[s]://domain/api| (the hosting URL and \verb|/api| suffix). % ----------------------------- \begin{table}[ht] \centering @@ -71,7 +71,7 @@ \subsection{The API Endpoints} \label{table:cta-nearby-params} \end{table} -The~\cref{table:cta-nearby-params} describes \textit{nearby} parameter. Note that, if radius is omitted, the results are sorted by Google's ranking -- ``Ranking will favor prominent places within the specified area. Prominence can be affected by a place's ranking in Google's index, global popularity, and other factors''~\cite{google-places-api-nearby-req} otherwise the results are sorted by distance. +\Cref{table:cta-nearby-params} describes \textit{nearby} parameter. Note that, if radius is omitted, the results are sorted by Google's ranking -- ``Ranking will favor prominent places within the specified area. Prominence can be affected by a place's ranking in Google's index, global popularity, and other factors''~\cite{google-places-api-nearby-req} otherwise the results are sorted by distance. % ----------------------------- \begin{table}[ht] \centering @@ -86,7 +86,7 @@ \subsection{The API Endpoints} \label{table:cta-find-params} \end{table} -The~\cref{table:cta-find-params} describes \textit{find} parameters. The \verb|location=lan,lng| and \verb|radius| must be provided both if used. +\Cref{table:cta-find-params} describes \textit{find} parameters. The \verb|location=lan,lng| and \verb|radius| must be provided both if used. % ----------------------------- \begin{table}[ht] \centering @@ -117,11 +117,11 @@ \subsection{The API Endpoints} \Cref{table:cta-tags} describes all endpoints related to \textit{tags}. The POST request to \verb|/tags/| should have a~body with array of \textit{TagUpdate} model. The~example is listed in~\cref{listing:tag-update-post} where \verb|id| contains tag id and \verb|change| contains value of \verb|like| or \verb|dislike| which corresponds with increasing (decreasing) tag's score. % --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # --- # \subsection{Express.js Pipeline} -Express.js framework has a powerful and configurable way how to process incoming request. Every request can be processed through functions, called middlewares, before sent to a router. The router is a set of functions which maps part of URL with HTTP method to trigger response to the incoming request. Together it creates a flexible way of developing any form of a web-server or in case of Coffee Time API a REST API. +\textit{Express.js} framework has a powerful and configurable way how to process incoming request. Every request can be processed through functions, called middlewares, before sent to a router. The router is a set of functions which maps part of URL with HTTP method to trigger response to the incoming request. Together it creates a flexible way of developing any form of a web-server or in case of Coffee Time API a REST API. Middleware functions can execute any code, make changes to the request (or to the response), end the request-response cycle or call next middleware~\cite{express-js-middleware}. The~function accepts three parameters -- \verb|req|, \verb|res| and \verb|next|. \verb|Req| is a request object containing all information related to the incoming request. The \verb|res| is a response object which can be used to alter the response, and~\verb|next| is the~callback function to trigger next middleware. In case of the Coffee Time API, three middlewares are used to process every incoming request. -First middleware check and parse request body (if any provided) in JSON format. JSON format was chosen as a~primary format for communication with Google Places API, the \gls{cta} forces JSON format to every request which contains the body. Next middleware logs each incoming request to the cloud functions. Each log message contains issued HTTP method, requested URL and sent body if present. Last middleware authorises incoming request against Firebase Authentication Service. +First middleware checks and parses request body (if any provided) in JSON format. JSON format was chosen as a~primary format for communication with Google Places API, the \gls{cta} forces JSON format to every request which contains the body. Next middleware logs each incoming request to the cloud functions. Each log message contains issued HTTP method, requested URL and sent body if present. Last middleware authorises incoming request against Firebase Authentication Service. \subsubsection{Authorisation Middleware} Each request to the API has to be authorised against Firebase Authentication services. The~authorisation process uses a~\gls{jwt} open standard~\cite{jwt-intro}. Each request has to include Authorisation header with ``Bearer token'' obtained earlier from \textit{Firebase Authentication}. @@ -213,28 +213,30 @@ \subsection{Domain Layer} One of important requirements of the Presentation layer and overall Flutter's philosophy is immutability. Hence, the domain entities are designed as immutable objects. Another requirement is object equality. By default, Dart compare objects by identity -- two objects are same instance, they are considered as identical (equal). In order to have fully functional application, it is necessary to override default equality behaviour to comparison by object properties. \subsubsection{Equatable Package} -If the default equality behaviour has to be changed, the \verb|==| operator and~\verb|hashCode| getter have to be overridden~\cite{dart-equality}. +If the default equality behaviour has to be changed, the \verb|==| operator\\ and~\verb|hashCode| getter have to be overridden~\cite{dart-equality}. Even with small classes, this work becomes quickly tedious and can leads to unnecessary bugs for example when some property is added and developer forgot to update these overrides. Therefore in case of complex classes the~amount of bugs only increases. \textit{Equatable} package~\cite{package-equatable} (developed by \textit{F. Angelov}) was created to simplify creating immutable classes with proper equality implementation. Class which needs to implement equality has to extend \verb|Equatable| base class provided by the package. Then it is needed to override \verb|props| getter where all class properties are listed. With that setup, equatable package internally provides proper equality comparison. This package is used to for all entities and classes which needed proper equality implementation. An example of its usage is shown in~\Cref{listing:ct-opening-hour-entity}, which is \verb|OpeningHours| entity implementation. -\begin{listing}[ht] +\begin{listing}[!htb] \begin{minted}{dart} class OpeningHours extends Equatable { final bool openNow; final List periods; final List weekdayText; - OpeningHours({this.openNow, this.periods, this.weekdayText}); + OpeningHours({this.openNow, + this.periods, this.weekdayText}); OpeningHours copyWith( - {bool openNow, List periods, List weekdayText}) { - return OpeningHours( - openNow: openNow ?? this.openNow, - periods: periods ?? this.periods, - weekdayText: weekdayText ?? this.weekdayText); + {bool openNow, + List periods, + List weekdayText}) { + return OpeningHours( + openNow: openNow ?? this.openNow, + periods: periods ?? this.periods, + weekdayText: weekdayText ?? this.weekdayText); } - @override List get props => [openNow, periods, weekdayText]; } @@ -391,7 +393,7 @@ \subsubsection{Flutter\_bloc Package} \begin{itemize} \item \textbf{BlocProvider} -- Provides \gls{bloc} instance down to the tree. Internally it is using \textit{Provider} package. - \item \textbf{BlocBuilder$<$Bloc, State$>$} -- Listen for changes from given \textit{Bloc} and~its state, which has to be provided somewhere in the~parent widgets. \textit{BlocBuilder} has \textit{builder} callback, where new widget based on obtained state is returned. + \item \textbf{BlocBuilder$<$Bloc, State$>$} -- Listen for changes from given \textit{Bloc} and~its state, which has to be provided somewhere in the~parent widgets. It has \verb|builder| callback, where a~new widget based on obtained state is returned. \item \textbf{BlocListener$<$Bloc, State$>$} -- In order to do side effects, such as display notification, \textit{BlocListener} can be used. As~\textit{BlocBuilder} it is listening for changes from Bloc and its new state. \item \textbf{BlocConsumer$<$Bloc,State$>$} -- Combines functionality of \textit{BlocBuilder} and \textit{BlocListener} together. \end{itemize} @@ -520,11 +522,11 @@ \section{SOLID and Dependency Injection} One important part of maintainable and testable code are SOLID principles, originally designed by \textit{Bob C. Martin}~\cite{bob-martin-design-patterns}. Each letter stands for one principle: \begin{enumerate} - \item Single Responsibility Principle -- a class should only have on responsibility. That class should have one reason to change. - \item Open Closed Principle -- a class should be open for extension, but closed for modification. - \item Liskov Substitution Principle -- if class \textit{A} is a subtype of class \textit{B}, then it should be possible to replace \textit{B} with \textit{A} without disrupting the~behaviour of the program. - \item Interface Segregation -- many specific interfaces are better than one general-purpose interface. In other words, split larger interfaces to smaller ones. - \item Dependency Inversion -- high-level modules should not depend on low-level modules. Both should depend on abstractions. + \item \textit{Single Responsibility Principle} -- a~class should only have on responsibility. That class should have one reason to change. + \item O\textit{pen Closed Principle} -- a~class should be open for extension, but closed for modification. + \item \textit{Liskov Substitution Principle} -- if class \textit{A} is a subtype of class \textit{B}, then it should be possible to replace \textit{B} with \textit{A} without disrupting the~behaviour of the program. + \item \textit{Interface Segregation} -- many specific interfaces are better than one general-purpose interface. In other words, split larger interfaces to smaller ones. + \item \textit{Dependency Inversion} -- high-level modules should not depend on low-level modules. Both should depend on abstractions. \end{enumerate} Dependency Injection mechanism is used to provide concrete implementations of each required abstraction to classes which depends on it. diff --git a/chapters/04_deploy.tex b/chapters/04_deploy.tex index 5a28fa3..e0720cf 100644 --- a/chapters/04_deploy.tex +++ b/chapters/04_deploy.tex @@ -1,7 +1,7 @@ \chapter{Application Release} \label{ch:testing} -Before application can be released to production it should be properly tested. In this last chapter, the development process is outlined, automated unit testing and pull-request approach of development even as single developer. Later on, the process of incrementally tested application though internal a beta testing channels on the Android devices is explained. In the end, released version of the application is shown along with link to \textit{Google Play Store}. +Before application can be released to production, it should be properly tested. In this last chapter, the~development process, automated unit testing and pull-request approach of development even as a~single developer are outlined. Later on, the process of incrementally tested application though internal a beta testing channels on the Android devices is explained. In the end, released version of the application is shown along with link to \textit{Google Play Store}. \section{Development Workflow} Coffee Time was developed as fully open-sourced (MIT licensed) application available at GitHub. Even as a~single developer, author wanted to have full control over development process. The~development workflow was setup accordingly: @@ -131,9 +131,9 @@ \section{User Testing Re-Evaluation} \begin{answer} Landscape mode was disabled. \end{answer} - \item The map marker could contain more information than the cafe's name only. + \item The map marker could contain more information than the~cafe's name only. \begin{answer} - Currently it is not doable due to a~limitation of the maps plugin. + Currently it is not doable due to a~limitation of the~maps plugin. \end{answer} \end{questions} @@ -144,7 +144,7 @@ \section{User Testing Re-Evaluation} \section{Release} Coffee Time was released as version \textit{1.0.0} to the \textit{Google Play Store} for Android devices. In order to publish a release, a proper name and description in all available languages had to be filled before the application could be accepted. Moreover, the store displays application photo, logo and a~cover image. These fields were necessary to fill as well. After the~release, two minor versions \textit{1.0.1} and \textit{1.0.2} were released as hotfixes to prevent application crashes on some devices. -\Cref{fig:ct-released-version} shows released version. In contrast with prototype version (\Cref{fig:hifi}), there are no significant graphical changes other than +\Cref{fig:ct-released-version} shows the~released version. In contrast with prototype version (\Cref{fig:hifi}), there are no significant graphical changes other than \begin{itemize} \item changed font typeface, diff --git a/chapters/_conclusion.tex b/chapters/_conclusion.tex index e5f9dd6..239586b 100644 --- a/chapters/_conclusion.tex +++ b/chapters/_conclusion.tex @@ -3,7 +3,7 @@ Next chapter was focused on introducing proposed application, its designing process, prototyping and user testing. Low-Fidelity and High-Fidelity prototypes were created to verify proposed design. Both prototypes are also included along with final implementation in the~appendix. -In the~implementation, more details were covered and also introduced several popular packages and solutions within Flutter community. In the~end, the~\textit{Android} version was successfully tested and released for download. +In the~implementation chapter, more details were covered and also several popular packages and solutions within Flutter community were introduced. In the~end, the~\textit{Android} version of the~Coffee Time application was successfully tested and it was released for download. \section{Next Steps} Coffee Time is for sure not ``feature-complete'' and there is plenty of space for improvements. Ongoing future development is planned to obtain more experience with Flutter framework and bring an~even better, feature ``rich'', application. @@ -12,15 +12,15 @@ \section{Next Steps} \begin{itemize} \item Add missing feature ``searching cafes in custom location''. - \item Synchronization of favorited cafes. - \item Better map view with more information in it. - \item Optimise application performance, responsivity and adaptability to different form factors, screen sizes and resolutions. + \item To synchronize favourite cafes. + \item A~better map view with more information in it. + \item Optimise application performance, responsivity and adaptability to different form factors (mobile phones, tablets, \ldots), screen sizes and resolutions. \item Add full \textit{iOS} support. This includes redesign of the application to more modern cross-platform look. - \item As a experiment, build application also for web and desktop platform. + \item As an~experiment, build application also for web and desktop platform. \end{itemize} \subsection{Personal Author's Note in the End} \begin{quote} -I really believe that Flutter is a~promising framework, which increasingly gains on popularity and in the closest future there will be more opportunities as the~framework will get adopted by larger companies. In contrast with Xamarin, my subjective opinion is that the~Flutter development workflow is faster, more convenient and easier to use. Of course, as with every new popular framework, there is no guarantee that Flutter will be truly the right solution in the future. But I am convinced that, at this moment, Flutter is stable to use as a production-ready framework. If the application does not use very specific platform features, Flutter can be used without any hesitation. +I really believe that Flutter is a~promising framework which increasingly gains on popularity and in the closest future there will be more opportunities as the~framework will get adopted by larger companies. In the~contrast with Xamarin, my subjective opinion is that the~Flutter development workflow is faster, more convenient and easier to use. Of course, as with every new popular framework, there is no guarantee that Flutter will be truly the right solution in the future. But I am convinced that, at this moment, Flutter is stable to use as a production-ready framework. If the application does not use very specific platform features, Flutter can be used without any hesitation. \end{quote} \end{conclusion} \ No newline at end of file diff --git a/dp_nymsa.tex b/dp_nymsa.tex index 591a1f2..49d6f0b 100644 --- a/dp_nymsa.tex +++ b/dp_nymsa.tex @@ -32,6 +32,9 @@ \usepackage{minted} % code highlight \usemintedstyle{friendly} +% HIDE red boxes around links +% \hypersetup{hidelinks} % #### ENABLE BEFORE PRINT #### + % FIX https://tex.stackexchange.com/questions/343494/minted-red-box-around-greek-characters \makeatletter \AtBeginEnvironment{minted}{\dontdofcolorbox} @@ -65,7 +68,6 @@ } % Q.A env - \newenvironment{questions}{\begin{enumerate}[label=\bfseries\arabic*.]\bfseries} {\end{enumerate}} \newenvironment{answer}{\par\normalfont}{} @@ -83,14 +85,14 @@ \acknowledgements{I would like to thank my supervisor \textit{Ing. David Šenkýř} for his guidance and~valuable advices. Sincere gratitude belongs to my partner and~family for their support during work on this thesis.} -\abstractCS{Práce se zabývá využitím multiplatformního frameworku Flutter pro tvorbu mobilních, webových tak i~desktop aplikací. Hlavním tématem práce framework Flutter a~jeho použitelnost při tvorbě aplikací. Flutter je prakticky vyzkoušen na návrhu~a~implementaci aplikace Coffee Time pro operační systém Android. Coffee Time uživatelům pomáhá vyhledávat kavárny v~blízkém okolí s~možností filtrování dle různých kritérií.} +\abstractCS{Práce se zabývá multiplatformním frameworkem Flutter, a~to nejen pro tvorbu mobilních aplikací. V~práci je popsán samotný framework, jeho použitelnost a~využití při vývojí aplikací. Následně je famework použit při~návrhu a~implementaci aplikace Coffee Time pro operační systém Android. Aplikace vyhledává kavárny v~blízkém okolí s~možností filtrování dle různých kritérií. Uživatelé aplikace si mohou zobrazit detailní informace, spustit navigaci nebo přečíst hodnocení. Aplikace byla navrhnnuta pomocí prototypu uživatelského rozhraní a~jeho postupném otestování. Nakonec byla aplikace zpřístupněna a~nasazena ke stažení pro mobilní telefony se systémem Android.} -\abstractEN{A~thesis is focused on multi-platform framework Flutter for creating mobile, web and desktop applications. The~main topic is Flutter framework and its usability during application development. In practice, Flutter is used to design and implement a~Coffee Time application for Android devices. Coffee Time helps users to search nearby cafes with filtering by different criteria.} +\abstractEN{This thesis is focused on multi-platform framework Flutter for creating not only mobile applications. In the~thesis, Flutter framework and its usability during application development are described. Flutter is used to design and implement the~Coffee Time application for Android devices. This application is able to search nearby cafes with options to filter them by different criteria. Application users can display cafe details, launch navigation or read reviews. The~application was designed using a~prototype user interface and its gradual testing before the~actual implementation. In the~end, the~application was released for download to Android devices.} \placeForDeclarationOfAuthenticity{Prague} \declarationOfAuthenticityOption{4} %volba Prohlášení //TODO -\keywordsCS{Flutter framework, reaktivní programování, Android aplikace, vyhledávač kaváren, serverless, Firebase.} +\keywordsCS{Flutter framework, reaktivní programování, Android aplikace, vyhledávač kaváren, serverless, Firebase.\clearpage} \keywordsEN{Flutter framework, reactive programming, Android application, cafe search, serverless, Firebase.} %volitelná URL práce, objeví se v tiráži @@ -100,17 +102,12 @@ \begin{document} % Acronyms and glossary -% \newglossaryentry{formula} -% { -% name=formula, -% description={A mathematical expression} -% } -\newacronym{aot}{AOT}{Ahead-of-time} +\newacronym{aot}{AOT}{Ahead-of-Time} \newacronym{bloc}{BLoC}{Business Logic Component} \newacronym{ctu}{CTU}{Czech Technical University} \newacronym{cta}{CTA}{Coffee Time API} \newacronym{gpa}{GPA}{Google Places API} -\newacronym{jit}{JIT}{Just-in-time} +\newacronym{jit}{JIT}{Just-in-Time} \newacronym{jwt}{JWT}{JSON Web Token} \newacronym{lofi}{Lo-Fi}{Low Fidelity} \newacronym{hifi}{Hi-Fi}{High Fidelity} diff --git a/ref.bib b/ref.bib index a158494..201acf9 100644 --- a/ref.bib +++ b/ref.bib @@ -1,7 +1,7 @@ @phdthesis{nymsap-bp, type = {Bachelor's thesis}, title = {Mobile Enterprise Architecture Process Analytic Tool Based on the DEMO Methodology}, - author = {NYMSA, Petr}, + author = {Nymsa, Petr}, month = may, school = {Czech Technical University in Prague, Faculty of Information Technology}, year = {2018}, @@ -9,28 +9,28 @@ @phdthesis{nymsap-bp @misc{react-native, title = {React Native}, - author = {Facebook Inc}, + author = {{Facebook Inc}}, url = {https://reactnative.dev}, note = {[online] [accessed: 10. 4. 2020]}, } @misc{xamarin-forms, title = {What is Xamarin Forms}, - author = {Microsoft}, + author = {{Microsoft}}, url = {https://docs.microsoft.com/en-us/xamarin/get-started/what-is-xamarin-forms}, note = {[online] [accessed: 10. 4. 2020]}, } @misc{ionic, title = {Ionic framework}, - author = {Ionic}, + author = {{Ionic}}, url = {https://ionicframework.com}, note = {[online] [accessed: 10. 4. 2020]}, } @misc{flutter, title = {Flutter framework}, - author = {Google LLC}, + author = {{Google LLC}}, url = {https://flutter.dev}, note = {[online] [accessed: 10. 4. 2020]}, } @@ -44,38 +44,37 @@ @misc{so-2019-survey @misc{so-flutter-trend, title = {Stack Overflow Flutter trends statistics}, - author = {Stack Overflow}, + author = {{Stack Overflow}}, url = {https://insights.stackoverflow.com/trends?tags=flutter\%2Cxamarin\%2Creact-native\%2Cionic}, note = {[online] [accessed: 28. 4. 2020]}, } @misc{flutter-technical-overview, title = {Technical overview - Flutter}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://flutter.dev/docs/resources/technical-overview}, note = {[online] [accessed: 28. 4. 2020]}, } @manual{dart-specs, title = {Dart Programming Language Specification}, - organization = {Google, LLC}, - address = {https://dart.dev/guides/language/specifications/DartLangSpec-v2.2.pdf}, + organization = {{Google LLC}}, + url = {https://dart.dev/guides/language/specifications/DartLangSpec-v2.2.pdf}, edition = 5, - month = 7, - year = 2019, + year = {2019}, note = {version 2.2}, } @misc{dart-type-system, title = {The Dart type system}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://dart.dev/guides/language/sound-dart}, note = {[online] [accessed: 28. 4. 2020]}, } @misc{dart-platforms, title = {Dart -- Platforms}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://dart.dev/platforms}, note = {[online] [accessed: 28. 4. 2020]}, } @@ -110,42 +109,42 @@ @misc{didier-internals @misc{flutter-widget-intro, title = {Introcution to widgets}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://flutter.dev/docs/development/ui/widgets-intro}, note = {[online] [accessed: 29. 4. 2020]}, } @misc{flutter-widget-layout, title = {Layouts in Flutter}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://flutter.dev/docs/development/ui/layout}, note = {[online] [accessed: 29. 4. 2020]}, } @misc{flutter-declarative, title = {Start thinking declaratively}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://flutter.dev/docs/development/data-and-backend/state-mgmt/declarative}, note = {[online] [accessed: 30. 4. 2020]}, } @misc{flutter-local-app-state, title = {Differentiate between ephemeral state and app state}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://flutter.dev/docs/development/data-and-backend/state-mgmt/ephemeral-vs-app}, note = {[online] [accessed: 30. 4. 2020]}, } @misc{flutter-simple-state-management, title = {Simple app state management}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple}, note = {[online] [accessed: 3. 5. 2020]}, } @misc{flutter-inherited-widget, title = {InheritedWidget}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html}, note = {[online] [accessed: 3. 5. 2020]}, } @@ -165,15 +164,15 @@ @misc{package-bloc } @misc{bloc-pattern-youtube, - title = {Flutter / AngularDart –- Code sharing, better together}, - date = {2018}, + title = {Flutter / AngularDart –- Code sharing, better together (DartConf 2018)}, author = {Paolo Soares}, url = {https://youtu.be/PLHln7wHgPE?t=1326}, + note = {[online] [accessed: 29. 4. 2020]}, } @misc{xamarin-data-binding, title = {Xamarin.Forms Data Binding}, - author = {Microsoft}, + author = {{Microsoft}}, url = {https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/}, note = {[online] [accessed: 29. 4. 2020]}, } @@ -187,7 +186,7 @@ @misc{adobe-prototype @misc{app-hejlik, title = {Gastromapa Lukáše Hejlíka}, - author = {Futured}, + author = {{Futured}}, url = {https://play.google.com/store/apps/details?id=com.thefuntasty.gmlh}, note = {[online] [accessed: 12. 4. 2020]}, } @@ -201,42 +200,42 @@ @misc{app-pivni-denik @misc{app-restu, title = {Restu}, - author = {Restu devs}, + author = {{Restu devs}}, url = {https://play.google.com/store/apps/details?id=com.thefuntasty.restu}, note = {[online] [accessed: 12. 4. 2020]}, } @misc{app-zomato, title = {Zomato}, - author = {Zomato}, + author = {{Zomato}}, url = {https://play.google.com/store/apps/details?id=com.application.zomato}, note = {[online] [accessed: 12. 4. 2020]}, } @misc{app-google-maps, title = {Google Maps}, - author = {Google LLC}, + author = {{Google LLC}}, url = {https://play.google.com/store/apps/details?id=com.google.android.apps.maps}, note = {[online] [accessed: 12. 4. 2020]}, } @misc{material-design, title = {Material Design}, - author = {Google LLC}, + author = {{Google LLC}}, url = {https://material.io/design}, note = {[online] [accessed: 12. 4. 2020]}, } @misc{material-design-elevation, title = {Elevation -- Material Design}, - author = {Google LLC}, + author = {{Google LLC}}, url = {https://material.io/design/environment/elevation.html\#elevation-in-material-design}, note = {[online] [accessed: 12. 4. 2020]}, } @misc{balsamiq, title = {Balsamiq, version 3.5.17}, - author = {Balsamiq Studios, LLC}, + author = {{Balsamiq Studios, LLC}}, url = {https://balsamiq.com}, note = {[online] [accessed: 1. 10. 2019]}, } @@ -250,98 +249,98 @@ @misc{hifi-prototype @misc{nielsen, title = {10 Usability Heuristics for User Interface Design}, - author = {Nielsen Norman Group}, + author = {{Nielsen Norman Group}}, url = {https://www.nngroup.com/articles/ten-usability-heuristics/}, note = {[online] [accessed: 12. 4. 2020]}, } @misc{google-places-api, title = {Places API Overview}, - author = {Google LLC}, + author = {{Google LLC}}, url = {https://developers.google.com/places/web-service/intro}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{google-places-api-key, title = {Get an API Key}, - author = {Google LLC}, + author = {{Google LLC}}, url = {https://developers.google.com/places/web-service/get-api-key}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{google-places-api-billing, title = {Places API Usage and Billing}, - author = {Google LLC}, + author = {{Google LLC}}, url = {https://developers.google.com/places/web-service/usage-and-billing}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{google-places-api-nearby-req, title = {Place Search}, - author = {Google LLC}, + author = {{Google LLC}}, url = {https://developers.google.com/places/web-service/search\#PlaceSearchRequests}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{xml-vs-json, title = {XML vs JSON}, - author = {TOM STRASSNER}, + author = {Tom Strassner}, url = {https://www.cs.tufts.edu/comp/150IDS/final_papers/tstras01.1/FinalReport/FinalReport.html}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{what-is-serverless, title = {What is serverless}, - author = {Anomaly Innovations, Serverless Stack}, + author = {{Anomaly Innovations, Serverless Stack}}, url = {https://serverless-stack.com/chapters/what-is-serverless.html}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{cloud-firestore, title = {Cloud Firestore | Firebase}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://firebase.google.com/docs/firestore}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{cloud-functions, title = {Cloud Functions for Firebase}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://firebase.google.com/docs/functions}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{cloud-auth, title = {Firebase Authentication}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://firebase.google.com/docs/auth}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{cloud-pricing, title = {Firebase Pricing}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://firebase.google.com/pricing}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{oauth, title = {OAuth 2.0}, - author = {Okta}, + author = {{Okta}}, url = {https://www.oauth.com}, note = {[online] [accessed: 14. 4. 2020]}, } @misc{kubernetes, title = {Production-Grade Container Orchestration}, - author = {Kubernetes}, - url = {https://kubernetes.io/}, + author = {{Kubernetes}}, + url = {https://kubernetes.io}, note = {[online] [accessed: 14. 4. 2020]}, } @Book{clean-architecture-book, author = {Martin, Robert}, - title = {Clean architecture : a craftsman's guide to software structure and design}, + title = {Clean Architecture: A Craftsman's Guide to Software Structure and Design}, publisher = {Prentice Hall}, year = {2018}, address = {London, England}, @@ -357,35 +356,35 @@ @misc{clean-architecture-article @misc{node-js, title = {Node.js}, - author = {OpenJS Foundation}, + author = {{OpenJS Foundation}}, url = {https://nodejs.org/en}, note = {[online] [accessed: 10. 5. 2020]}, } @misc{express-js, - title = {Express - Node.js web application framework}, - author = {Node.js Foundation}, + title = {Express -- Node.js web application framework}, + author = {{Node.js Foundation}}, url = {https://expressjs.com}, note = {[online] [accessed: 10. 5. 2020]}, } @misc{express-js-middleware, title = {Writing middleware for use in Express.js}, - author = {Node.js Foundation}, + author = {{Node.js Foundation}}, url = {https://expressjs.com/en/guide/writing-middleware.html}, note = {[online] [accessed: 10. 5. 2020]}, } @misc{jwt-intro, title = {JSON Web Token Introduction}, - author = {Auth0}, + author = {{Auth0}}, url = {https://jwt.io/introduction}, note = {[online] [accessed: 10. 5. 2020]}, } @misc{firebase-cli, title = {Firebase CLI}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://firebase.google.com/docs/cli}, note = {[online] [accessed: 11. 5. 2020]}, } @@ -404,8 +403,6 @@ @misc{package-bloctest note = {[online] [accessed: 17. 5. 2020]}, } - - @misc{package-freezed, title = {Freezed}, author = {Remi Rousselet}, @@ -415,7 +412,7 @@ @misc{package-freezed @misc{dart-equality, title = {Effective Dart: Design -- Equality}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://dart.dev/guides/language/effective-dart/design\#equality}, note = {[online] [accessed: 17. 5. 2020]}, } @@ -429,7 +426,7 @@ @misc{ibm-either @misc{package-mockito, title = {Mockito}, - author = {Dart Lang team}, + author = {{Dart Lang team}}, url = {https://pub.dev/packages/mockito}, note = {[online] [accessed: 17. 5. 2020]}, } @@ -443,14 +440,14 @@ @misc{package-getit @misc{bob-martin-design-patterns, title = {Design Principles and Design Patterns}, - author = {Martin, Robert}, + author = {Martin Robert}, url = {https://web.archive.org/web/20150906155800/http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf}, note = {[online] [accessed: 17. 5. 2020]}, } @misc{firebase-crashlytics, title = {Firebase Crashlytics}, - author = {Google, LLC}, + author = {{Google LLC}}, url = {https://firebase.google.com/docs/crashlytics}, note = {[online] [accessed: 17. 5. 2020]}, }