Skip to main content

Architecture

Introduction

This document aims to explain the architectural choices made for the GeoGirafe project. It highlights technological choices made to meet the project objectives, which serve as a reference for evaluating the technological choices made.

Naturally, the project architecture is not fix and will evolve over time.

General architecture principles

GeoGirafe's architecture is based on the principles described by 2 architecture models:

  • The hexagonal architecture. The application is broken down into several interchangeable, loosely coupled components,a which can be connected and communicate together via "facades" that create an abstraction and define a communication contract.

  • The Component-based software engineering. It consists of using a modular approach to the architecture of an IT project, which ensures better readability, better maintenance, and allows a better separation of responsibilities in the software.

Those architectural patterns emphasize the separation of concerns and promote the modularity and maintainability of the application. Here are some advantages of the Hexagonal Architecture:

  • Clean Separation of Concerns: We have a clear separation between the core business logic and the external concerns, such as UI, databases, and external services. This separation makes the codebase more organized and easier to understand.

  • Testability: The architecture promotes testability as the core business logic is isolated from external dependencies. This allows for easier unit testing of business logic without the need to interact with external services.

  • Flexibility and Maintainability: Those principles allow more flexibility in making changes to the application. Since the core business logic is decoupled, modifications to one part of the application are less likely to affect other parts, making it easier to maintain and evolve the software over time.

  • Adaptability to Different Environments: The architecture's focus on ports and adapters allows the application to adapt easily to different environments, such as switching backend technology or libraries. New adapters can be implemented without altering the core business logic.

  • Ease of Collaboration: The clear separation of concerns enables different teams to work on different parts of the application in parallel. The component 1 team can focus on implementing its own business rules independently of the component 2 team.

  • Reusability and Interoperability: The modularity and decoupling in the architecture facilitate reusability of components. Business logic can be reused in different contexts, and the application can interact with external systems or services through standardized interfaces, promoting interoperability.

  • Isolation of Frameworks and Libraries: The application's core logic is independent of any specific frameworks or libraries used for the UI or data storage. This isolation protects the business logic from being tightly coupled to any particular technology stack.

  • Sustainable Over Time: It reduces technical debt and makes the application more sustainable over time. Changes in technology or infrastructure can be easily accommodated without affecting the whole application.

Web-Components

After an in-depth analysis of the various options available, we decided to use Web-Components as the main technology for the GeoGirafe project. Web-Components are a W3C specification, and enable the creation of reusable, self-contained components.

The main advantage of Web-Components is that they are agnostic, and therefore not tied to any particular library, framework or vendor. As such, they meet the requirements of project sustainability and cost control.

Indeed, if technological migrations and evolutions are inevitable, Web-Components offer greater long-term stability. Web-Components are natively supported by all modern browsers, thus limiting the need for heavy framework dependency.

Thanks to its backward-compatible design, a Web-Component developed today will continue to function unchanged in a few years' time, even in the event of new specifications. This is not to say that they will never need to be migrated or adapted, but unlike a framework, which comes with a whole ecosystem whose evolution must be monitored to guarantee the project's stability, performance and security, with Web-Components these aspects are managed by the browser itself.

Another reason for choosing Web-Components is their modularity. Thanks to Shadow DOM, the styles and internal behavior of components can be encapsulated and isolated from the rest of the page, avoiding collisions and interference. Web Components thus promote a modular approach to building web applications, enabling the user interface to be broken down into distinct, independent components.

Finally, Web Components benefit from a growing ecosystem, and there seems to be a growing willingness to support this new standard. Indeed, all the major frameworks (Angular, React, Vue) now support Web-Components. Companies are making libraries available for working with Web-Components, including Microsoft with Fast, Adobe with Spectrum, Google with Lit, and Salesforce with Lightning.

In short, Web Components offer a simplified, modular and high-performance approach to Front-End development, while avoiding complex and costly future migrations and reducing maintenance costs. The advantages of Web Components in terms of technological independence, compatibility and separation of responsibilities make it possible to meet the requirements of perenniality, modularity, and economic sustainability of the project.

Dependency management

Web components are a modern, future-proof technology, but they don't solve everything. The reason frameworks exist is that they meet needs that are not covered by any web standard today. Examples include application state management, efficient management of DOM updates, and certain development and debugging tools.

GeoGirafe does NOT want to reinvent the wheel or to create its own framework. It would be a waste of time and would require too much maintenance in the long run. To avoid falling into this trap, and in order to meet these needs efficiently, certain libraries to be added as dependencies to the project must be selected judiciously. By carefully choosing those dependencies, GeoGirafe can benefit from the features and optimizations provided by these libraries, saving time and effort in the development process. Additionally, by relying on well-established libraries, the project can take advantage of their active communities for support, bug fixes, and updates, ensuring long-term stability and scalability.

