Roni Jumpponen Modern Architecture

Metropolia University of Applied Sciences Bachelor of Engineering

Mobile Solutions Bachelor’s Thesis 5 May 2021

Abstract

Author Roni Jumpponen Title Modern

Number of Pages 54 pages Date 5 May 2021

Degree Bachelor of Engineering

Degree Programme Information and Communications Technology

Professional Major Mobile Solutions

Instructors Mikael Lindblad, Site Project lead Peter Hjort, Senior Lecturer

The aim of the thesis was to research the necessity of software architecture in modern soft- ware development. Another aim was to find out how much architecture and documentation should be done in agile development, and what should be the points of focus. The idea was to use this gathered knowledge to deliver a solid software architecture and design for the partner corporation’s internal use application.

The application connected to the thesis is an experimental product utilizing modern sensor and data analysis technologies measuring fill rates based on various metrics. The current experiments include measuring the usage of restaurant, its line queues and the usage of parking lots around the corporation’s campus. The application is meant to be a living product with a long lifespan including collaboration with various third-party organizations such as universities.

This thesis builds on the key principles and concepts of traditional software architecture fo- cusing on more modern agile view and considerations on how they could still be beneficial for modern software development.

Incremental architecture and design were the themes of this study as the partner company wanted something that would stand the test of time and could be built piece by piece. Ease of expandability and modularity are key concepts for the thesis. The practical part focuses on the decision making which helped to reach the conclusions leading to the project team’s final version of the architecture and the connected cloud solution design. As the architecture is meant to be incremental, it will continue to change and evolve in future.

As a result of this study, a cloud solution on MS Azure was built. Also, this study compares different cloud service options for certain areas and cost analysis. Additionally, throughout the thesis there are mentions of different technologies for implementing various mechanisms used for enabling certain architectures and other key implementation details.

Keywords Software Architecture, Cloud, System, Design, Agile

Tekijä Roni Jumpponen Otsikko Moderni ohjelmistoarkkitehtuuri

Sivumäärä 54 sivua Aika 5.5.2021

Tutkinto Insinööri (AMK)

Tutkinto-ohjelma Tieto- ja viestintätekniikka

Ammatillinen pääaine Mobile Solutions

Ohjaajat Projektipäällikkö Mikael Lindblad Lehtori Peter Hjort

Insinöörityön tarkoituksena oli selvittää ohjelmistoarkkitehtuurin tarpeellisuus ja paikka mo- dernissa ohjelmistokehityksessä ja vastata kysymykseen, kuinka paljon arkkitehtuuria ja dokumentaatiota tarvitaan ketterässä ohjelmistokehityksessä. Tarkoituksena oli käyttää hankittu tietämys laadukkaan ohjelmistoarkkitehtuurin ja suunnitelman tuottamiseen työn tilaajayrityksen sisäiseen ohjelmistoprojektiin.

Insinöörityössä kehitetty sovellus on kokeellinen tuote, joka hyödyntää moderneja sensori- ja data-analyysiteknologioita, jotka mittaavat käyttöasteita käyttäen erilaisia mittaustapoja. Tämänhetkiset kokeet sisältävät yrityksen kampuksen ravintolan käyttöasteen, jonotusajat ja pysäköintipaikkojen käyttöasteen. Sovelluksen tarkoituksena on olla pitkän elinkaaren tuote, jota kehitetään yhteistyössä eri tahojen kanssa, kuten yliopistojen ja ammattikorkea- koulujen.

Insinöörityö rakentui perinteisen ohjelmistoarkkitehtuurin avainsääntöjen ja -konseptien va- raan tavoitellen modernimpaa ja ketterämpää näkökulmaa sekä tarjoaa ajatuksia siitä, kuinka ne voisivat vieläkin olla hyödyllisiä modernin ohjelmistokehityksen kannalta.

Inkrementaalinen arkkitehtuuri ja suunnittelu olivat vahvoja teemoja työssä, koska työn ti- lannut yritys halusi pitkän aikavälin ratkaisua, jonka ympärille voisi rakentaa asioita pikkuhil- jaa. Laajennuksen helppous ja modulaarisuus olivat avainkonsepteja insinöörityössä, ja työn käytännön osuus keskittyi projektiryhmän päätöksentekoon, joka johti arkkitehtuurin viimei- seen versioon ja siihen yhdistettävään pilvipalveluratkaisuun. Arkkitehtuuri tehtiin helposti muokattavaksi ja sen on tarkoitettu muuttuvan vielä tulevaisuudessa.

Työn tekninen näkökulma sisälsi pilvipalveluratkaisun rakentamisen MS Azuressa ja eri pal- veluiden välisiä vertailuja sekä hinta-analyysin. Tämän lisäksi insinöörityöraportti sisältää paljon viitteitä erilaisiin teknologioihin, joita käytetään erilaisten arkkitehtuurien mahdollista- miseen tai muihin oleellisiin toteutuksiin.

Avainsanat ohjelmistoarkkitehtuuri, pilvi, järjestelmä, suunnittelu, ketterä kehitys

Contents

List of Abbreviations

1 Introduction 1

2 Software Architecture 2

2.1 Structures 2 2.2 The purpose of software architecture 4

3 Quality attributes 5

3.1 System requirements 6 3.2 Scenarios 6 3.3 Tactics 7 3.4 Availability 7 3.5 Interoperability 8 3.6 Modifiability 10 3.7 Performance 11 3.8 Security 13 3.9 Testability 15 3.10 Usability 18 3.11 Other quality attributes and customized quality attributes 19

4 Software architecture patterns 19

4.1 Layered architecture and monoliths 20 4.2 Microkernel architecture 23 4.3 Microservices 25

5 Agile software architecture 29

5.1 Evolutionary software architecture 31

6 Documenting and visualizing the architecture 32

6.1 Architectural views and notations 33 6.2 C4 Architecture model 33

7 Project background 35

8 Initial project requirements 36

8.1 Functional requirements for the product 36 8.2 Quality attributes 37 8.3 Constraints 37

9 Project infrastructure and early design choices 38

9.1 Toolkit 38 9.2 Early design choices and observations 39

10 Project architecture and pattern choices 40

10.1 First pattern consideration, the microservices 40 10.2 Microkernel style frontend speculations and research 42 10.3 Meet the micro frontends 43

11 Creating a cloud solution design 45

12 Further development and complications 48

13 Azure environments and Cost estimations 49

14 Conclusion for the project, but not for the product 51

References 53

List of Abbreviations

C4 Model Context, Container, Component, Code

IPC Inter-process communication

1

1 Introduction

Software development is evolving at a rapid rate and new concepts and technologies are created on a daily basis. Software architecture follows suite and there are new patterns, methods and principles being created to match the evolution and creation of technolo- gies and methods such as Agile development, new frontend and backend frameworks, public cloud platforms and emergence of edge cloud systems.

Software architecture is at the heart of every software application’s development and should never be neglected. This thesis covers how software architecture should be uti- lized in modern agile way of working and what is “just enough” of planning and designing before development can begin and how the architecture and the design evolves during the project’s lifespan.

This thesis was done in collaboration with a global technology company and both the software architecture, and the system design being created and evaluated are connected to a real-world project. In the thesis we will go through the principles of software archi- tecture and analyze with examples how these design decisions impacted the develop- ment of the project team’s architecture and the actual software system.

Practical work and examples will include creating the documentation and visualization of the architecture along with cloud solution design and implementation on MS Azure.

Practical work will cover the key design decisions of translating the software architecture into a cloud solution architecture, process of creating the right design using the cloud native services and implementing the design in practice. The study also includes com- parisons between the different options for services and solutions to certain aspects of the system and includes detailed analysis on the reasoning why the development team chose one solution over the other options when choosing the implementation.

The purpose of the thesis is to transmit the conceptual ideas behind software architec- ture, the analytical processes and how modern systems are designed using these pro- cesses and built both on the premises and on the public cloud.

2

This study aims to streamline and compress the information into easily understandable and cohesive package with more practical outlook using real-world examples and rele- vant information towards software engineers looking to start creating their own architec- ture and building their own software systems.

ISO/IEC/IEEE International Standard - Systems and —Vocabulary [1] will be used as a reference for standard software engineering and architecture termi- nology.

2 Software Architecture

Software architecture in essence is a set of structures comprised of software elements, their relations to each other and properties of elements and relations. These structures and their combinations are often represented as “views”. Views or viewpoints offer dif- ferent levels of abstraction for representation and visualization. This is important, be- cause stakeholders have different interests and needs that need to be represented and visualized when describing the architecture of a system to them. Stakeholders of the system can be anyone who would be interested in the architecture in some form of ab- straction, like someone from management department or developer or the actual end user.

2.1 Structures

Structures are the key components in the representation of every architecture. Structures represent the architecturally important engineering leverage points of the system and a are a way of building and presenting the architecture to its stakeholders. Unfortunately, there is no approved common language in the industry when defining what they really are.

In the book Software Architecture in practice by Len Bass, Paul Clements and Rick Kaz- man [2] the authors refer to three key types of structures: Module, component-and-con- nector(C&C) and allocation structures. Modules represent code or data units that need to be developed or bought for the system like Clients, API’s, Databases and so on. Mod- ules can also be used to describe functionalities within those applications. Component- and-connector structures describe how the system functions as a set of components with

3 connector interactions during runtime. This could include the interfaces and protocols used to communicate. Allocation structures describe system’s relationship with non-soft- ware structures within its environment. Allocation structures include system properties like hardware used, networks and development teams working on specific parts of the system.

Another way to describe structures used in this thesis is based on Simon Brown’s C4 architecture model [3]. C4 model stands for: Context, Containers, Components and Code with each offering a different architectural view and level of abstraction within same sys- tem. Context level defines the context architecture is used in and systems relations to its stakeholders and other related systems. In this model the containers, components and code are the static structures of the system. Containers in the container layer represent the individual “applications” and their purpose within the system such as GUI clients and servers in the traditional meaning. Component level of abstraction consists of compo- nents representing the functionalities or features within a container. For example: an individual component might handle any incoming http requests and send it to one of the other components for analysis, which is then sent back to the first component for re- sponse or some other component else for additional processing. Code level of abstrac- tion is composed of the classes or functions the individual components use to reach their required functionalities. In this thesis the C4 model is used for visualization of the archi- tecture and will be presented again later in the thesis in more detail, and it will also be used as the primary way of describing software structures. For more information on the C4 model, see Image 1 below.

As a further clarification, in this thesis the word “system” describes the bigger picture and includes every software container and component. Another term used for this would be service landscape or system landscape. Service is another term used in this thesis for describing individual software units or applications. Services are mostly the same as containers or modules, but a bit narrower term used in certain styles of architecture for describing a combination of software and data units usually implementing a complete stand-alone feature.

4

Image 1. Layers of C4 Software Architecture Model [2]

2.2 The purpose of software architecture

Software architecture fulfils many purposes in software development. It can be used to analyze the system and look for flaws and possible improvements even before a single line of code has been written. Documented software architecture can be used as a tool for communicating with different stakeholders like line managers and developers and making sure everyone is collaborating efficiently. It can be used to reason about possible costs for projects, training new employees and when done well it provides the teams with guidelines for future development and can be evolved alongside the development to match the life cycle of the project.

Architecture can be used as a reusable model to enable reproduction of a system or a system fulfilling a similar purpose, especially when well documented. This is represented by architectural patterns and to some extent brought even further with the modern cloud solutions and platforms that enable you to reproduce your whole cloud solution by ex- porting it as code and importing it somewhere else (Infrastructure as code) [4]

5

Even in agile software development the architecture can be used to direct the develop- ment teams towards a right direction by setting guidelines, technology choices, patterns to follow and documenting the essential parts of the architecture. Thesis will cover this topic in a later chapter with more detail and follow the progress throughout the practical execution of the project done in an agile manner.

3 Quality attributes

Quality attributes are measurable or testable properties of the system that indicate how well the system fulfills the needs of the stakeholders. Quality attributes are often in con- flict with each-other and the goal is finding the right balance between them fitting the system requirements. Quality attributes are important architecture tool for expressing the qualities systems should have, how they can be reached and for reasoning about the correct design decisions. While analyzing and designing can feel redundant and waste of time in agile software development these attributes represent a line of thinking the architects and developers should use when creating and testing a software and should always be under consideration in one form or another when making key design deci- sions.

Many other quality attributes exist than there are listed in this chapter and many archi- tects have their own terminology and classifications as mentioned in the previous chap- ter, but the ones listed here form a good basis for a proper cohesive analysis. There are also multiple different standards set by organizations for Quality attributes like the ISO / IEC 25010[5] forming a good starting point for new architects needing a checklist. Image 2 illustrates the eight main quality attributes of ISO / IEC 25010[5] and their sub attrib- utes.

Image 2. ISO / IEC 25010 Standard [5]

6

3.1 System requirements

System requirements consist of functional requirements, quality attribute requirements and constraints. Requirements come in many forms and they can be text documents or user stories or even reusing old systems as a part of the new system. Functional require- ments state what the system must do, how it should behave in given circumstances or react to certain events. Quality attribute requirements measure how the functional re- quirements should perform. This can be scaled to fit the context it is used in. Single function of the system can have qualifications and so can a whole module or even the system. Constraints on the other hand are design decisions that have already been made beforehand which the architect and the development team have no say in. These are usually set by the management or the client company ordering the development of the application. Constraints can be anything from using a certain technology or programming language or reusing existing parts of a previously built system to using certain architec- ture style or pattern when building the system, like microservices.

3.2 Scenarios

Scenarios are something the authors of Software Architecture in Practice (SEI Series in Software Engineering)[2] use for analyzing and expressing the quality attributes. These scenarios work similarly to user stories but are used for measuring systems quality in- stead. Scenarios are a widely used by software architects in the industry.

There is a source of stimulus causing an event. It could be a user or it could be a part of the system or a separate system connected to the main system.

The source instigates a stimulus which is a different type of an event depending on which quality attribute is being analyzed. When analyzing performance, the event could simply be a user pressing a button for navigating to the next page inside an application. In a nutshell stimulus is something that requires some sort of response.

Stimulus can occur on many types of environments. Environments are used to express which mode the system is running on. Does the event happen during testing? Or in live production? These different modes are called environments.

7

Artifact is used to describe the affected part of the system. It could mean the system as a whole or any specific part of it like a container or maybe a component inside the con- tainer.

Response is used for describing what should happen when certain stimulus happens. Response is how the system reacts to an event. This is used as a guideline for develop- ers when developing the system. If we take the first example from stimulus then the response would be for the UI to change to the next page or screen after user presses the button to navigate there.

Response measure is a metric for which the architect and developers determine if the response is good enough and it fulfils the requirements set for it. Simplest form of meas- ure would be time, when measuring performance how long does it take for an http re- quest to produce a response?

3.3 Tactics

Tactics are methods which can be utilized to modify system’s response to the events or stimuli more towards a preferred direction and quality attributes. These are the design decisions that mold the system to fit the requirements. In addition, tactics are used in conjunction with architecture patterns to find the right mesh of elements and used to enhance the architecture patterns towards specific quality attributes.

3.4 Availability

Availability is closely related to system up-time, it refers to the fact that system should be available and able to respond and function normally even if there is a fault occurring. The system should be able to recognize and respond to these faults in some meaningful way and these responses can be different depending on the criticality of the functionality. Availability has become extremely important metric for software service providers and most likely has the biggest impact on an organization’s economy and finances out of all quality attributes, because system downtime is often in direct relationship with loss of money. Availability has close ties with other quality attributes like security, performance and safety. Faults and unavailability caused by security risks are the most evident, mak- ing security the most self-explanatory of the three.

8

Scenario for availability could include a fault occurring on one server and making it mal- functional. This could be recovered from by having multiple instances of identical servers and directing traffic to those other servers while the malfunctioning one recovers. Server would be the artifact in this case and environment would be production runtime. Good measures here would be to take in account how long it takes to detect the malfunctioning instance and how fast the redirection to the healthy instances is after the fault has oc- curred.

This error or fault should be logged and monitored for future fixes. Updates could be implemented with always having old instances of the server running until the updated instances are ready to receive requests.

Retrying is an essential and common tactic when no response has been received. This is especially important in critical parts of system where loss of data is unacceptable and always needs to be up to date. These requests could also be placed in a queue when there are heavy server loads to ensure they are received in proper order when that part of the system becomes available again.

For data handling it is incremental to always have replicas or backups available stored on a different server. When increasing availability even further the data and perhaps the whole system could have instances spread out to servers located on different regions. Modern cloud services heavily enable this sort of behavior and allow the easy replication of data and computing around the globe ensuring your system never suffers from outage. This is where the connection with performance becomes evident with users possibly be- ing able to access the instance of the system located on their region with lower latency.

Many other tactics exist for availability with each of them having their own purpose with multiple use-cases.

3.5 Interoperability

Interoperability quality attribute translates to the system’s ability to communicate with other systems and the ability for the containers and components inside those systems communicate with each other. This includes the ability to not only correctly exchange data but also to interpret it. With separation of concerns, decoupling and microservices

9 in general trending upwards when companies are starting new projects and building new systems, interoperability has become an essential point of every service-oriented archi- tecture. Interoperability measures the ability to detect other services and correctly and reliably deliver data back and forth.

Classic scenario for interoperability could have a user(source) sending their gps-coordi- nates(stimulus) to a service-catalog-server (artifact) during runtime environment. As re- sponse user would get some relevant information combined with their current location like locations of nearby restaurants and other services shown on a map overlay. Meas- uring this could simply be done by checking if the location data were sent and interpreted correctly and correct services were sent in response.

Interfaces are a vital component of the systems interoperability. REST is the current standard for most applications providing a great and simple interface for handling CRUD operations. REST is the most common and traditional way of handling the client-side to server-side connectivity but can also be utilized for backend service to service connec- tions. Modern web and mobile applications are becoming more real-time and as such often utilize messaging protocols such as web sockets to get real-time information and updates. Similar methods are also popular for handling the server-side traffic and as such most modern systems use event-based messaging for internal communication.

First tactic towards interoperability is the discovery of services. Locating services can be done in many ways by using names, addresses or locations.

Second tactic is managing the interfaces. This means orchestrating and tailoring the in- terfaces. Event or service bus is a good example of this as it distributes the messages based on the chosen method. Most common ways of doing this would be queue based where messages are put on queue and then distributed in correct order to the individual services and the second one is based on topics where services subscribe to topics and receive messages that are sent to those topics. Topics enable multiple services to re- ceive the same message and is great for reducing overhead and improving performance at the same time.

In large projects with multiple teams collaborating and building their own services there often remains a need for some interoperability between those services. API schemas and documentation can be a helpful tool for describing the services to other teams, but

10 this is often not enough since even if the technical interfaces may be compatible there is also the need that the data being handled is also compatible. Communication is essential in ensuring that one service creating the request receives the data it is requesting and not something else that may resemble that data. Orchestration services like Kubernetes are becoming an essential tool for interoperability with many modern applications utiliz- ing docker and running services inside containers.[5]

3.6 Modifiability

Modifiability is about change. Change is something that happens during every project’s, and product’s lifespan and modifiability is about making that change less painful and costly. Foreseeing the future is one of the jobs of a and making the system modifiable involves a fair amount of analysis. Knowing in advance what can change, what is the likelihood of the change and when should the change be made, can help with planning ahead towards the future which is essential when estimating possible costs occurring during the project’s lifecycle. Different mechanisms can be introduced for making those future modifications easier but justifying the implementation of those mechanisms and design decisions requires analysis. This analysis should be mostly fo- cused on estimating if the cost of creating those mechanisms is higher than the future benefit of having them.

Modifiability refers to change in a very loose way, it can refer to developer making a change to the system during development by deploying updated code, system adminis- trator changing settings during runtime and it can even refer to end user making a change like changing their app’s background picture.

Example scenario for modifiability could include a developer(source) wanting to make a change(stimulus) to an UI component (Artifact). Proper response would be change being made and unit tested. Time is money in software development world and the cost would be measured by how long it would take for that change to be made and possibly for the software to be deployed if the development team is utilizing the continuous integration and deployment model.

Modifiability has a strong connection with modularity in a way that most of the modifia- bility tactics are based on code units working as individual entities. Many modern

11 architecture patterns like the microservices pattern are based on the concept that a soft- ware unit or service should have an individual set of responsibilities and should not be tied to other services in a binding way. If the service can act as an autonomous unit it is much easier to change and update more frequently and easily without breaking any of the other services. This process is called decoupling or reducing the coupling. Second tactic would be connected to reasoning about how to build those services. Increasing the cohesion means that if the service fills too many responsibilities that do not serve the same purpose it should be split into smaller units with their own purposes.