To integrate the selected dependencies effectively, it is important to avoid tightly coupling them with the codebase. This can be achieved by utilizing "interfaces" or "wrappers" to encapsulate the specific functionality provided by the dependencies. By employing this approach, GeoGirafe ensures a more decoupled architecture that is flexible and adaptable to changes. If a particular dependency becomes obsolete or needs to be replaced, GeoGirafe can simply modify the internal implementation within the interface or wrapper, without having to modify the entire codebase. This reduces the potential impact on the application's functionality and minimizes the maintenance effort required.

State-Management

State management is an important concept in software development, particularly in the field of applications and user interfaces. It refers to the way in which the data and state of an application are managed, modified and shared between different components.

In many applications, state refers to the set of data that describes the current state of the application, including variable values, configurations, connection states, display states and so on. Managing this state is crucial to ensuring that the application runs smoothly.

By using a well-designed state management approach, developers can simplify the development process, improve the maintainability and testability of their code, and deliver a smoother, more responsive user experience.

State management is therefore a central element of the application. Many state management libraries exist, and it's important to choose one that is stable, high-performance and not too intrusive in the code. Indeed, it must be possible to replace it if necessary, without having to modify all the application's components.

The State Management of GeoGirafe is based on the on-change library. This library itself is based on the standard Proxy object.

DOM manipulation & Responsiveness

In native javascript, dom manipulation can be a laborious and verbose process, often requiring the use of complex methods and properties to access, modify and create HTML elements. However, many libraries offer a simplified and more intuitive approach to performing these tasks, as well as optimizing performance.

Like State-Management, we have looked for a library that can be replaced if necessary, without impacting all application components. And we have found µhtml. The library allows developers to write HTML templates using template literals in JavaScript, providing a concise and efficient way to manipulate the DOM. uHtml offers a lightweight and flexible alternative to traditional DOM manipulation methods, making it easy to create, update, and remove elements dynamically. One of the key advantages of uHtml is its simplicity and ease of use, and the fact that it allows its integration or replacement into an existing project without the need for a major refactor.

Performance

Performance is an essential element in delivering an optimal user experience. We are committed to designing a front-end architecture that promotes fast loading times, smooth navigation and a highly responsive user interface.

Web Components are designed to be lightweight and performance-optimized, but that's not enough. In order to optimize performance, the following elements need to be taken into account:

  • Initial load size: It's crucial to minimize the initially loaded size by reducing JavaScript, CSS and other unnecessary resources. This can be achieved by using techniques such as minification, compression and lazy loading of non-essential resources.
  • Number of server calls: It's important to reduce the number of server calls by grouping requests, using appropriate caching and optimizing network requests. This minimizes latency and improves overall application loading speed.
  • Code quality: Well-optimized and structured code can make a major contribution to performance. It is essential to use efficient coding practices, avoid redundancies, optimize loops and algorithms, and ensure that code is clean, readable and maintainable.

To meet these needs, bundling tools (vitejs) and quality control tools (linting, sonarcloud) have been implemented.

Quality

Unit tests are specifically designed to validate the correct operation of individual code units by isolating each component and checking for specific functionality, edge cases and error scenarios.

Integration tests, on the other hand, are designed to verify the correct interaction between the various modules and components of the application in an environment close to production. It is essential to work with data that is close to real-life, in order to assess the quality and performance of the application as soon as possible. This avoids the risk of focusing solely on unit tests, which may not cover all possibilities. This avoids the "tunnel effect", and ensures that as many use cases as possible are covered as early as possible in the project.

To meet this need, we regularly update our test environments using real data from production. This enables us to simulate real-life conditions as closely as possible, and to evaluate application performance in authentic scenarios. By using these real-life test environments, we can detect and resolve potential problems earlier in the development cycle, thus improving the overall quality of our application.

tip

Before any major release, integration tests are done manually following a test book accessible to everyone here: https://docs.google.com/spreadsheets/d/1UEOs3WAC-3JlpuTbXCVjE5OAqDYtQVlwqeZBopQz-9E/edit?usp=sharing

Security

Security is of big importance in GeoGirafe. We have to pay attention to for example data protection, business reputation, or possible financial loss.

DevSecOps, a combination of Development, Security, and Operations, is an approach that integrates security practices into the entire software development lifecycle. The goal here is to identify as early as possible the vulnerabilities our application could have, by incorporating security measures from the beginning of the development process. This proactive approach reduces the likelihood of security breaches, protects sensitive data, and enhances overall application security.

In order to achieve this, a quality and vulnerability control tool is needed. We have chosen SonarCloud.

Diagrams

TODO: Architecture diagram

TODO: Infrastructure diagram

Querying features using WMS or WFS

---
config:
theme: neutral
---
flowchart LR
A[Want to do GetFeature/GetFeatureInfo on layer] --> B{has layer been configured as queryable?}

B -->|Yes| C{Does the layer's OGC server provide a WFS URL?}

C -->|Yes| E[Do a WFS GetFeature request]
C -->|No| F[Do a WMS GetFeatureInfo request]
B -->|No| D[Don't do a request]

This decision-tree is implemented in the MapComponent.onSelectFeatures() method