To further enable the same code units and services to be more flexible, defer binding tactic could be utilized. Using parameters instead of hardcoded variables enables the same software to be ran in many different environments and modes. In practice this would mean having a different set of parameters for testing, development, and produc- tion which the same program could be ran on. These parameters would include different database and storage connections, runtime modes, potentially would enable different functions to be ran as well. These parameters could be used for declaring connections to other services as well to make the changes to API endpoints and other services easier in the future and further decreasing the coupling between the two services. Simplest way of achieving much of the previously mentioned properties would be using environmental variables in the software which are set during compile / build time, but there are many other ways and tactics which could be used to make the system more dynamic like dis- covery of the services during runtime which was mentioned previously with interopera- bility quality attribute.

3.7 Performance

Performance is measured in time. Time it takes for the system to respond to a request or process events, or the number of requests the system can handle / time unit. Perfor- mance might not be the primary quality attribute defining a system, but it is always in the discussion in one form or another because all systems need some sort of performance to function properly, meaning all systems have performance requirements. Performance has been the defining element during much of the history of software architecture since it is always a requirement and hardware has not always been as advanced as it is today. In modern software architecture other quality attributes have risen to take the spotlight due to powerful hardware and scaling technologies becoming more easily accessible

12 and better optimized. Performance is closely linked to scalability since increasing sys- tems capacity has direct relation with performance improvement.

Example scenario for performance could have a user(source) buying something from an ecommerce site(stimulus) and scenario would revolve around processing that transac- tion (Response) in normal production environment and artifact being the part or parts of system processing that request. Response measure would in this case be the time it takes to process that transaction.

Performance measures time it takes to process events and performance tactics revolve around reducing that process time. Often the biggest bottlenecks inside systems happen when a large quantity of services are reliant on particular services to process their re- quests. This becomes especially evident when there are long chains of communications called sagas with services having dependencies on other computations and responses before these services can continue their own processes.

Performance tactics include a set of tools for controlling demand, implementing sched- uling policies, and managing resources.

For controlling the demand, codecs with sampling rates for different data formats can help in lowering the frequency data is captured to create a more consistent stream of data and minimal packet loss. Limited event responses can help when your queues of get too big and become a bottleneck when processing data, the events could be priori- tized and the ones measured not to be as important could be dropped and logged or just put aside for later processing when the system is under less stress.

Scheduling policies help in prioritizing the events. Prioritization can have many different forms and methods. Events could be equal where first event is the first out or some events might have more priority based on their deadline or based on semantic im- portance like topics or targeted services. Scheduling politics are also used for dividing the server loads between replicas in preferred manner and possibly prioritizing requests for certain endpoints and services deemed more critical than others.

Managing resources is an important aspect of performance. Vertical and horizontal scal- ing are the primary means of adding performance without touching the software. Vertical scaling or scaling up is a brute force tactic of getting better, more powerful hardware to

13 run the servers on. Horizontal scaling or scaling out means adding more machines or instances of services to the pool of resources. Both scaling methods improve perfor- mance, but horizontal scaling can be an important tool for availability as well when main- taining multiple replicas of servers processing the incoming requests. This can be further improved by having multiple copies of the data by caching the common responses in server’s memory to reduce the latency and database loads. Processing requests in par- allel with multithreading or asynchronously is effective an effective tool for improving per- formance when implementing input / output heavy services.

3.8 Security

Security measures systems ability to protect data from unauthorized access while being able to be accessed normally by other authorized systems and users. Having a good data security has become crucial over the last few decades after the rise of e-commerce and digital service platforms. These platforms usually hold and process a great quantity of confidential user information and security is of utmost importance for avoiding data breaches, which could cause great harm for both to the organization offering the services reputation and the users whose information would get leaked and in worst case abused.

Attacks are attempts to access or modify a system’s data unauthorized or deny services from legitimate authorized users. The latter are very common and called distributed de- nial of service attacks (DDoS).

Confidentiality, integrity, and availability (CIA Triad) is a simple and common model used to characterize and describe the most important parts of cybersecurity. Confidentiality stands for data and services being protected from authorized access. Integrity stands for data not being subject to unauthorized manipulation and availability for system to be available for legitimate authorized users even in the case of services being subjected to attacks like DDoS.

Authentication and authorization are the most important parts of any system with confi- dential user information. Authentication verifies the identity of the user to the system and authorization grants the verified user the rights of performing actions within the users given range of privileges.

14

Nonrepudiation is one of the more overlooked security characteristics and especially in the case of e-commerce platforms it is one of the most essential. Nonrepudiation means that the party performing an action cannot possibly deny performing that action later.

Reasoning about security scenarios starts from different types of attacks being per- formed by a source which could be a human or another system. It could be someone from inside the organization trying to edit data without privileges. An angry employee after getting a pay cut trying to delete the whole product database. The correct response to this would be this person either not having privileges and access to perform the action or system maintaining an audit trail or log so this event could be tracked down. The measure would be how long it takes for the illegitimate event to be identified and data restored.

Security tactics are divided into four categories. Detecting attacks, resisting attacks, re- acting to attacks, and recovering from attacks.

Detecting attacks can be done by implementing a network intrusion detection system (NIDS). This system monitors incoming requests and network traffic to a known set of signatures and patterns of malicious behavior. These systems are usually bought from third party organizations since they are complex systems on their own and require a fair amount of data to be functional. Artificial intelligence is becoming an important part of modern versions of these types of systems by enabling advanced threat prediction and recognition capabilities.

Tactics for resisting attacks revolve around identifying, authenticating and authorizing actors. Actors can be users, other systems or devices trying to access the system which are identified through verified access codes, IP addresses, certificates, or by other means. Authentication can be implemented in various ways, but always refers to ensur- ing the actor is who it claims to be. Authorization is about managing access rights for authenticated actors. Access rights can refer to rights to access and modify data or ser- vices and is usually implemented with actor class groups where each class has a set of privileges. Simple example of this would be a basic user group where users belonging to that group only have access and modification rights to their own data, but a user be- longing to administrator group would have full access and possibly even modification rights to some parts of the user data. Data encryption is essential for any modern appli- cation with most web-based systems utilizing transport layer security (TLS).

15

When an attack occurs and is detected, there should always be a reaction from the sys- tem and a plan for recovery. Most common reactions would be revoking access from the actor performing the attack and notifying the relevant parties about the attack. Recovery tactics are mostly the same as availability tactics that permit the restoration, but in addi- tion maintaining an audit log is especially important. Audit logs are records which contain all actions performed by users and the system and their outcomes. Audit trails can be used for tracing actions to identities of attackers. Audit logs are important for enabling the nonrepudiation which was mentioned earlier.

3.9 Testability

Testability is an important quality of every modern software system throughout its entire lifecycle. Testability focuses on detecting the flaws within the system and making sure it recovers from them accordingly.

Creating a system with good testability takes time and resources, but essentially enables longevity and continued development with both playing a big role in agile software de- velopment.

Software testability refers to the ease with which software can be made to demon- strate its faults through (typically execution-based) testing. [2. p. 339]

Key tactics to ensure your systems testability are divided into two categories: Control and observe system state and limit complexity.

When there is a controllable state that can observed, conclusions can be made based on the state and since the state can be controlled it can be used test every fringe case that the system could possibly produce. Control and observe system state in its simplest form can mean providing a software component like a class a set of inputs, letting it process those inputs and then observing the outputs. This action would be called a unit test in software development.

Every tactic includes the usage of different set of runtime environments. In practical terms this would mean setting up different runtime environment modes for the applica- tions like production, testing, development, staging each utilizing a different set of re- sources.

16

Specialized interfaces tactic is about having specialized interfaces for testing the appli- cation. Running the application in testing environment mode the tester would have ac- cess to different setter and getter functions which would not be available in other envi- ronments. In addition to this the development environment could possibly include addi- tional debug features which are not wanted in production environment of the application and the test environment could include methods used just for testing, advanced logging of errors and reports.

Record and playback tactic captures an input causing a fault for further use in the testing process. This is essential for recreating faults that could be difficult to recreate otherwise.

Abstracting data sources as in abstracting the interfaces the software is working with. Different runtime environment modes each having their own sets of interfaces stored in environmental variables. Running the application in development environment would use local or development realm databases and running the same application in production environment would use the live application database with real data.

Many different software frameworks and platforms offer inbuilt runtime environments and in most of them it is possible to utilize either inbuilt or third-party libraries for environment variables.

Sandboxes are isolated instances or replicas of the system used for testing purposes. Sandbox acts as a playground for testing where the tester does not have to worry about consequences of their actions and often utilize virtualized resources. Virtualized re- sources enable testing of the fringe cases using customized datasets in combination of a certain type of system state, for example the tester can simulate what happens when event is supposed to trigger at midnight by moving the system clock to midnight and observing if the event really triggers and if it has some other unwanted consequences. Virtualized resources include tinkering with the operating systems or the hardware that would be normally out of systems boundary of control.

Best example of executable assertions would be unit test cases where the tester creates the assertions manually based on the wanted behavior of the software. The assertions are designed to check that the output values are within the set of boundaries when given a certain input and if the output does not then the test fails. This tactic is used in every modern application and utilized in many different forms. One additional usage example

17 would be for monitoring the flow of data in a certain part of the system during runtime and creating alerts when data outputs do not match the given constraints.

Limiting complexity enables the ease of testing for all parts of the application. A good way to ensure the structure of the code remains clean and quality good is to utilize test driven development when producing an application. Often when tests are written first the complexity of the code stays low. Modifiability tactics like loose coupling and separation of concerns can be used for limiting complexity. Components with focused functionalities and purpose are easier to test.

Last important piece of measuring testability is test data and automation. Test data is a common cause of problems and should be carefully planned and accounted for at the start of the project’s development. In modern software development test automation is more of a necessity and a requirement than an option and should always be implemented in some form.

Creating large and useful test data sets is essential, but one of the hardest things to do. There are two popular approaches to test data. One approach is creating a software to generate the data. This is the ideal solution since you can ensure that the data is diverse enough that it covers all the possible fringe cases and scenarios. There is a significant investment involved though in terms of time and investment.

Second approach is taking a set of data from the production environment and processing it to give it required level of anonymity. Anonymity processing could include removing or altering any sensitive or in general personal information. The second approach is gener- ally easier and less time consuming but could cause other issues related to the data diversity and coverage. Handling of personal information also requires extra care to be taken.

Test automation usually involves utilization of a framework or frameworks which run on set time periods or whenever a change is made to the codebase. The latter is called the continuous integration model and is in wide use globally. Most modern systems utilize CI model in their test automation and there are a variety of tools available.

18

3.10 Usability

Usability focuses on measuring the ease of user interaction with the system. How easy is it to learn how to use the system, is it easy for the user to find the functionalities and information they are looking for? How efficiently can the user interact with the system, can something be improved to make the system better and more efficient to use? How can we adapt the system to suit the needs of the user? What kind of relevant feedback should it provide for the user? One notable thing to account for is that there might be different types of users with different sets of usage requirements like system administra- tors and other types of users with different sets of privileges when using the system. They might have completely different UI’s as well.

Usability is an important attribute for any application and while many other quality attrib- utes collide with each other, usability often works in perfect cohesion with modifiability. Separation of concerns is important when designing an easily usable system since sep- arating the UI from actual business logic helps with constant prototyping, which is im- portant for Usability testing. MVC pattern is good traditional example of this type of de- sign where business logic is separated from the UI.

Existing UX Design tools like Adobe XD and Sigma [6] help test the UI before any code has been written by visualizing the designs in an interactive form. At the start of the software development process, it is often a good idea to have multiple different prototype UI’s produced which can be switched around and enhanced based on the received user feedback.

Good way for approaching usability is creating scenarios or user stories where the user performs an action and system reacts to that action. What kind of feedback does user get for performing that action? What if user did not mean to perform the action, can it be cancelled or reverted? Can the system help user perform the action better in some way like autocompleting the lines on a form?

How does architectural usability differ from the actual UX design? In many ways it does not, it is just the first stop on the same road. Architectural usability is more focused on the basics and high-level concepts and UX design is about going into more details with actual end users when the key system functionalities and requirements have been real- ized. Usability in software architecture focuses more on deep level reasoning on how the

19 system should react to user actions rather than on tweaking the UI to perfection. In agile software development UX design and architectural usability are very tightly connected as one directly affects the other.

3.11 Other quality attributes and customized quality attributes

Many more quality attributes exist than were mentioned in this chapter. There are ways to analyze and reason about attributes like scalability, monitorability, portability, deploy- ability and others as can be seen from the (image 2) showcasing the ISO / IEC 25010[5] standard.

As many quality attributes as the standards like ISO / IEC 25010[5] include sometimes projects have very specific requirements which cannot be measured by any existing or commonly known attributes. For this reason, it is sometimes preferable to create com- pletely new quality attributes. A good example of this would be a company launching a new project while wanting to lure in new talented developers. A key requirement is set for the project which requires the system to utilize new, highly rated, and trendy technol- ogies developers would want to work with. As a measure of trendiness architects need to create a new quality attribute called “trendy” and find ways to measure this trendiness, including the creation of scenarios and tactics for it.

4 Software architecture patterns

Software architectural pattern is a manifestation of good design decisions and design structures that have been discovered and molded into a reusable entity. Architectural patterns are not invented, they are discovered through practice. Throughout the history of software development these patterns have been found and most of them have evolved and divided into directions where they benefit certain types of applications. There are no silver bullets in software architecture which is why each one of these patterns have their own weaknesses and strengths. Generalist patterns exist, but they are not very good for any specific purpose but, they can form a solid backbone for a new project early on before making the decision on which direction and pattern is the best long-term solution for that specific project. Software architecture patterns have such a strong impact on modern software architecture that many architects use specific patterns as high-level definitions of the whole architecture of their system. The reason behind this is that

20 architectural patterns are essentially meant to represent the shape of the entire system and often define the structures used for describing the specific architecture to an extent.

Tactics or strategies as many architects call them have a strong relation with architectural patterns. Usually even if the architect finds the perfect pattern for a specific type of soft- ware system, it will need to be tailored towards certain quality attributes deemed im- portant to the stakeholders. Software architecture and software development in general is all about solving problems and these problems are rarely identical. Neither are the software systems solving these problems and as such, even though architectural pat- terns may form a good backbone to start building upon, they never represent the abso- lute truth. In fact, even when solving problems that are very similar, the solutions can take very different shapes.

One important thing to note is the fact that architectural patterns are often used on con- junction with one another. Patterns are used for describing different functionalities and structures within the system and while most patterns focus on the software and code units or modules and containers, some patterns describe the communication mecha- nisms between those modules and so on. Different parts of the system might also have different priorities in terms of quality attributes so naturally they should utilize different patterns. It is a key challenge to keep architecture of a system on a simple enough level so it can be described in many levels of abstraction and shared with different stakehold- ers while still getting the full benefits of different architectural styles and patterns.

There are many more existing architectural patterns than are mentioned in this chapter, but the ones selected here are perhaps the most relevant for modern software develop- ment and additionally provide important background for the practical work connected to this thesis. Mark Richards’s and O’Reilly’s Software architecture patterns [8] provides a great high level starting point for descriptions and example use cases of various archi- tectural patterns.

4.1 Layered architecture and monoliths

The very first architectural pattern most developers turn to when starting a new project is called layered architecture pattern, also known as n-tier architecture pattern. This

21 pattern has been in wide use for a long time and is probably the best known and most of the time the very first one taught to new developers.

The layered architecture organizes its components or structures in horizontal layers, each layer having a specific purpose within the application. The most common and tra- ditional approach has three layers and consists of presentational layer (GUI), business layer (business logic) and the data layer (Databases). This is the building block for most applications at the beginning of their lifespan and has traditionally been the most com- mon pattern the organizations have stuck with even when the applications grow, and the codebases become massive. Large applications built with layered architectures often have over five tiers, open and closed layers and sometimes vertical layers called side- cars as well. Traditionally the idea behind layers was to have them closed and only al- lowing them to communicate with the one layer directly below them, but this can be prob- lematic in some cases, which is why the concept of open layers was invented. Open layers are layers that can be bypassed to access the layer below it directly. Sidecars on the other hand are rare since it is not usual that there is a need to share something between all layers, but one such case would be domain specific library, used if it is deemed essential to have all layers use the same exact object model for specific objects to ensure data consistency. The problem with layered architectural ap- proach is that the performance suffers from adding more layers, because of the overhead in execution caused by each upper layer having to connect to the lower layers for every operation. For large applications splitting the codebase into layers and multiple deploy- able units becomes essential for maintenance and further development reasons mean- ing that layers need to use IPC mechanisms to communicate. Image 3 below illustrates the data flow within the layered-architecture and showcases the responsibilities of each layer.

22

Image 3. Layered architecture with four layers and customer data flow example [8]

Scaling brings more problems and although the layered approach with divided deploy- ments between layers deals with it slightly better than applications with massive singular codebases, at some point these applications become something called “Monoliths”. Monoliths are massive applications with large singular components and often start caus- ing complications for the applications stakeholders. While many scalability tactics exist to help with the size of the application, often bottlenecks happen with this type of archi- tectural pattern and while the application can be scaled layer by layer it becomes very expensive to do so with the largest problem being the final database layer which is es- pecially costly and hard to scale.

At some point monoliths become notoriously hard to develop with many software com- ponents being coupled and hard if not impossible to change without consuming massive

23 amounts of time. This architectural anti pattern is called the “big ball of mud”, which de- scribes the different software components having interdependencies with each other and becoming impossible to maintain. This big ball of mud scenario can be largely avoided by building something called “Modular monoliths” which are monolithic applications, but with decoupled software components and modules inside. Although it does not help with the problems related to scaling, it helps a great deal with keeping the application main- tainable and developable.

Layered architectural pattern is a good generalist pattern and often the best way to start building a new application. It is however important to plan further ahead, build modular software components and start branching out into a different, more suited architectural pattern and style for the specific application, when more scaling is required, and addi- tional features need to be implemented. The layered pattern is overall very simple to understand and develop initially, but generally lacks the agility needed in modern soft- ware development.

4.2 Microkernel architecture

The microkernel pattern is an interesting and heavily influential pattern in software archi- tectures history. It focuses on the concept of having a core application which holds the basic functionalities and a plugin-based approach for adding new features and improve- ments. Most product-based applications utilize this pattern in a way where the application can be released as one initial core package, and afterwards new features can be devel- oped and added in to elevate the product. Adding of these features is usually done during development, but this approach can also be taken one step further with runtime down- loadable plugins, allowing great modularity and customizability for the applications users. Additionally, these plugins could be developed by third party organizations allowing for truly extensive applications with massive plugin libraries to be developed.

The microkernel architecture consists of two types of structures, a core system, and the plugins. The origin of the patterns name comes from operating systems as they usually utilize this sort of architecture, other notable examples would be IDE’s which are usually just fancy text editors without the additional customization components. The core appli- cation usually implements the general business logic needed for the application to func- tion, and the logic for adding and removing the plugins. In addition, the core application

24 needs to keep track of available plugins through some sort of registry or library. The registry should include all essential information regarding the plugin’s identity, function- ality, and remote access details. Example visualization of the architecture in Image 4 below.

Image 4. Microkernel architecture example [8]

The plugin modules themselves are independent stand-alone components which are used to enhance and extend the functionalities of the core application in some way. Plugins are generally independent from other plugins as it is not recommended to create unneeded dependencies, but exceptions can sometimes be made, and some plugins even are even designed to extend other plugins functionalities towards a wanted direc- tion. Plugins can vary in size greatly, from simple chat app emoji extensions to massive standalone applications like video games and other heavier applications running on top of the operating systems.

Communication between the core application and the plugins is called inter-process communication which is used in other types of architecture as well. Various ways of connecting plugin modules to the core application exist and the architectural pattern itself does not specify the correct way of implementation. The implementation of connectivity depends largely on the type of application being built, how it is deployed and applications size. Common ways of handling this include OSGI (Open service gateway initiative) for JVM based applications, inter-process messaging or through object instantiation when using the same codebase. Contracts are an important part of inter-process communica- tion as they enable the communication between the core application and the modules,

25 they usually consist of the and format used for the communication. For ap- plications with third party plugins, it can be a good idea to implement adapters to stand- ardize the contracts into an understandable form to prevent the need of creating custom- ized code for each connected plugin.

The usage of microkernel varies from product-based applications to large business ap- plications as it offers an easily extendable platform for future development. Microkernel pattern is often best used as a part of another type of architecture as often it is only needed for specific parts of the system to be built in this way like the graphical user interfaces.

Drawbacks of the microkernel architecture are the relatively high initial complexity and while the plugins may be easy to develop, it may become hard to make changes to the core application without breaking some of the plugin modules in the process. In addition to this, depending on the implementation of the plugin modules, the application may be- come hard to scale as these applications often become similar, to previously mentioned modular monoliths. This can largely be avoided by creating dynamic modules which can be separately deployed and used as downloadable plugins each utilizing their own server-side implementations. Contracts and other implementation details bring a fair amount of extra complexity and need to be managed and planned for carefully for the application to work in a desired manner.

The microkernel pattern provides great flexibility and continuity when well implemented and offers a great backbone for expandable applications. It is best implemented by em- bedding it into another pattern like the microservices from the next chapter. Important things to note are that the microkernel architecture requires a fair amount of planning in advance with the contract management and other required mechanisms. Depending on the implementation method, it may also require some initial development time investment to get up and running properly due to its complexity. Additionally, changes to the core application may require massive collaboration efforts and precise communication.

4.3 Microservices

Modern applications are rarely just traditional layered applications with layers only com- municating with the layer below them. Most modern systems consist of tens, sometimes

26 hundreds if not thousands of individual stand-alone and cross functioning services serv- ing a singular important purpose within the system. The backend services communicate with the frontend clients and with each other remotely using http requests and often through asynchronous messaging. A system utilizing this type of architecture is using a service-oriented architecture in its modern form: the microservices architecture.

For the last several years microservices has been becoming a strong alternative to more traditional patterns and a great quantity of success stories have been written using this pattern, perhaps the best well known one being Netflix. This has caused an impact on the industry and most of the proficient architects and organizations are now trying to utilize this pattern in their own applications, and some have done successfully. Unfortu- nately, as previously mentioned there are no silver bullets in software architecture and while the microservices architecture offers an excellent toolkit for large, modular, scaling and easily developable applications with daily deployments, as an architecture it is still in many ways unrefined and complicated. Many organizations have encountered prob- lems trying to make use of this pattern, often when it has been used wrongly or when it should not have been used at all for that specific purpose or application.

Microservices architectural pattern is all about distributed services, but there are many general misconceptions regarding the size of these services. Many architects have taken a similar approach to Netflix where the microservices are very miniscule in size and the services use a fair amount of inter-process communication which was mentioned earlier. This misconception has led to catastrophic results in large number of software projects where organizations have been trying to directly copy similar methods as the Netflix ap- proach is organized for extreme growth and scaling, but is extremely hard to navigate, costly, and while Netflix is an extremely large application it has a fairly simple domain structure compared to more data driven applications, meaning that similar approach would be extremely hard for applications with more complex structures requiring high amount of IPC and data consistency checks. For many organizations copying Netflix’s approach meant that the service domains would be badly defined and often overlapping, services would be independently deployed, but coupled because of their dependencies of other services while having a worse performance because of remote IPC needed, and the sheer amount of individual services would mean bad cost optimization.

After the meteoric rise of the microservices architecture the software architects have been trying to determine the best possible descriptions for meaning and size of a

27 microservice. Fairly common agreements are that these services should be decoupled, stand-alone and they should implement a clearly distinct feature or functionality for the application. In addition, these services should be independently testable and deployable and require minimum possible amount of inter-process communication to be functional and accessing these services should be done through a remote-access protocols like REST. Most commonly these services should also have their own databases which are not accessible by any other service and naturally the services should be responsible for every transaction related to that specific data. Most important thing to note is that the microservices architecture was developed around the agile values and business needs of developers into autonomous teams. The microservices architecture offers a platform for each team to be allocated to work on individual services and codebases reducing the need of having to navigate large and complex codebases and coordinating with poten- tially hundreds of other developers. Team allocation structures are a good starting point when reasoning about the sizes of services as often it is enough for the team to start working on one service with modular code and then later refactor and split it into multiple services if needed.

Domain driven design [9] has a strong place within the microservices architecture since business domains should be clearly defined to maintain control over the distributed ser- vices. Each service within microservices architecture should be responsible for their own subdomain representing the data and functionalities they contain.

Basic components for building microservice architectures usually include an API Gate- way acting as an aggregation layer. Aggregation layer is responsible for controlling the traffic flow to services including load balancing, acting as a firewall for possible attacks and in unison with authentication service it is responsible for authorizing incoming re- quests. Services are the second component of the architecture and as described earlier they fulfill some function within the system and are accessed through the API Gateway. Services are not only responsible for user interaction, but especially in modern systems there are services for quantity of purposes like data analysis, data parsing, combined workflows, and data pipelines which enable the user interaction services to fulfil their purpose by providing much of the necessary data processing remotely. See Image 5 below for a simple example visualization of microservices architecture.

28

Image 5. Microservices architecture example

The microservices architecture is often paired up with event driven architecture [8 p.11] to enhance performance and interoperability. The upside of this approach being asyn- chronous messaging which unlike synchronous http REST does not have to wait for re- sponses avoiding situations where the services are blocked during high loads and faults. In addition to this the event driven architecture provides a platform for topic-based func- tionality where services can be subscribed to a topic and will receive messages related to that topic when an event is published, enabling simultaneous multiservice communi- cation and a higher performance as redundant messages will not need to be queued for each service. The event driven architecture requires some sort of mechanism and ser- vice like an event hub to be implemented.

Microservices architecture provides a great platform for large applications with almost infinite scaling, modularity, modifiability and deployability possibilities. This does come with a cost of performance since the decoupled services will need to communicate with each other using remote IPC mechanisms and a much higher complexity of the architec- ture which needs strict domains and policies to be set in place for the system to work as whole. When correctly implemented the microservices architecture offers unprecedented opportunities compared to other patterns, but it is certainly not the pattern for smaller applications and should almost never be considered as a starting architecture. However, looking forward is highly recommended and building modular code greatly helps when

29 transferring from for example, the layered architecture towards microservices architec- ture as the initial functionality is usually quite similar.

Chris Richardson goes into much further detail about microservices architectures in his book “Microservices Patterns” [9] offering insight on domain driven design, services, in- ter-process communication and more.

5 Agile software architecture

Agile comes in many flavors but every process and methodology are built upon the same ideals: being responsive, adapting quickly and being able to develop new features faster when requested by the users and to be able to show continuous progress during early phases of the project’s life cycle using live software instead of just documentation and initial designs. Authors of the agile manifesto [11] describe the agile values in the follow- ing way.

Individuals and interactions over processes and tools

Working software over comprehensive documentation

Customer collaboration over contract negotiation

Responding to change over following a plan

That is, while there is value in the items on the right, we value the items on the left more. [11]

There have been some misinterpretations of these values causing some organizations to abandon software architecture practice nearly completely for a time. Although the au- thors clearly state that there is value in the items on the right and they should be valued as well with the left side being the primary focus. A common interpretation of these values in many organizations moving towards the more agile style of software development was only using the left side items and getting rid of the right-side items completely, often causing a general lack of direction and lapses in communication which were supposed to be the strengths of the agile approach. As one would imagine this caused even larger issues than the traditional waterfall approaches and initially discouraged the usage of agile methodologies in many large organizations [12].

30

This has changed during the recent years with organizations finding their own versions of agile implementation and a comfort zone on the importance of both sides of the agile values while also understanding them better. While inspecting the agile values, on a glance one could easily argue that the right side represents software architecture, which is exactly why software architecture was supposedly not needed when working with agile processes. While this is mostly true in traditional sense, causing the software architects not to fit in with the agile approach initially as values shifted more towards the respon- siveness and development, software architecture is still a vital part of most applications and should not be neglected. The role of the software architects has also changed and developed drastically to be more in line with the agile values.

The traditional depiction of a software architect was an individual or group of individuals sitting in their ivory towers, planning, designing and then throwing the designs to the floor below for the developers to start developing the application. The sup- ported and enabled this way of working although, being disconnected from the product itself was problematic and often some of the major problems that occurred could have been easily solved with more communication between architects and developers. An- other glaring problem with the ivory tower sort of approach is the assumption that the architect is an expert on every part of the software which is just never true.

Obviously, this was not the standard way of working for everyone and every organization as often architects were more connected to the actual products and developers, as ar- chitects should always utilize the experts around them to find the best possible solutions. Many developers, architects and even clients were frustrated by the old waterfall model way of working, which is exactly why agile manifesto was initially created and why it became popular enough to become the standard way of doing software development.

How is a modern software architect different from a traditional one? First of all because of the agile way of working and many of the practices utilizing team structures like SCRUM [13] where everyone is “just” a member of the team, the software architect is a role for an individual within that team. The software architect might not even have a title of a software architect, his title might be that of an engineer or developer, the only thing that matters is that this individual has the main responsibility regarding the applications architecture within that development team. To be more in line with the focus on left side agile values and responsibilities of the right side being smaller, the architect in addition to architectural responsibilities, is a developer working as part of the team. In software

31 architecture, the one benefit that stands above everything else when it comes to agile values is the fact that architecture is about abstraction and the ability to communicate the very technical nature of software systems to different stakeholders in an understand- able way. Meaning individuals and interactions alongside customer collaboration have become the primary focuses and responsibilities for modern software architects.

The new challenge architects and development teams face is finding the balance be- tween architecture and agile values. How much architecture is “just enough” changes based on the project and the development team as more experienced developers might need less planning and architecture than a team consisting of more junior developers.

Agile manifesto consists of 12 principles and while it was created all the way back at 2001 the core principles remain valid and are essential for modern software development [11]

5.1 Evolutionary software architecture

Change is inevitable. Evolutionary architecture follows the veins of agile software devel- opment and focuses on applying incremental change to the system [14]. Evolutionary architecture largely builds upon the continuous delivery principles where a product is released in short cycles and makes architecture part of those cycles. As described in the earlier chapter, software architecture used to be something that was done at the beginning of projects to lay a foundation to start building the software from. The problem with that approach was the fact that things change and often during the development it was realized that the architecture did not account for some things that were extremely important for the project. In waterfall model this would mean returning to the first step and starting the design phase again which happened often as it was next to impossible to account for everything straight from the beginning. Agile software development re- quires agile architecture and the first key principle behind evolutionary is to offer a living, changing architecture for agile projects that supports similar incremental change that happens in practice with every release cycle.

Second principle of evolutionary architecture is guidance. This principle focuses on im- plementing fitness functions to ensure the system is developed towards the preferred direction. In practice these fitness functions are different mechanisms used for

32 monitoring and testing the software during development which include setting constraints and boundaries. These tests could be done during continuous integration and deploy- ment workflows to ensure the software works within given parameters, or they could be something, that is ran continuously in production environment to observe the system behavior. Good examples of fitness functions would be Netflix’s simian army [15] which includes various tools filling different purposes.

The third principle is about supporting multiple dimensions of change. This includes both technical and domain changes. Technical changes could include the ease of including new technologies like libraries, tools, and frameworks to the system. Domain changes could include additions of new features, interfaces and other more visible changes re- lated to the actual business. Architectures react to domain changes differently and the large part of the reason why modular architectures like the microservices have gained so much popularity during the recent times is because they enable these sort of domain changes to happen with relative ease.

Evolutionary architecture offers a platform for incremental development and works in co- hesion with the agile values and as of such offers good guidelines for how architecture should be approached in modern software development.

6 Documenting and visualizing the architecture

Documentation is a very controversial topic in agile software development as it is not valued as highly as presenting live code, but even in the modern software architecture and development it has important use cases and should not be neglected completely. The need for documentation varies based on the project and the team developing it, but there should always be some way of describing the software to its different stakeholders. Whiteboarding is popular way of handling the architectural communication between team members on day-to-day basis, but it only works when everyone understands the context of the problem and the presented solution. Often there is a need for a more long-term documentation which can be returned to for re-evaluating the design choices that have been made it the past or for describing the architecture for a stakeholder who is not yet familiar with the system.

33

6.1 Architectural views and notations

Software architectures are complex multi-dimensional entities, and these dimensions are represented as viewpoints. Views or viewpoints offer a way of presenting the certain types of structures and their relations within the system. A sample service view in micro- services architecture could describe the different services, their basic means of commu- nication and their purpose within the system alongside possible dependencies. Another view in the same microservices architecture could offer an overview on the deployment of the services describing the pipeline, or a team allocation view describing which teams the services belong to. Additionally, the communication mechanisms could be complex and important enough to warrant their own view.

Views offer important vantage points for observing the problems in multiple dimensions and while they cannot all be documented; the development teams should always make decisions on which views offer the most important architectural insight for the project and document accordingly. Understanding the audience is another extremely important as- pect of views and they should always be directly tailored towards specific stakeholders.

Notations are something that have lost most of their significance with the rise of agile methodologies as documentation is valued less. Notations are generally divided into three categories: Informal, semiformal and formal notations. Informal notations are still widely used as they are often graphically visualized views using a general-purpose dia- gramming or editing tool, like Visio, Powerpoint or the previously mentioned traditional whiteboard. Informal notation cannot be formally analyzed but offers an abstracted view of the architecture important for high level communication and information sharing be- tween shareholders. Semiformal and formal notations are rarely used in modern software development, but UML [16] used to be a popular semiformal way of producing a graphical presentation of the architecture using a standardized notation for architectural structures and is still used occasionally.

6.2 C4 Architecture model

While notation and formality has less meaning now, lack of common language for de- scribing the different architectural structures is a common problem in the industry. C4 Model was developed by Chris Brown between 2006 and 2011 to solve this problem [3].

34

C4 is a notation technique for graphically modelling software architecture and uses struc- tural decomposition of system into containers and components to offer different levels of abstraction as was explained in the first chapter. Having a model and common notation can help in building a more disciplined approach to architecture within an organization which can potentially help with cross-team coordination and overall communication.

Structurizr [17] a tool developed by the same author and is used for creating visualiza- tions of the C4 architecture model. In practice it functions as a zoomable model of the system where the user can observe the different levels of abstraction. If a high-level view of the architecture is required for the presentation purposes the architect can use the context view for showcasing the overall big picture. If a developer is moving to work on different part of the system and needs a more detailed look, he can check the container view, zoom into it to see the different software components the container consists of. Additionally, Structurizr offers a developer friendly way of creating architecture as it offers a possibility of creating visual diagrams of the architecture through code. The Image 6 below shows the container view visualizing the major software units and their relations with each other, the end users, and other systems.

Image 6. Sample C4 container view diagram [3]

35

The C4 model is more lightweight and flexible than the previously used modeling nota- tions and tools that have gone out of fashion. Furthermore, it can be used in conjunction with UML for code generated visualizations. C4 model was developed keeping agile val- ues in mind making it much easier to maintain than most alternatives.

7 Project background

The following chapters follow the practical work related to this thesis, the thought pro- cesses the project team used when designing and developing the thesis related product and the challenges faced during the development process. There will be short descrip- tions of different technologies, agile methods, team allocations and other architecture related processes included. This will be the project team’s answer for the question: how much architecture is “just enough” in agile software development and the project team’s version of evolutionary architecture.

The project team consisted of four developers and a product owner (PO). Two members of the project started few weeks earlier than the others and were mainly responsible for the initial planning, architecture, building the infrastructure and tooling for the project and the product being developed. Three of developers had also worked on the earlier version of the product beforehand and were already familiar with the idea behind it.

The product was an internal smart campus application developed to help employees by offering various quality of life improvements regarding improved workplace information flow and other benefits like helping them schedule their days better by offering them relevant real-time data around the campus area. The data-driven backbone of the appli- cation was developed before this project started and everything was available from the start.

Technically the product itself consisted of a progressive web application (PWA) frontend built on react and a traditional layered pattern backend solution built on Node.js Express and MongoDB database, combined with a sensor data pipeline. Additionally, there was a backend service for campus related news done with python and flask using Post- greSQL database, and an old frontend web application with unknown technical details. The whole solution was containerized with docker and deployed on azure.

36

8 Initial project requirements

As the team started gathering early project and system requirements it quickly became clear that there was a need to build the whole project infrastructure from the scratch. The very first requirements were the assembly of the toolkit and researching possible thesis topics that would benefit the project and deciding on the agile methodologies used for development. One additional requirement regarding the toolkit was that it should be de- coupled from the company’s own organizational tools as it would be used for collabora- tion projects with a local university.

8.1 Functional requirements for the product

The primary top level functional requirements for the end-user product consisted of the following.

• Users should be able to securely login using the organizational methods and services. If possible, there should be additional custom login service for development and university collaboration teams. • Users should be able to see relevant usage data from the corporation’s campus. Initially the campus restaurant usage and queue times alongside parking fill rates. • Users should receive relevant information regarding the campus. Initially in form of the campus newsletter. One of the newsletters should be high- lighted and highlight should be changed daily. • Users should be able to customize their frontpage with widgets of their lik- ing. New features should have widgets.

After further discussions it was evident that the product was meant to be a living product with constant incremental changes and to be used as a steppingstone for collaboration projects, finding and hiring new talent and for testing experimental technologies. The project team realized that implementation of architectural mechanisms to support this model of development and collaboration would be essential for the longetivity of the pro- ject.

In addition to the previously mentioned requirements, the product owner mentioned an additional, experimental sensor-based feature which should be implemented in the re- lease version of the product. This feature showcases a real-time visualization of employ- ees eating in the campus restaurant as 3D models. The idea behind the feature was to

37 enable the users to see the real-time usage status of the whole restaurant without any- one’s privacy being invaded.

8.2 Quality attributes

Once the initial functional requirements were set, the project team started looking into the general direction regarding the quality attributes which should be prioritized in the project and when designing the system. The project team deduced that main quality at- tributes defining the architecture would certainly be modifiability and expandability, be- cause incremental change to the system and addition of new features were the priorities. Additionally, there were other important quality attributes to account for and they were as following.

• Security. System should be relatively secure and only employees should have access. • Performance. System should have decent enough performance to not in- terfere with usability. • Usable and tailored more towards engineers and technical staff since most of the employees are from this category. • Testable. System and all its parts should be testable.

Other considerations which would be likely connected to the project were modularity and ease of collaboration could be a possible quality attribute, but project team would have to come up with a metric to measure it with.

8.3 Constraints

Right from the beginning it was clear there would be quite a few constraints when it came to the project and the product itself. First constraint was the usage of old code and parts of the old system. This required fair amount of attention and planning ahead since the sensor services were controlled by a third-party partner. This meant that the project team initially had no direct influence on things like traffic flow from those sensors or the old authentication mechanism.

Other constraints included using the old authentication in some form, like having it as part of one version of the system which could be accessed from outside the organization.

38

Everything was and should be deployed on the organizations Azure which had a special subscription not including every cloud service, so that would require special tackling around when designing the system, and more custom code and configurations than usual.

The restriction of using old code obviously meant restricted technology choices and be- cause it is not recommended including too many different technologies to a project un- less there is an extremely strong case to be made for them. For these reasons, the pro- ject team decided to continue with the same software technology stack for the most part. The frontend would be a PWA written in Javascript and backend services would utilize node.js express for I/O heavy features and python with flask for more compute heavy tasks and smaller services.

9 Project infrastructure and early design choices

As mentioned in the earlier chapter, the first key requirement was building the project infrastructure including the whole toolkit and team collaboration methods. The project team was already familiar with some of the agile methodologies like SCRUM [18] and KANBAN [19], but neither felt like the right fit from the start as the project team wanted something that included the SCRUM team and meeting structure, but a more flexible approach to task creation and sprints. The project team decided to try SCRUMBAN [20] which is a mixture of both SCRUM and KANBAN to get the best out of both worlds.

9.1 Toolkit

As the project team started building the project toolkit the very first decision needed to be made was deciding on the tool as it would be used for creating the project backlog. As the product owner wanted to keep things separate from the or- ganizational tools and use something which was more openly accessible the project team decided to stick with Trello as everyone in the team was already familiar with it and it would fit perfectly with the SCRUMBAN agile methods.

As the project team started considering the project requirements and building the back- log another thing which quickly rose as a priority was the version control as evidently there was no existing one in place. Although the product owner and other members of

39 the organization did have a long history of various projects done with universities and other third-party organizations, all of the previously created code was spread around in various repositories under different individuals and organizations. It was clear that for the continuous future development this would need to change.

The very first major design decision project team did was creating a GitHub organization [21] meant for collaboration projects. The previously created code repositories would be gathered under organization for future clarity and ease of coordination. This organization would be shared with both the employees and with the university students and both could form teams under the organization. For the projects to be truly collaborational, the code should be shared as it can greatly help both sides, with the students representing the potential future talent for the corporation. This would give the project team the first met- rics for collaboration quality attribute: Employee and student contributors on repositories, count of repositories under the organization and ease of access to all of the code related to the projects. Additionally, the GitHub organization offers a project management tool more suited for software development and could be a potential addition to the toolkit in future projects as having project management in the same place as code repositories could be beneficial for information sharing.

Communication within the team would be done through the organizational toolkit and as discussed in the previous chapter most of the primary technology choices were already mostly set in stone.

9.2 Early design choices and observations

After conducting a thorough analysis on the functional and quality attribute requirements the project team started investigating the best ways of approaching the overall architec- ture of the project. It was evident that the projects would be done in collaboration with third parties yet there was a will for a production ready application to be released and maintained, causing few interesting dilemmas. There was clearly a need for separation of development and production deployment environments, which is often a standard ap- proach to building software in general. Having a sandbox testing realm resembling the live production, but with every action being reversible, is highly preferable as mentioned in the testability section of the quality attributes chapter.

40

The project team wanted to make the product’s architecture support incremental change and realized that modularity could greatly assist with both the collaboration and expanda- bility as features could be added to the final product as modules after its initial release. Additionally, this would help with future developability as third parties could concentrate on their own modules instead of dealing with the whole codebase which would be bound to grow into a monolith at some point during its lifespan.

The concern of building a monolithic application was especially large as in most cases the developers working on the application would have no prior experience of working on the codebase. This would cause the initial complexity and barrier of starting to work on the application ramp up exponentially every time a group finished working on the appli- cation and next group would start. Not to mention how hard it would be to coordinate multiple teams working on the same codebase at the same time with some of them being employees, some university students and some from other third-party organizations.

10 Project architecture and pattern choices

The project team started looking forward and away from the original layered architecture and looking for alternative solutions more in line with the quality attribute requirements. A natural way of approaching modularity was looking at team allocation structures and researching ways to enable teams to work independently from each other. After further research it was concluded that service-oriented architecture approaches would enable this sort of development and deployment model.

10.1 First pattern consideration, the microservices

One of the reasons microservices architecture was developed was to support agile phi- losophies of small teams which was perfectly in tune with the wanted quality attributes and team allocation structures. Additionally, it was already well known and finding re- search material regarding the implementation details and supporting architectures was simple, and for those reasons the project team chose this as the original architectural pattern to start building from.

In the original layered architecture approach the central server handled three different responsibilities: authentication, restaurant data processing and parking data processing.

41

Since there was no gateway the news server had to request authentication and authori- zation from the central server. The original system and its domain responsibilities visu- alized in Image 7.

Image 7. The original project architecture

When observing this from the microservices perspective, the news server was already a microservice as it was autonomous stand-alone service decoupled from the rest of the application. The central server however should be split into three different services each holding their own responsibility domains, especially since the project team wanted to make the original authentication service optional. The custom authentication service would be deployed only on development realm and the production realm would use the organizational authentication. These services would need an aggregation layer to be built in the form of an API gateway. The gateway would be responsible for controlling the incoming traffic, handling tasks like load balancing, authorization and directing the re- quests to right backend endpoints. The Image 8 showcases the system in microservices form with the backend having a more focused domain decomposition.

42

Image 8. The original architecture as microservices

Although the microservices solve many of the problems regarding the backend architecture like team allocation, code splitting and separate deployments it would complicate the overall architecture with features like the previously mentioned need to use IPC for inter-service communication. No asynchronous IPC mechanisms were initially required for the current features of the product, so it felt reasonable to think of it as something that would be eventually implemented when needed. No architecture is perfect, and the project team felt that these complications were necessary evil compared to the potential initial and future gains, but the architecture should be evolutionary to support incremental adding of these mechanisms in the future.

The microservices architectural pattern would solve most of the backend issues, but the application would still have monolithic frontend. This meant it would only solve half of the problem project team was having. The project team started researching possible frontend solutions supporting similar team allocation and collaboration structure to use in conjunction with the microservices backend.

10.2 Microkernel style frontend speculations and research

The project team started researching different solutions for building modular applica- tions. The microkernel architecture seemed intriguing and as it supported the modular

43 approach the project team wanted to take. There were several problems for implement- ing the microkernel however, as it most of the samples and frameworks developed were for Java applications or for node.js backend solutions. The old PWA solution project team had was a client side rendered application which meant that the architecture and its im- plementation mechanism would have support browser Javascript modules, and both re- act and PWA. Another problem the project team had with microkernel architecture in general was the need for central core application, as it would be much better if the appli- cation could just be developed as several independent applications and stitched together afterwards. This would give the project teams full autonomy and enable more experi- mental prototyping as nothing would be coupled.

10.3 Meet the micro frontends

The project team started to have a clearer picture on what they wanted their architecture to achieve, and after further research learned about an architectural pattern called micro frontends [22]. The micro frontends pattern is brand new and advertises itself as micro- services in the frontend which was exactly what the project team was looking for. Micro frontends had several features which made it even better fit than what was initially spec- ulated as most of the technologies were platform agnostic, meaning you could develop applications created using different frameworks like react, angular and vue.js, and com- bine them together.

Many of the micro frontend technologies also had great amount of freedom when com- bining the applications. The application separation could be done by page or by feature, for example an e-commerce application could have shopping cart, a service catalog and user features all in their own applications even though they would be shown on the same page. The technology of choice for the project group was called module federation which is an addon for popular module bundler called webpack [23].

Although micro frontends could technically be developed on their own, they would require a host or shell application for combining the applications functionalities, which would be responsible for navigating between the various applications and possibly providing ap- plications with global functionalities like redux stores. In module federation the depend- encies can be shared between applications. This means that the micro frontends perfor- mance and load times will not suffer from running multiple applications. Additionally,

44 webpack and module federation support service workers, which meant that building PWA micro frontends was possible.

The downside of the approach project team took was the fact that it added a fair bit of complexity to the application. Additionally, with micro frontends and especially module federation being brand new concepts, there was practically no documentation. And since the project team was building a PWA application there obviously was absolutely no doc- umentation when it came to micro frontends combined with PWA. As the micro frontends felt like an answer for everything the project team needed, they decided to continue working on it even with a realization that the implementation would require experimenta- tion and a lot of effort. The final domain decomposition with end-to-end features is show- cased in Image 9 below.

Image 9. The project architecture as micro frontends

45

With the pattern representing what the project team wanted from their architecture the focus started shifting more towards the implementation details and the cloud solution design.

11 Creating a cloud solution design

The project team was now at a point where they could start creating more practical de- signs based on the architecture and began researching Azure [24]. The product owner had selected MS Azure as the deployment environment because it was a public service, meaning sharing access with third parties was much easier than when working with com- pany’s internal tools and because it was much easier finding information about it and people could have pre-existing knowledge of working with it.

Based on the architecture the project team had a clear picture of what they were search- ing for. Services would have their own GitHub repositories and would be deployed as containers on a cloud hosting service. Azure has multiple different options for this as the most traditional approach would be creating virtual machines and deploying the software on them similarly to how it would be done on premises, but the project team wanted something simpler and looked for cloud native solutions instead. The simplest ways of hosting container-based applications were ACI or Azure container instances and web apps for containers. Third and last way of doing this cloud natively was AKS or Azure Kubernetes service [25], which is a somewhat heavier solution utilizing the popular Ku- bernetes platform in a cloud native form. The project team did not have access to AKS because of the limited azure subscription, meaning the choice was between ACI and Webapps which function quite similarly but with ACI being a standalone service and Web apps being tied to azure app service subscription for billing and resource management. The project team decided to go with Web Apps as some of the pre-existing parts of the system were already deployed on them and it felt like a solid solution.

The deployment for previous pieces of the system was done through docker hub, but the project team wanted to try a service called azure container registry. ACR or Azure con- tainer registry can be used for storing docker images similarly to docker hub but has the added benefit of being in the same environment as the services hosting the applications. This makes deploying the software much faster and ACR having a built-in continuous deployment with webhooks when used in conjunction with azure services being another

46 important perk. Another good feature inbuilt to the web apps is the ability to have multiple deployment slots. An updated application can be deployed into staging slot and is only swapped to production slot if the startup process goes cleanly. If there is an occurring error it means nothing is deployed, and the old version remains. The deployment flow is illustrated in Image 10 found below.

Image 10. Deployment workflow

Azure has a wide variety of cloud native database solutions with the most notable one being CosmosDB. CosmosDB offers a scalable cloud native noSQL platform which can be used through several APIs like MongoDB and mySQL. The old server which was refactored during the project already used MongoDB through mongoose library and the project team saw no reason to change it as it was perfectly functional, only relevant changes made were decoupling the domains as restaurant and parking used the same collection which did not seem like a good practice. The news service used postreSQL database and azure had a corresponding service in the form of azure postreSQL server. As mentioned in the earlier chapters the microservices should have their own databases, but especially in cloud environment there is no need for every service to have their own database server. The two azure native cloud service database platforms would be able to support all the services developed in the future and having two different platforms utilizing different APIs would offer a fair bit of flexibility for the development teams tech- nology choices.

47

For storage operations Azure offers variety of options, but what the project team was looking for in this case was something closely resembling a web server for storing and serving static content like the news related pictures. Azure offers a good rest-based ser- vice called azure blob storages for unstructured data. Blob storages are connected to a azure storage account which can hold multiple blob storages, file stores and queues.

After the deployment choices were decided on the project team proceeded to look to- wards the security options. API gateways are used to control the traffic to services but require a virtual network to fulfill their purpose. Virtual networks simulate on premises environments where all devices are connected to a same local area network and service discovery is handled through private IP addresses. API gateway being the only service with an openly accessible public address controls the traffic flow in and out of the system are usually implemented using Azure Application Gateway and can be upgraded with a firewall for better security, the project team did not initially have access to the application gateway service and decided to build an API gateway manually using Nginx [26].

Method used by the corporation for organizational authentication and authorization was handled through azure active directory (AAD) which is an enterprise identity service providing SSO and multi-factor authentication. Every application used by the organiza- tion was based on AAD which is why it was required as an authentication method for the production version of the product.

For security management, threat protection, and recommendations azure has a service called Security Center which proved to be a useful tool for tracking and fixing security vulnerabilities. The project team wanted something for handling secrets and certificates, and azure provides this in a form of Key Vault, but unfortunately it was not part of the subscription originally used.

Azure monitor provided observability to the deployed applications, their usage and net- working. This is essential when tracking costs or when searching for ways to improve performance by finding potential bottlenecks within the system. The initial cloud solution design is visualized in Image 11 below.

48

Image 11. High level overview of the cloud solution

In the case of the project groups’, the services did not have need for remote IPC mech- anisms, but if they would be needed in the future azure offers multiple ways of imple- menting event driven mechanisms. Event grid is the most lightweight option and can be used directly with all azure cloud native applications to enable the use of automated events. For more heavy-weight, event-driven architectures and operations azure has an event hub which is a real-time data ingestion service such as Apache Kafka [27].

12 Further development and complications

Since the micro frontends and implementation technologies like the one chosen by the project team called “module federation” are new inventions and just starting to gain pop- ularity it was extremely hard to find information and code samples. Webpack and Module federation offer very little in terms of actual documentation and although they do have a fair amount of very simplistic code samples and examples in their GitHub repository, figuring out how to combine and interpret everything proved to be a complicated task. As not only the tech choices and libraries used in the samples were different from the project teams, additionally the actual form of implementation of the whole architecture was dif- ferent.

49

The project team wanted the software units or modules to be autonomous independent units but additionally wanted to include global properties like a shared redux store with persistent data yet did not want any of the modules to be reliant on the global function- alities. Sharing the redux store for react applications did not prove problematic, and the persistent data could be shared to applications using other frameworks through browser storage options like local storage and session storage. What did prove problematic though was the fact that for the application to be truly autonomous the reducers which required the usage of persistent data would have to be injected to the host store asyn- chronously and redux does not really support persistent asynchronous reducers as it cleans up the storage if the reducer does not exist when it is called before injection. As the project team did not want to add code belonging to the feature applications to the host application this was a big dilemma. After few days of experimenting the found solu- tion was adding automated empty dummy reducers for the persistent asynchronous re- ducers every time the store is initialized which would deny the redux cleanup process of persistent initially nonexistent reducers. The micro frontend applications were configured with different modes where they would create their own redux stores and other necessary resources when ran independently and use the host resources when available.

Unfortunately, the third-party partner organization which was involved in the project early on was forced to transfer their assets to the project team as they could no longer maintain them, causing some additional workload for the project team. Eventually it would be a good thing to have all the assets available under one organization, but for the current project’s scheduling this caused complications. The third-party partner organization con- trolled the sensors and data pipelines which had to be transferred to a different location and required some additional configurations and hardware.

13 Azure environments and Cost estimations

The azure subscription started causing more issues as the project got nearer to the re- lease and it was concluded that to properly secure the solution and make it easier to develop in the future there was a need for alternative, more production ready environ- ment. The corporation, being a large international company had many organizational private cloud environments and tools at their disposal which were studied, but as they only offered environments for teams operating inside the company and as the project

50 was supposed to be collaborational the available choices did not fit the project team’s needs.

It was decided that the best approach would be getting a completely new azure subscrip- tion. As all new costs within organization would need to be budgeted and approved by higher ups the project team needed to come up with cost analysis involving the potential costs for the current azure solution and how much could they potentially increase in the future with more users and more deployed features.

As there had only been very small test groups beforehand it would be very hard to judge the potential usage of the application just by looking at the metrics, the project team decided to proceed with the minimal requirements for the features required designed for light production use as it would enable the use of all necessary production ready fea- tures. The light production would support a bigger audience than required meaning there was enough room to grow and as the subscription could be used to host multiple systems the extra allocation could be used for supporting and hosting other future projects and products. Azure offers a simple tool for cloud service cost estimations [28] and the fol- lowing calculations created with it [Table 1].

Table 1. Azure cost estimation for light production usage

Service Name Tier Additional infor- Estimated cost mation Container Registry Standard / Premium 10 / 500 webhooks 20-50e / m month CosmosDB Standard p/t 400 Ru/s 20-50e / month PostgreSQL Server Basic 50e / month Storage account Standard LRS, Hot, General 50e / month purpose V2, 2TB Application Gateway Medium Firewall included, 1-2 100-200e / month instances App Service Standard (S2) 2 cores, 3.5 GB RAM, 140-280e / month 50GB Storage 1-2 in- stances Overall Cost 400-651e / month

Services missing from the list were Virtual networks, which azure offers for free and only bills for VNET peering which the project team had no need for and Azure Key Vault which was deemed useful, but not necessary given the current scope of the application. The database tiers may seem low, but the actual amount of daily database writes and reads

51 for the system was extremely low since the services could serve most of the content directly from cache as the application did not offer many personalized services and most of the content was generalized. Application gateway and App service could be ran with multiple instances if needed for availability needs, but ultimately it would be left for the management to decide how essential the system uptime would be for the product as they would effectively double the costs for the corresponding services. Additionally, the cost analysis did not include AAD as the subscription would be under the organizational do- main, meaning there would be no additional costs involved.

14 Conclusion for the project, but not for the product

As the system and the architecture have been built with future in mind, it is important to look forward to what could be done next. By the time this thesis is nearing its completion, the digital twin feature utilizing the 3D restaurant model is nearing its completion and will be added to the product. The frontend solution is another micro frontend web application and can be added easily. The backend solution however proved a bit problematic as it requires a fair amount of computing power to run the model and the project team thought it would probably be best to deploy it on premises running in same machinery as other analytics engines even though azure does offer possibilities for running streaming and gaming platforms.

During the development of the current product there were several innovation projects being worked on in parallel. The idea behind those innovation projects was to produce new feature prototypes for the application, and as with the current architecture those prototypes could be refined and added to the current application with relative ease to an extent. For features providing more personalized content there would be a need for de- tailed user modelling, services and potentially implementation of more advanced remote IPC mechanisms like events. Claiming that adding everything previously mentioned should be easy is false but claiming that they could probably be added without touching any existing software components and not having to worry about breaking anything is potentially true, and that already is a big step up when it comes to producing software. To the project teams eyes that is already an evolutionary architecture, especially when everything can be individually built, experimented with, and tested before they are added to the product.

52

In retrospective there were a lot of things that proved challenging for the project team. As the team consisted of mostly junior members, the project management and task time consumption estimations proved to be difficult early on. The architecture itself was very experimental and because of its complexity it caused some implementation challenges, especially since the previously built code and parts of the system had to be refactored to support this kind of architectural approach. However, to enable expandability and incre- mental development of the project in the future, the effort and the time investment was deemed necessary.

The aim for this thesis was to offer a high-level overview of what software architecture is about, how it can be utilized in modern software development and to give solid reasoning behind why certain design choices were made during the development and what led the project team to the path they ended up taking. Software architecture was a big part of that path and every member within the team felt like having an aim, built step by step is an essential part of agile software development. Software architecture offers a powerful platform for software development and it is up to the developers and management to use it the way they see fit and where it will be useful for their specific projects. It should not be neglected, but neither should it be overdone and finding that balance is the hardest part of modern software architecture.

53

References

1 ISO/IEC/IEEE International Standard - Systems and software engineering—Vo- cabulary, in ISO/IEC/IEEE 24765:2017(E) , vol., no., pp.1-541, 28 Aug. 2017, doi: 10.1109/IEEESTD.2017.8016712.

2 Bass Len, Clements Paul, Kazman Rick. Software Architecture in Practice (SEI Series in Software Engineering) 3rd Edition, Kindle Edition. E-book. AddisonWes- ley Professional.Details

3 Simon Brown. C4 Software architecture model. Internet. . Read 10.3.2021

4 J. C. Patni, S. Banerjee and D. Tiwari, "Infrastructure as a Code (IaC) to Software Defined Infrastructure using Azure Resource Manager (ARM)," 2020 International Conference on Computational Performance Evaluation (ComPE), Shillong, India, 2020, pp. 575-578, doi: 10.1109/ComPE49325.2020.9200030.

5 ISO/IEC 25010. Internet. . Read 20.3.2021

6 D. Elliott, C. Otero, M. Ridley and X. Merino, "A Cloud-Agnostic Container Or- chestrator for Improving Interoperability," 2018 IEEE 11th International Confer- ence on Cloud Computing (CLOUD), San Francisco, CA, USA, 2018, pp. 958- 961, doi: 10.1109/CLOUD.2018.00145.

7 Best UX Tools: 11 Tools to make your life easy in 2021. UXCam .18.3.2021. In- ternet . Read 6.4.2021

8 Mark Richards. Software architecture patterns. E-book. O’Reilly Media inc. 2015.

9 F. Rademacher, J. Sorgalla and S. Sachweh, "Challenges of Domain-Driven Mi- croservice Design: A Model-Driven Perspective," in IEEE Software, vol. 35, no. 3, pp. 36-43, May/June 2018, doi: 10.1109/MS.2018.2141028.

10 Chris Richardson. Microservices Patterns. Audiobook. Manning Publications. 22.10.19.

11 Agile manifesto. Internet. . Read 4.2.2021.

12 Sanjay Zalavadia. InfoQ. Internet. . Read 21.4.2021.

13 P. Trivedi and A. Sharma, "A comparative study between iterative waterfall and incremental software development life cycle model for optimizing the resources using computer simulation," 2013 2nd International Conference on Information Management in the Knowledge Economy, 2013, pp. 188-194.

54

14 Neal Ford, Rebecca Parsons, Patrick Kua. Building Evolutionary Architectures: Support constant change. O’Reilly Media Inc. 2017.

15 Netflix tech blog. Netflix. Internet. . 19.6.2011. Read 20.2.2021.

16 E. Braude, "Incremental UML for Agile Development: Embedding UML Class Models in Source Code," 2017 IEEE/ACM 3rd International Workshop on Rapid Continuous Software Engineering (RCoSE), 2017, pp. 27-31, doi: 10.1109/RCoSE.2017.1.

17 Simon Brown. Structurizr. Internet. . Read 10.1.2021.

18 A. Mundra, S. Misra and C. A. Dhawale, "Practical Scrum-Scrum Team: Way to Produce Successful and Quality Software," 2013 13th International Conference on Computational Science and Its Applications, 2013, pp. 119-123, doi: 10.1109/ICCSA.2013.25.

19 A. Ang and R. Piplani, "A performance comparison between the Extended Kan- ban Control System (EKCS) and the Traditional Kanban Control System (TKCS)," 2010 IEEE International Conference on Industrial Engineering and En- gineering Management, 2010, pp. 2052-2056, doi: 10.1109/IEEM.2010.5674654.

20 Pahuja, Savita. SCRUMBAN. Internet. . Read 28.4.2021.

21 Github organizations. Github. Internet. . Read 28.4.2021

22 P. Y. Tilak, V. Yadav, S. D. Dharmendra and N. Bolloju, "A platform for enhanc- ing application developer productivity using microservices and micro-frontends," 2020 IEEE-HYDCON, 2020, pp. 1-4, doi: 10.1109/HYD- CON48903.2020.9242913.

23 Webpack. Webpack. Internet. . Read 20.3.2021.

24 Azure docs / architecture. Azure. Internet. . Read 14.2.2021.

25 Steve D. Pountol. Docker & Kubernetes (2 Books in 1). Luke Vyoz. Audiobook. 25.07.2020.

26 Derek DeJonghe. Nginx Cookbook. O’Reilly. eBook. Read 5.3.2021.

55

27 R. Shree, T. Choudhury, S. C. Gupta and P. Kumar, "KAFKA: The modern plat- form for data management and analysis in big data domain," 2017 2nd Interna- tional Conference on Telecommunication and Networks (TEL-NET), 2017, pp. 1- 5, doi: 10.1109/TEL-NET.2017.8343593.

28 Azure pricing calculator. Azure. . Read 25