Category Archives: Arquitetura

O que é TOGAF

O que é TOGAF®?

TOGAF®—The Open Group Architectural Framework é uma das estruturas de arquitetura empresarial para melhorar a eficiência empresarial. A estrutura ajuda as empresas a definir suas metas e alinhá-las com os objetivos de arquitetura em torno do desenvolvimento de software empresarial.

O TOGAF® tem sido usado por arquitetos corporativos (EAs) como uma linguagem comum para traçar estratégias de desenvolvimento de TI por mais de 25 anos. Ele foi desenvolvido em 1995 para ajudar empresas e arquitetos corporativos a se alinharem em projetos interdepartamentais de forma estruturada para facilitar os principais objetivos de negócios.

Em particular, de acordo com o Open Group Architectural Forum, o objetivo fundamental do TOGAF® é dar suporte às necessidades críticas dos negócios por meio de:

  • Garantir que todos falem a mesma língua.
  • Evitando a dependência de soluções proprietárias padronizando métodos abertos para arquitetura empresarial.
  • Economizando tempo e dinheiro e utilizando recursos de forma mais eficaz.
  • Alcançando ROI demonstrável.

E para garantir que o acima seja implementado de forma sistemática e repetível, um processo personalizável chamado Método de Desenvolvimento Arquitetônico (ADM) TOGAF® pode ser seguido em vários estágios para gerenciar os requisitos de qualquer empreendimento de modernização de TI em larga escala.

Em 2022, o The Open Group atualizou a estrutura e lançou o TOGAF Standard, 10ª edição, que substitui a edição 9.2 anterior. A atualização torna a adoção mais fácil para as organizações implementarem as melhores práticas do TOGAF. O The Open Group afirma que a 10ª edição fornece eficiência aprimorada e navegação mais simples para implementar a estrutura, tornando-a mais acessível e amigável.

Os quatro domínios arquitetônicos do TOGAF

O processo ADM do TOGAF® foi projetado especificamente para acelerar o fluxo de trabalho em quatro domínios da arquitetura empresarial:

  1. Arquitetura de negócios
    Responsável por mapear os relacionamentos entre as hierarquias operacionais, políticas, capacidades e iniciativas de uma empresa.
  2. Arquitetura de aplicativos
    Responsável por definir aplicativos relevantes para lidar com dados da empresa e as maneiras de implementar e implantar esses aplicativos na infraestrutura geral.
  3. Arquitetura de dados
    Responsável por definir as regras e padrões para armazenar e integrar dados.
  4. Arquitetura técnica
    Define plataformas, serviços e todos os componentes tecnológicos circundantes para servir como referência para equipes de desenvolvimento.

O Modelo de Desenvolvimento de Arquitetura TOGAF (ADM)

A estrutura TOGAF não apenas descreve os principais componentes de uma Arquitetura Empresarial por meio de seus quatro Domínios Arquitetônicos, mas também fornece um roteiro claro sobre como criar essa arquitetura. Esse roteiro é conhecido como Método de Desenvolvimento de Arquitetura (ADM) e é um processo sequencial de nove fases. O ADM orienta as organizações no desenvolvimento de sua Arquitetura Empresarial e é descrito na Figura 1.

Open Group Architecture Framework (TOGAF) - Método de Desenvolvimento de Arquitetura

Figura 1: Método de desenvolvimento da arquitetura TOGAF ®

Ao longo dos nove estágios do processo TOGAF® ADM, esses quatro domínios arquitetônicos se tornam iterativamente desenvolvidos para criar uma arquitetura equilibrada capaz de garantir mudanças organizacionais. Um processo independente do setor, esse método tem como objetivo limitar a adivinhação e promover a maturidade em programas de arquitetura empresarial — tudo isso enquanto acumula repositórios arquitetônicos específicos da empresa para dar suporte a projetos futuros.

Quais são os desafios do TOGAF® em ambientes de TI modernos?

O TOGAF® está atualmente na versão 10, e com sua biblioteca em evolução de definições e simbologia vem a luta inevitável para se alinhar à estrutura de forma ágil. Muito disso se deve ao processo abrangente de revisão de conformidade arquitetônica do TOGAF®, uma lista de verificação envolvendo centenas de itens de categorias como gerenciamento de informações e sistemas; hardware e sistemas operacionais; serviços de software e middleware; aplicativos (especificações de negócios, infraestrutura e integração); e gerenciamento de informações.

No entanto, embora a conformidade seja um elemento indispensável da governança arquitetônica, aderir religiosamente aos padrões da estrutura é uma tarefa difícil para qualquer programa de arquitetura empresarial . Como tal, para organizações modernas que desejam manter eficientemente as melhores práticas do TOGAF®, é quase necessário obter a participação das partes interessadas em toda a organização para avaliar e catalogar eficientemente os projetos de TI.

Agile e TOGAF® são de fato capazes de coexistir, mas para que isso aconteça, caminhos colaborativos para padronizar entidades de TI entre equipes devem ser estabelecidos.

 

O que há de novo no TOGAF® 10?

10ª edição do TOGAF apresenta um novo formato modular que traz vários benefícios. O ramo Conteúdo Fundamental inclui todos os fundamentos da estrutura, tornando mais fácil para as empresas começarem a implementar e aprender o TOGAF. Esta parte da estrutura é a menos provável de mudar significativamente ao longo do tempo . A estrutura modular fornece aos arquitetos corporativos melhor orientação e um processo de navegação mais simples, permitindo que eles usem a estrutura de forma eficaz. A base de conhecimento e a orientação específica do tópico são separadas em partes formais da estrutura, tornando possíveis lançamentos frequentes de material adicional, preservando a estabilidade no conteúdo fundamental.

Além disso, a 10ª edição do TOGAF continua a aprimorar sua capacidade de dar suporte aos aspectos fundamentais da estratégia de negócios, tornando mais útil para os fornecedores fornecer novos recursos e serviços para segmentos de mercado especializados, ao mesmo tempo em que aderem a padrões abertos. A estrutura é projetada para se adaptar às necessidades de negócios em mudança e é um corpo vivo de conhecimento, permitindo que as organizações estabeleçam formas ágeis de trabalho que evoluem continuamente. A 10ª edição do TOGAF demonstra como a estrutura está evoluindo para fornecer valor em tempos de mudança.

Fundamentals of Software Architecture

Fundamentals of Software Architecture: An Engineering Approach

Preface: Invalidating Axioms

Axiom – A statement or proposition which is regarded as being established, accepted, or self-evidently true.

Software architects (like mathematicians) also build theories atop axioms (but the software world is softer than mathematics).

Architects have an important responsibility to question assumptions and axioms left over from previous eras. Each new era requires new practices, tools, measurements, patterns, and a host of other changes.

Chapter 1: Introduction

The industry does not have a good definition of software architecture.

Architecture is about the important stuff… whatever that is ~ Ralph Johnson

The responsibilities of a software architect encompass technical abilities, soft skills, operational awareness, and a host of others.

When studying architecture – keep in mind that everything can be understood in context – why certain decisions were made, was based on the realities of the environment (for example building microservice architecture in 2002 would be inconceivably expensive).

Knowledge of the architecture structure, architecture characteristics, architecture decisions, and design principles is needed to fully understand the architecture of the system.

  • structure/style: microservices, layered, microkernel, …
  • characteristics: availability, reliability, scalability, fault tolerance, security, …
  • decisions: what is and what is not allowed, rules for a system how it should be constructed
  • design principles: guidelines for constructing systems — leverage async messaging between services to increase performance

Expectations of an architect:

  • make architecture decisions
    • instead of making technical decisions (use React.js), instruct development teams (use a reactive-based framework)
  • continually analyze the architecture
    • validate decisions made years ago in order to prevent structural decay
  • keep current with the latest trends
    • the decisions an architect makes tend to be long-lasting and difficult to change. understanding and following key trends helps the architect prepare for the future
  • ensure compliance with decisions
    • continually verify that development teams are following the architecture decisions and design principles defined
  • diverse exposure and experience
    • an architect should be at least familiar with a variety of technologies, effective architect should be aggressive in seeking out opportunities to gain experience in multiple languages, platforms and technologies
  • have business domain knowledge
    • without business knowledge, an architect cannot communicate with stakeholders and business users and will quickly lose credibility
  • possess interpersonal skills
    • interpersonal skills, including teamwork, facilitation, and leadership
    • engineers love to solve technical problems, however G. Weinberg said: “no matter what they tell you, it is always a people problem”
    • many architects are excellent technologists, but are ineffective architects because of poor communication skills
  • understand and navigate politics
    • have negotiation skills, almost every decision an architect makes will be challenged

All architectures become iterative because of unknown unknowns. Agile just recognizes this and does it sooner.

Iterative process fits the nature of software architecture. Trying to build a modern system such as microservices using Waterfall will find a great deal of friction.

Nothing remain static. What we need is evolutionary architecture – mutate the solution, evolve new solutions iteratively. Adopting Agile engineering practices (continuous integration, automated machine provisioning, …) makes building resilient architectures easier.

Agile methodologies support changes better than planning-heavy processes because of tight feedback loop.

Laws of Software Architecture:

  • Everything in software architecture is a trade-off
  • If an architect thinks they have discovered something that isn’t a trade-off, more likely they just haven’t identified the trade-off yet
  • Why is more important than how

Chapter 2: Architectural thinking

4 main aspects of thinking like an architect:

  1. understanding the difference between architecture and design
    • architecture vs design
      • architecture: defining architecture characteristics, selecting architecture patterns, creating components
      • design: class diagrams, user interface, code testing and development
    • architects and development teams have to form strong bidirectional relationship, be on the same virtual team
    • where does architecture end and design begin? nowhere
    • architecture and design must be synchronized by tight collaboration
  2. wide breadth of technical knowledge
    • developer – significant amount of technical depth
      • specialised in languages, frameworks and tools
    • architect – significant amount of technical breadth
      • broad understanding of technology and how to use it to solve particular problems
  3. understanding, analyzing, and reconciling trade-offs between various solutions and technologies
    • thinking like an architect is all about seeing trade-offs in every solution
    • the ultimate answer for architectural questions: it depends on … (budget, business env, company culture, …)
    • look at the benefits of a given solution, but also analyze the negatives
    • analyze trade-offs and the ask, what is more important, this decision always depend on the environment
  4. understanding the importance of business drivers
    • business drivers are required for the success of the system
    • understanding the domain knowledge and ability to translate those requirements into architecture characteristics

Frozen Caveman Anti-Pattern: describes an architect who always reverts to their pet irrational concern for every architecture. This anti-pattern manifests in architects who have been burned in the past by a poor decision/unexpected occurrence, making them particularly cautious in the future.

How an architect can remain hands-on coding skills?

  • do frequent proof-of-concepts
  • whenever possible, write best production-quality code (even when doing POCs) — POC code often remains in the repository and becomes the reference or guiding example
  • tackle technical debt stories or architecture stories, freeing the development team up to work on the critical function user stories
  • work on bug fixes
  • create simple command-line tools and analyzers to help the development team with their day-to-day tasks
  • do code reviews frequently

Chapter 3: Modularity

Modularity is an organizing principle. If an architect designs a system without paying attention to how the pieces wire together, they end up creating a system that presents myriad difficulties.

Developers typically use modules as a way to group related code together. For discussions about architecture, we use modularity as a general term to denote a related grouping of code: classes, functions, or any other grouping.

Cohesion – refers to what extent the parts of a module should be contained within the same module. It is a measure of how related the parts are to one another.

Abstractness is the ratio of abstract artifacts to concrete artifacts. It represents a measure of abstractness versus implementation. A code base with no abstractions vs a code base with too many abstractions.

Chapter 4: Architecture Characteristics Defined

Architects may collaborate on defining the domain or business requirements, but one key responsibility entails defining, discovering, and analyzing all the things the software must do that isn’t directly related to the domain functionality — architectural characteristics.

Operational Architecture Characteristics:

  • Availability – how long the system will need to be available
  • Continuity – disaster recovery capability
  • Performance – stress testing, peak analysis
  • Recoverability – how quickly is the system required to be on-line again?
  • Reliability – if it fails, will it cost the company large sums of money?
  • Robustness – ability to handle error and boundary conditions while running
  • Scalability – ability for the system to perform and operate as the number of users/requests increases

Structural Architecture Characteristics

  • Configurability – ability for the end users to easily change aspects of the software’s configuration
  • Extensibility – how important it is to plug new pieces of functionality in
  • Installability – ease of system installation on all necessary platforms
  • Localization – support for the multiple languages, currencies, measures
  • Maintainability – how easy it is to apply changes and enhance the system?
  • Portability – does the system need to run on more than one platform?
  • Supportability – what level of technical support is needed by the application?
  • Upgradeability – ability to quickly upgrade from a previous version

Cross-cutting Architecture Characteristics

  • Accessibility – access to all users, including those with disabilities
  • Archivability – will the data need to be deleted/archived?
  • Authentication – security requirements to ensure users are who they say they are
  • Authorization – security requirements to ensure users can access only certain functions within application
  • Legal – what legislative constraints is the system operation in?
  • Privacy – ability to hide transactions from internal company employees
  • Security – does the data need to be encrypted in the database, what type of authentication is needed…?
  • Supportability – what level of technical support is needed by the application?
  • Usability – level of training required for users to achieve their goals with the app

Any list of architecture characteristics will be an incomplete list. Any software may invent important architectural characteristics based on unique factors. Many of the terms are imprecise and ambiguous. No complete list of standards exists.

Applications can support only a few of the architecture characteristics we have listed. Firstly, each of the supported characteristics requires design effort. Secondly, each architecture characteristic often has an impact on others. Architects rarely encounter the situation where they are able to design a system and maximize every single architecture characteristics.

Never shoot for the best architecture, but rather the least worst architecture.

Too many architecture characteristics lead to generic solutions that are trying to solve every business problem, and those architectures rarely work because the design becomes unwieldy. Architecture design should be as iterative as possible.

Chapter 5: Identifying Architectural Characteristics

Identifying the correct architectural characteristics for a given problem requires an architect to not only understand the domain problem, but also collaborate with the problem domain stakeholders to determine what is truly important from a domain perspective.

Extracting architecture characteristics from domain concerns: translate domain concerns to identify the right architectural characteristics. Do not design a generic architecture, focus on short list of characteristics. Too many characteristics leads to greater and greater complexity. Keep design simple. Instead of prioritizing characteristics, have the domain stakeholders select the top 3 most important characteristics from the final list.

Translation of domain concerns to architecture characteristics:

  • Mergers and acquisition -> Interoperability, scalability, adaptability, extensibility
  • Time to market -> Agility, testability, deployability
  • User satisfaction -> Performance, availability, fault tolerance, testability, deployability, agility, security
  • Competitive advantage -> Agility, testability, deployability, scalability, availability, fault tolerance
  • Time and budget -> Simplicity, feasibility

Extracting architecture characteristics from requirements: some characteristics come from explicit statements in requirements.

Architecture Katas – in order te become a great architect you need a practice. The Kata exercise provides architects with a problem stated in domain terms (description, users, requirements) and additional context. Small teams work 45 minutes on a design, then show results to the other groups, who vote on who came up with the best architecture. Team members ideally get feedback from the experienced architect abut missed trade-offs and alternative designs.

Explicit characteristics – appear in a requirements’ specification, e.g. support for particular number of users.

Implicit characteristics – characteristics aren’t specified in requirements documents, yet they make up an important aspect of the design, e.g. availability – making sure users can access the website, security – no one wants to create insecure software, …

Architects must remember: there is no best design in architecture, only a least worst collection of trade-offs.

Chapter 6: Measuring and Governing Architecture Characteristics

  • They aren’t physics – many characteristics have vague meanings, the industry has wildly differing perspectives
  • Wildly varying definitions – different people may disagree on the definition, without agreeing on a common definition, a proper conversation is difficult
  • Too composite – many characteristics compromise may others at a smaller scale

Operational measures: obvious direct measurements, like performance — measure response time. High-level teams don’t just establish hard performance numbers, they base their definitions on statistical analysis.

Structural measures: addressing critical aspects of code structure, like cyclomatic complexity – the measurement for code complexity, computed by applying graph theory to code.

Overly complex code represents a code smell. It hurts almost every of the desirable characteristics of code bases (modularity, testability, deployability, …). Yet if teams don’t keep an eye on gradually growing complexity, that complexity will dominate the code base.

Process measures: some characteristics intersect with software development processes. For example, agility can relate to the software development process, ease of deployment and testability requires some emphasis on good modularity and isolation at the architecture level.

Governing architecture characteristics – for example, ensuring software quality within an organization falls under the heading of architectural governance, because it falls within the scope of architecture, and negligence can lead to disastrous quality problems.

Architecture fitness function – any mechanism that provides an objective integrity assessment of some architecture characteristic or combination of architecture characteristics. Many tools may be used to implement fitness functions: metrics, monitors, unit tests, chaos engineering, …

Rather than a heavyweight governance mechanism, fittness functions provide a mechanism for architects to express important architectural principles and automatically verify them. Developer know that they shouldn’t release insecure code, but that priority competes with dozens or hundreds of other priorities for busy developers. Tools like the Security Monkey, and fitness functions generally, allow architects to codify important governance checks into the substrate of the architecture.

Chapter 7: Scope of Architecture Characteristics

When evaluating many operational architecture characteristics, an architect must consider dependent components outside the code base that will impact those characteristics.

Connascence – Two components are connascent is a change in one would require the other to be modified in order to maintain the overall correctness of the system.

If two services in a microservices architecture share the same class definition of some class, they are statically connascent. Dynamic connascence: synchronous – caller needs to wait for the response from the callee, asynchronous calls allow fire-and-forget semantics in event-driven architecture.

Component level coupling isn’t the only thing that binds software together. Many business concepts semantically bind parts of the system together, creating functional cohesion.

Architecture quantum – an independently deployable artifact with high functional cohesion and synchronous connascence.

  • independently deployable – all necessary components to function independently from other parts of the architecture ( e.g. a database – the system will not function without it)
  • high functional cohesion – how well the contained code is unified in purpose, meaning – an architecture quantum needs to do something purposeful
  • synchronous connascence – synchronous call within an application context of between distributed services that form this architecture quantum.

Chapter 8: Component-Based Thinking

Architects typically think in terms of components, the physical manifestation of a module. Typically, the architect defines, refines, manages, and governs components within an architecture.

Architecture Partitioning – several styles exist, with different sets of trade-offs (layered architecture, modular monolith).

Convay’s Law: Organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations.

This law suggests that when a group of people deigns some technical artifact, the communication structures between the people end up replicated in the design.

Technical partitioning – organizing components by technical capabilities (presentation, business rules, persistence).

Domain partitioning – modeling by identifying domains/workflows independent and decouples from another. Microservices are based on this philosophy.

Developer should never take components designed by architects as the last words. All software design benefits from iteration. Initial design should be viewed as a first draft.

Component identification flow:

  • identify initial components
  • assign requirements to components
  • analyze roles and responsibilities
  • analyze architecture characteristics
  • restructure components

Finding proper granularity for components is one of most difficult tasks. Too fine-grained design leads to too much communication between components, too coarse-grained encourage high internal coupling.

Discovering components:

  • entity trap – anti-pattern when an architect incorrectly identifies the database relationships, this anti-pattern indicates lack of thought about the actual workflows of the application.
  • actor-actions approach – a popular way to map requirements to components, identify actors who perform activities with the application and the actions those actors may perform.
  • event storming – the architect assumes the project will use messages and/or events to communicate between components, the team tries to determine which events occur in the system based on requirements and identified roles, and build components around those event and message handlers.
  • workflow approach – identifies the key roles, the kinds of workflows, and builds components around the identified activities

Monolithic vs Distributed Architecture:

  • monolithic: a single deployable unit, all functionality of the system that runs in the process, typically connected to a single database
  • distributed: multiple services running in their onw ecosystem, communicating via network, each service can may have its own release cadence and engineering practices

Chapter 9: Foundations

Architecture styles (a.k.a. architecture patterns) – describe a named relationship of components covering a variety of architecture characteristics. Style name, similar to design patterns, creates a single name that acts as shorthand between experienced architects.

Big Ball of Mud – the absence of any discernible architecture structure. The lack of structure makes change increasingly difficult. Problematic testing, deployment, scalability, performance, … Mess because of lack of governance around code quality and structure.

Client/Server – separation of responsibilities – backend-frontend/two-tier/client-server.

Architecture styles can be classified into 2 main types:

  • monolithic – single deployment of unit code
    • layered, pipeline, microkernel
  • distributed – multiple deployment units connected through network
    • service-based, event-driven, space-based, service-oriented, microservices
    • much more powerful in terms of performance, scalability, and availability, but there are trade-offs

The Fallacies of Distributed Computing:

  1. The Network is Reliable – fact: networks still remain generally unreliable, this is why things like timeouts and circuit breakers exist between services. The more a system relies on the network, the potentially less reliable it becomes.
  2. Latency is Zero – local call is measured in nanoseconds/microseconds, the same call made through a remote access protocol is measured in milliseconds. Do you know what the average round-trip latency is for a RESTful call in your prod env?
  3. Bandwidth is Infinite – communication between remote services significantly utilizes bandwidth causing networks to slow down. Imagine 2000 req/s, 500 kb each = 1 Gb! Ensuring that the minimal amount of data is passed between services in a distributed architecture is the best way to address this fallacy.
  4. The Network is Secure – the surface area for threats and attacks increases by magnitudes when moving from a monolithic to a distributed architecture, despite measures like VPNs, trusted networks and firewalls.
  5. The Topology Never Changes – network topology (routers, hubs, switches, firewalls, networks, appliances) CAN change, architects must be in constant communication with operations and network administrators to know what is changing and when so they can make adjustments.
  6. There is Only One Administrator – this fallacy points to the complexity of distributed architecture and the amount of coordination that must happen to get everything working correctly. Monoliths do not require this level of communication and collaboration due to the single deployment unit characteristics.
  7. Transport Cost is Zero – transport cost does not refer to latency, but rather to actual cost in terms of money associated with making a simple RESTful call. Distributed architectures cost significantly more than monolithic architectures, primarily due to increased needs for additional hardware, servers, gateways, firewalls, subnets, proxies, …
  8. The Network is Homogenous – notwork is not made up by one network hardware vendor, not all of this heterogeneous hardware vendors play well together.

Other distributed considerations:

  • distributed logging – debugging in a distributed architecture is very difficult and time-consuming, logging consolidation tools may help.
  • distributed transactions – in a monolith it is super easy to perform commit/rollback, it is much more difficult todo the same in a distributed system. Distributed systems rely on eventual consistency – this is one of the trade-offs. Transactional SAGAs are one way to manage distributed transactions.
  • contract maintenance and versioning – a contract is behaviour and data that is agreed upon by both the client and service, maintenance is hard due to decoupled services owned by different teams and departments.

Chapter 10: Layered Architecture Style

The Layered Architecture (n-tiered) – standard for most applications, because of simplicity, familiarity, and low cost. The style also falls into several architectural anti-patterns (architecture by implication, accidental architecture).

Most layered architectures consist of 4 standard layers: presentation, business, persistence, and database.

The layered architecture is a technically partitioned architecture (as opposed to domain-partitioned architecture). Groups of components, rather than being grouped by domain, are grouped by their technical role in the architecture. As a result, any particular business domain is spread throughout all of the layers of the architecture. A domain-driven design does not work well with the layered architecture style.

Each layer can be either closed or open.

  • closed – a request moves top-down from layer to layer, the request cannot skip any layers
  • open – the request can bypass layers (fast-lane reader pattern)

The layers of isolation – changes made in one layer of the architecture generally don’t impact/affect components in other layers. Each layer is independent of the other layers, thereby having little or no knowledge of the inner workings of other layers in the architecture. Violation of this concept produces very tightly coupled application with layer interdependencies between components This type of architecture becomes very brittle, difficult and expensive to change.

This architecture makes for a good starting point for most applications whe it is not known yet exactly which architecture will ultimately be used. Be sure to keep reuse at minimum and keep object hierarchies. A good level of modularity will help facilitate the move to another architecture style later on.

Watch out for the architecture sinkhole anti-pattern – this anti-pattern occurs when requests move from one layer to another as simple pass-through processing with no business logic performed within each layer. For example, the presentation layer responds to a simple request from the user to retrieve basic costumer data.

Chapter 11: Pipeline Architecture Style

Pipeline (a.k.a. pipes, filters) architecture: Filter -(Pipe)-> Filter -(Pipe)-> Filter -(Pipe)-> Filter

  • pipes – for the communication channel between filters, each pipe is usually unidirectional and point-to-point.
  • filters – self-contained, independent from other filters, stateless, should perform one task only. 4 types of filters exist within this architecture style
    • producer – the starting point of a proces, sometimes called the source
    • transformer – accepts input, optionally performs a transformation on data, then forwards it to the outbound pipe, also known as “map”
    • tester – accepts inout, tests criteria, then optionally produces output, also known as “reduce”
    • consumer – the termination point for the pipeline flow, persist or display the final result

ETL tools leverage the pipeline architecture for the flow and modification of data from one database to another.

Chapter 12: Microkernel Architecture Style

The microkernel architecture style (a.k.a plug-in) – a relatively simple monolithic architecture consisting of two components: a core system and plug-in components.

Core system – the minimal functionality required to run the system. Depending on the size and complexity, the core system can be implemented as a layered architecture or modular monolith.

Plug-in components – standalone, independent components that contain specialized processing, additional features, and custom code meant to enhance or extend the core system. Additionally, they can be used to isolate highly volatile code, creating better maintainability and testability within the application. Plug-in components should have no-dependencies between them.

Plug-in components do not always have to be point-to-point communication with the core system (REST or messaging can be used instead). Each plug-in can be a standalone service (or even microservice) – this topology is still only a single architecture quantum due to monolithic core system.

Plug-in Registry – the core system needs to know about which plug-in modules are available and gow to get them. The registry contains information about each plug-in (name, data, contract, remote access protocol). The registry can be as simple as an internal map structure owned by the core system, or as complex as a registry and discovery tool (like ZooKeeper or Consul).

Examples of usages: Eclipse IDE, JIRA, Jenkins, Internet web browsers, …

Problems that require different configurations for each location or client match extremely well with this architecture style. Another example is a product that places a strong emphasis on user customization and feature extensibility.

Chapter 13: Service-Based Architecture Style

A hybrid of the microservices, one of the most pragmatic architecture styles (flexible, simpler and cheaper than microservices/even-driven services).

Topology: a distributed macro layered structure consisting of a separately deployed user interface, separately deployed coarse-grained services (domain services) and a monolithic database. Because the services typically share a single monolithic database, the number of services within an application context range between 4 and 12.

Base on scalability, fault tolerance, and throughput – multiple instances of a domain service can exist. Multiple instances require some load-balancing.

Many variants exist within the service-based architecture:

  • single monolithic user interface
  • domain-based user interface
  • service-based user interface

Similarly, you can break apart a single monolithic database, going as far as domain-scoped databases.

Service-based architecture uses a centrally shared database. Because of small number of services, database connections are not usually an issue. Database changes, can be an issue. If not done properly, a table schema change can impact every service, making database changes very costly task in terms of effort and coordination.

One way to mitigate the impact and risk of database changes is to logically partition the database and manifest the logical partitioning through federated shared libraries. Changes to a table within a particular logical domain, impacts only those services using that shared library.

When making changes to shared tables, lock the common entity objects and restrict change access to only the database team. This helps control change and emphasizes the significance of changes to the common tables used by all services.

Service based architecture – one of the most pragmatic architecture styles, natural fit when doing DDD, preserves ACID better than any other distributed architecture, good level of architectural modularity.

Chapter 14: Event-Driven Architecture Style

A popular distributed asynchronous architecture style used to produce highly scalable and high-performance apps. It can be used for small applications as well as large, complex ones. Made up of decoupled event processing components that asynchronously receive and process events. It can be used as a standalone style or embedded within other architecture style (e.g. event-driven microservices architecture).

2 primary topologies:

  • the mediator topology – used when you require control over the workflow of an event process
    • an event mediator – manages and controls the workflow for initiating events that require the coordination of multiple event processors, usually there are multiple mediators (associated with a particular domain)
    • if an error occurs (no acknowledgement from on eof event processors), the mediator can take corrective action to fix the problem
    • the mediator controls the workflow, it can maintain the event state and manage errors
    • operates on commands (send-email, fulfill-order), rather than on events (email-sent, order-fulfilled)
    • cons: not as highly decoupled as the broker topology, lower scalability, hard to model complex workflows
  • the broker topology – used when you require a high level of responsiveness
    • no central event mediator
    • message flow is distributed across the event processor components in a chain-like broadcasting fashion
    • a good practice: for each event processor advertise what it did to the rest of the system, regardless of whether any other event processor cares about what that action was
    • operates on events (email-sent, order-fulfilled), rather than on commands (send-email, fulfill-order)
    • cons: challenging error handling – no central monitoring/controlling, not possible to restart a business transaction (because actions are taken asynchronously)

ERROR HANDLING: the workflow event pattern – leverages delegation, containment, and repair through the use of a workflow delegate. On error, the event consumer immediately delegates the error to the workflow processor and moves on. The workflow processor tries to figure out what is wrong with the message (rules, machine learning, …), once the message is repaired it can be sent back to the event processor. In case a very problematic error a human agent can determine what is wrong with the message and then re-submit.

Data loss (lost messages) – a primary concern when dealing with asynchronous communication. Typical data-loss scenarios:

  • the message never makes it to the queue or the broker goes does before the event processor can can retrieve the message
    • solution: leverage persistent message queues (guaranteed delivery), message persisted in the broker’s database ( not only in the memory)
  • event processor de-queues message and crashes before it can process the message
    • solution: client acknowledge mode – message is not deleted from the broker immediately, but waits for acknowledgement
  • event processor is unable to persist the message in the database
    • solution: leverage ACID transactions

Broadcast – the capability to broadcast events without knowledge of who is receiving the message and what they do with it. Broadcasting is perhaps the highest level of decoupling between event processors.

In event-driven architecture, synchronous communication is accomplished through request-reply messaging. Each event channel within request-reply messaging has 2 queues (request + reply queue). 2 primary techniques for implementing request-reply messaging:

  1. [PREFERRED] Correlation ID – a field in the reply message usually set to the request message ID.
  2. Temporary queue – dedicated for the specific request, created when the request is made, and deleted when the request ends. Does not require Correlation ID. Large message volumes can significantly slow down the message broker and impact performance and responsiveness.
  • Request-Based – for well-structured, data-driven requests (e.g. retrieving customer profile data).
  • Event-Based – for flexible, action-based events that require high level of responsiveness and scale, with complex and dynamic processing.

Chapter 15: Space-Driven Architecture Style

In any high-volume application with a large concurrent load, the database will become a bottleneck, regardless of used caching technologies.

The space-based architecture style is specifically designed to address problems involving high scalability, elasticity, and high concurrency issues.

Tuple space – the technique of using multiple parallel processors communicating through shared memory.

High scalability, elasticity, and performance are achieved by removing the central database and leveraging replicated in-memory data grids. Application data is kept in memory and replicated among all active processing units.

Several architecture components that make up a space-based architecture:

  • processing unit: containing the application code
    • single or multiple processing units
    • contains in-memory data grid and replication engine usually implemented using: Hazelcast, Apache Ignite, Oracle Coherence
  • virtualized middleware: used to manage and coordinate the processing units
    • handles the infrastructure concerns (data sync, request handling)
    • made of:
      • messaging grid – manages input request and session state, determines which active processing components are available to receive the requests and forwards to one of those processing units (usually implemented using HA Proxy and Nginx)
      • data grid – implemented within the processing units as a replicated cache
      • processing grid – (optional component) manages orchestrated request processing when there are multiple processing units involved in a single business request
      • deployment manager – monitors response times and user loads, starts up new processing units when load increases, and shuts down when the load decreases
  • data pumps: used to synchronously send updated data to the database
    • is a way of sending data to another processor which then updates data in a database
    • always asynchronous, provide eventual consistency
    • when a processing unit receives a request and updates its cache, that processing unit becomes the owner of teh update and is responsible for sending that update through the data pump so that the database can be updated eventually
    • implemented using messaging; messages usually contain the new data values (diff)
  • data writers: used to perform the updates from the data pumps
    • accept messages from a data pump and updates the database with the information contained in the message
  • data readers: used to read database data and deliver it to processing units upon startup
    • responsible for reading data from the database and sending it to the processing units via reverse data pump
    • invoked in one of 3 situations:
      • a crash of all processing unit instances of the same named cache
      • a redeployment of all processing units within the same named cache
      • retrieving archive data not contained in the replicated cache

Data collision – occurs when data is updated in one cache instance A, and during replication to another cache instance B, the same data is updated by that cache B.The local update to B will be overridden by the old data from cache A, cache A will be overridden by cache B. Data Collision Rate factors: latency, number of instances, cache size.

Distributed cache – better data consistency. Replicated cache – better performance and fault tolerance.

Example usages of space-based architecture: well suited for applications that experience high spikes in user or request volume and apps that have throughput excess of 10k concurrent users – online concert ticketing systems, online auction systems.

Chapter 16: Orchestration-Driven Service-Oriented Architecture

This type appeared in the late 1990s when companies were becoming enterprises and architects were forced to reuse as much as possible because of expensive software licenses (no open source alternatives).

Reuse – the dominant philosophy in this architecture.

  • Business Services – sit at the top of this architecture and provide the entry point. No code, just input, output and schema information.
  • Enterprise Services – fine-grained, shared implementations – atomic behaviors around particular business domain – CreateCustomer, CalculateQuote, … – collection of reusable assets – unfortunately, the dynamic nature of reality defies these attempts.
  • Application Services – not all services in the architecture require the same level of granularity, these are one-off, single-implementation services, for example an application a company doesn’t want to take the time to make a reusable service.
  • Infrastructure Services – supply the operational concerns – monitoring, logging, auth.
  • Orchestration Engine – the heart of this architecture, defines the relationship between the business and enterprise services, how they map together, and where transaction boundaries lie. It also acts as an integration hub, allowing architects to integrate custom code with package and legacy software systems.

This architecture in practice was mostly a disaster.

When a team builds a system primarily around reuse, they also incur a huge amount of coupling between components. Each change had a potential huge ripple effect. That in turn led to the need for coordinated deployments, holistic testing and other drags on engineering efficiency.

This architecture manages to find the disadvantages of both monolithic and distributed architectures!

Chapter 17: Microservices Architecture

There is no secret group of architects who decide what the next big movement will be. Rather, it turns out that many architects end up making common decisions.

Microservices differ in this regard – it was popularized by a famous blog entry by Martin Fowled and James Lewis.

Microservices Architecture is heavily inspired by the ideas in DDD – bounded context, decidedly inspired microservices. Within a bounded context, the internal parts (code, data schemas) are coupled together to produce work, but they are never coupled to anything outside the bounded context.

Each service is expected to include all necessary parts to operate independently.

Performance is often the negative side effect of the distributed nature of microservices. Network calls take much longer than method calls. It is advised to avoid transactions across service boundaries, making determining the granularity the key to success in this architecture.

It is hard to define the right granularity for services in microservices. If there are too many services, a lot of communication will be required to perform work. The purpose of service boundaries is to capture a domain or workflow.

Guidelines to find the appropriate boundaries:

  • purpose – a domain, one significant behaviour on behalf of the overall application
  • transactions – often the entities that need to cooperate in a transaction show a good service boundary
  • choreography – if excellent domain isolation require extensive communication, you may consider merging services back into larger service to avoid communication overhead

Microservices Architecture tries to avoid all kinds of coupling – including shared schemas and databases used as integration points.

Once a team has built several microservices, they realize that each has common elements that benefit from similarity. The shared sidecar can be either owned by individual teams or a shared infrastructure team. Once teams know that each service includes a common sidecar, they can build a service mesh – allowing unified control across the infrastructure concerns like logging and monitoring.

2 styles of user interfaces:

  • monolithic user interface – a single UI that calls through the API layer to satisfy user request
  • micro-frontends – each service emits the UI for that service, which the frontend coordinates with the other emitted UI components

Microservices architectures typically utilize protocol-aware heterogeneous interoperability:

  • protocol-aware – each service should know how to call other services
  • heterogeneous – each service may be written in a different technology stack, heterogeneous means that microservices fully support polyglot environments
  • interoperability – describes services calling one another, while architects in microservices try to discourage transactional calls, services commonly call other services via the network to collaborate

For asynchronous communication, architects often use events and messages (internally utilizing an event-driven architecture).

The broker and mediator patterns manifest as choreography and orchestration:

  • choreography – no central coordinator exists in this architecture
  • orchestration – coordinating calls across several services

Building transactions across service boundaries violates the core decoupling principle of the microservices architecture. DON’T.

Don’t do transactions in microservices – fix granularity instead.

Exceptions always exist (e.g. 2 different services need vastly different architecture characteristics -> different boundaries), in such situations – patterns exist to handle transaction orchestration (with serious trade-offs).

SAGA – the mediator calls each part of the transaction, records success/failure, and coordinates results. In case of an error, the mediator must ensure that no part of the transaction succeeds if one part fails (e.g. send a request to undo

  • usually very complex). Typically, implemented by having each request in a pending state.

A few transactions across services is sometimes necessary; if it is the dominant feature of the architecture, mistakes were made!

Performance is often an issue in microservices – many network calls, which has high performance overhead. Many patterns exist to increase performance (data caching and replication).

However, one of the most scalable systems yet have utilized this style to great success, thanks to scalability, elasticity and evolutionary.

Additional references on microservices:

  • Building Microservices
  • Microservices vs. Service-Oriented Architecture
  • Microservices AntiPatterns

Chapter 18: Choosing the Appropriate Architecture Style

Choosing an architecture style represents the culmination of analysis and thought about trade-offs for architecture characteristics, domain considerations, strategic goals, and a host of other things.

Preferred architecture shift over time, driven by:

  • observations from the past – rely on experience and observations
  • changes in the ecosystem – constant change is a reliable feature of the software development
  • new capabilities – architects must keep an eye open to not only new tools but new paradigms
  • acceleration – new tools create new engineering practices, which lead to new design and capabilities
  • domain changes – the business continues to evolve
  • technology changes – as technology evolves, organizations have to keep up with at least some of these changes
  • external factors – external factors may force a migration to another option

When choosing an architectural style, an architect must take into account all the various factors that contribute to the structure for the domain design. Architects should go into the decision comfortable with the following things:

  • the domain – good general understanding of the major aspects of the domain
  • architecture characteristics that impact structure – architect must discover and elucidate the architecture characteristics
  • data architecture – architects and DBAs must collaborate on database, schema and other DB-related concerns
  • organizational factors – external factors may influence design – cost, company’s plans, …
  • knowledge of process, trams, and operational concerns – software development process, interaction with operations and the QA influence a design
  • domain/architecture isomorphism – some problem domains match the topology of the architecture

Several determinations:

  • monolith vs distributed
  • where should data live
  • synchronous or asynchronous communication between services

General tip:

Use synchronous by default, asynchronous when necessary

Chapter 19: Architecture Decisions

Making architecture decisions involves gathering enough relevant information, justifying the decision, documenting the decision, and effectively communicating the decision to the right stakeholders.

Decision anti-patterns:

  • covering your assets – occurs when an architect avoids/defers making architecture decisions out of fear of making the wrong choice, 2 ways to overcome:
    • wait until you have enough information to justify and validate your decision, but waiting too long holds up development teams
    • continually collaborate with development teams to ensure that the decision can be implemented as expected, quickly respond to change
  • groundhog day – when people don’t know why a decision was made, so it keeps getting discussed over and over, architect failed to provide a justification for the decision (technical and business justifications)
  • email-driven architecture – where people lose, forget, or don’t even know an architecture decision has been made and therefore cannot implement that decision, notify impacted people directly in order to avoid this anti-pattern

Architecturally significant decisions are those decisions that affect [OR]:

  • the structure – impacts the patterns/styles of architecture being used
  • nonfunctional characteristics – architecture characteristics (performance, scalability, …)
  • dependencies – coupling points between components/services within the system
  • interfaces – how services and components are accessed and orchestrated
  • construction techniques – platforms, frameworks, tools, processes

Architecture Decision Records – ADRs – short text file describing a specific architecture decision. 5 main sections:

  • title – numbered sequentially and contains short phrase describing the architecture decisions
  • status – one of: proposed (must be approved-by a higher-level decision maker), accepted (approved & ready for implementation), suspended (decision changed and superseded by another ADR)
  • context – what situation forces me to make this decision, this section also provides a way to document the architecture (clear & concise)
  • decision – the architecture decision, along with full justification for the decision, advised to use following voice: we will do, we will use, … — this section allows an architect to place more emphasis on why rather than how. Understanding why a decision was made is far more important than understanding how something works.
  • consequences – the overall impact of an architecture decision, this section forces the architect to think about whether those impacts outweigh the benefits of the decision. Another good use is to document the trade-offs’ analysis.
  • [additional] compliance – how the architecture decision will be measured and governed from a compliance perspective
  • [additional] notes – various metadata — author, approval date, approved by, superseded date, last modified date, …

Authors’ recommendation — store ADRs in a wiki, rather than on Git.

ADRs can be used as an effective means to document a software architecture.

Chapter 20: Analyzing Architecture Risk

Every architecture has risk associated with it — risk involving availability, scalability, data integrity, … — by identifying risks, the architect can address deficiencies and take corrective actions.

The Architecture Risk Matrix – 2D array — the overall impact and the likelihood, each dimension has 3 ratings (low, medium, high). When leveraging the risk matrix to qualify the risk, consider the impact dimension first and the likelihood dimension second.

Risk Assessment – a summarized report of the overall risk of an architecture (the risk matrix can be used to build it).

Risk Storming – a collaborative exercise used to determine architectural risk within a specific dimension (area of risk) — unproven technology, performance, scalability, availability, data loss, single points of failure, security. Risk storming is broken down into 3 primary activities:

  1. Identification – each participant individually identifies areas of risk within the architecture, should involve analyzing only one particular dimension
  2. Consensus – highly collaborative activity with the goal of gaining consensus among all participants
  3. Mitigation – involves changes or enhancements to certain areas of the architecture

Risk storming can be used for other aspects of software development — for example story grooming — story risk, the likelihood that the story will not be completed.

Chapter 21: Diagramming and Presenting Architecture

Effective communication becomes critical to an architect’s success. No matter how brilliant an architect’s ideas are, if they can’t convince managers to fund them and developers to build them.

Diagramming and presenting are 2 critical soft skills for architects.

Irrational Artifact Attachment – is the proportional relationship between a person’s attachment to some artifact and how long it took to produce.If you spend a lot of time on something , you may have an irrational attachment to that artifact (proportional to the time invested). Use Agile approach in order to avoid this anti-pattern – create just-in-time artifacts, use simple tools to create diagrams.

Baseline features of a diagram tool:

  • layers – used to link a group of items together logically to enable hiding/showing individual layers. An architect can build a diagram where they can hide overwhelming details or to incrementally build pictures for presentations
  • stencils/templates – allow to build up a library of common virtual components (basic shapes with a special meaning, e.g. microservice stencil)
  • magnets – assistance in drawing lines

Diagram Guidelines:

  • Titles – all elements of the diagram should have title or are well known to the audience
  • Lines – should be thick enough to be seen, if lines indicate information flow use arrows
    • solid lines = synchronous communication
    • dotted lines = asynchronous communication
  • Shapes – each architect tends to make their own standard set of shapes, hint: use 3D boxes to indicate deployable artifacts and rectangles to indicate containership
  • Labels – label each item in a diagram, especially if there is a chance of ambiguity for the readers
  • Color – use colors when it helps to distinguish one artifact from the other
  • Keys – if shapes are ambiguous, include a key on the diagram clearly indicating what each shape represents

Book recommendation: Presentation Patterns

When preparing a presentation – use different type of transition when changing a topic, use the same transition within a topic.

When presenting, the presenter has 2 presentation channels: verbal and visual. By placing too much text on the slides and then saying the same words, the presenter is overloading one information channel and starving the other.

Using animations and transitions in conjunction with incremental builds (reveal information gradually) allows the presenter to make more compelling, entertaining presentations.

Info-decks – slide decks that are not meant to be projected but rather summarize information graphically, essentially using a presentation tool as a desktop publishing machine. They contain all the information, are meant to be standalone, no need for presenter.

Invisibility – a pattern where the presenter inserts a blank slide within a presentation to refocus attention solely on the speaker (turn of one visual channel).

Chapter 22: Making Teams Effective

A software architect is also responsible for guiding the development team through the implementation of the architecture.

Software architect should create and communicate constraints, or the box, in which developers can implement the architecture. Tight boundaries = frustration, loose boundaries = confusion, appropriate boundaries = effective teams.

3 basic types of architect personalities:

  • a control freak:
    • controls every detailed aspect of the software development process
    • too fine-grained and too low-level decisions
    • may restrict the development team to use specific technology, library, naming convention, class design
    • steals art of programming away from the developers
  • an armchair architect:
    • hasn’t coded in a very long time and does not take the implementation details into account
    • creates loose boundaries, in this scenario, development teams end up taking the role of architect, doing the work an architect is supposed to be doing
    • in order to avoid such behaviour, an architect should be involved in the technology being used on the project
  • an effective architect:
    • produces the appropriate constraints and boundaries, ensures that the team members are working well together and have the right level of guidance on the team
    • requires working closely and collaborating with the team, and gaining respect of the team as well

Elastic Leadership – https://www.elasticleadership.com — knowing how much control to exert on a given development team, factors to determine how many teams a software architect can manage at once:

  • team familiarity – the better team members know each other, the less control is needed because team members start to become self-organizing, the newer the team members, the more control needed to help facilitate collaboration among team members and reduce cliques within the team
  • team size – the larger the team, the more control is needed, the smaller the team, less control is needed
  • overall experience – teams with more junior developers require more control and mentoring whereas teams with more senior developers require less control
  • project complexity – highly complex projects require the architect to be more available to the team and to assist with issues that arise, hence more control is needed on the team
  • project duration – the shorter the duration, the lass control is needed, the longer the project, the more control is needed

3 factors when considering the most effective team size:

  • process loss – (Brook’s law) the more people you add to a project, the more ime the project will take, example: unable to parallelize work, merge conflicts
  • pluralistic ignorance – when everyone agrees to a norm because they think they are missing something obvious, rather than speaking up, a person chooses to follow the group (similar to “The Emperor’s New Clothes” — the king is naked), an architect should observe body language of all team members and ask each person what they think about the proposed solution
  • diffusion of responsibility – as team size increases, it has a negative impact on communication

An effective architect not only helps guide the development team through the implementation of the architecture, but also ensures that the team is healthy, happy, and working together to achieve a common goal.

Checklists work and provide an excellent vehicle for making sure everything is covered and addressed. The key to making teams effective is knowing when to leverage checklists and when not to. Most effective checklists:

  • code completion checklist – if everything in the checklist is completed, then the developer can claim they are actually done with the code
  • unit and functional testing checklist – contains some of the more unusual and edge-case tests that software developers tend to forget to test
  • software release checklist – releasing software is perhaps one of the most error-prone aspects of the software development life cycle, it helps avoid failed builds, deployments, and it significantly reduces the amount of rish associated with releasing software

Many items from the checklists can be automated.

Don’t worry about stating the obvious in a checklist. It’s the obvious stuff that’s usually skipped or missed.

Chapter 23: Negotiation and Leadership Skills

Negotiation is one of the most important skills a software architect can have. Effective software architects understand the politics of the organization, have strong negotiation and facilitation skills, and can overcome disagreements when they occur to create solutions that all stakeholders agree on.

“We must have zero downtime”, “I need these features yesterday”, …:

Leverage the use of grammar and buzzwords to better understand the situation

Enter the negotiation wit as many arguments as possible:

Gather as much information as possible before entering into a negotiation

Save this negotiation tactic for last:

When all else fails, state things in terms of cost and time

Does entire system require 99.999% availability or just some parts?:

Leverage the “divide and conquer” rule to qualify demands or requirements

Demonstrate your point with a real-life example:

Always remember that demonstration defeats discussion

Avoid being too argumentative or letting things get too personal in a negotiation — calm leadership combined with clear and concise reasoning will always win a negotiation

Ivory Tower architecture anti-pattern – Ivory tower architects are ones who simply dictate from on high, telling development teams what to do without regard to their opinion or concerns. This usually leads to a loss of respect for the architect and an eventual breakdown of the team dynamics.

When convincing developers to adopt an architecture decision or to do a specific task, provide a justification rather than “dictating from on high”

By providing a reason why something needs to be done, developers will more likely agree with the request. Most of the time, once a person hears something they disagree with, they stop listening. By stating the reason first, the architect is sure that the justification will be heard.

If a developer disagrees with a decision, have them arrive at the solution on their own

Win-win situation: the developer either fail trying and the architect automatically gets buy-in agreement for the architect’s decision or the developer finds a better way to address concerns.

Accidental complexity – we have made a problem hard, architects sometimes do this to prove their worth when things seem too simple or to guarantee that they are always kept in the loop on discussions and decisions. Introducing accidental complexity into something that is not complex is one of the best ways to become an ineffective leader as an architect. An effective way of avoiding accidental complexity is what we call the 4C’s of architecture:

  • communication
  • collaboration
  • clarity
  • conciseness

Be pragmatic, yet visionary. Visionary – Thinking about or planning the future with imagination or wisdom. Pragmatic – Dealing with things sensibly and realistically in a way that is based on practical rather than theoretical considerations.

Bad software architects leverage their title to get people to do what they want from them to do. Effective software architects get people to do things by not leveraging their title as architect, but rather by leading through example, not title. Lead by example, not by title.

To lead a team and become an effective leader, a software architect should try to become the go-to person on the team – the person developers go to for their questions and problems. Another technique to start gaining respect as a leader and become the go-to person on the team is to host periodic brown-bag lunches to talk about specific technique or technology.

Too many meetings? Ask for the meeting agenda ahead of time to help quantify if you are really needed at the meeting or not.

Meetings should be either first thing in the morning, right after lunch, or toward the end of the day, but not during the day when most developers experience flow state.

The most important single ingredient is the formula of success is knowing how to get along with people ~ Theodore Roosevelt

Chapter 24: Developing a Career Path

An architect must continue to learn throughout their career. Technology breadth is more important to architects than depth.

The 20-Minute Rule – devote at least 20 minutes a day to your career as an architect by learning something new or diving deeper into a specific topic. Spend min. 20 minutes to Google some unfamiliar buzzwords.

Technology Radar: https://www.thoughtworks.com/radar

You can create your won personal technology radar. It helps to formalize thinking about technology and balance opposing decision criteria.

Architects should choose some technologies and/or skills that are widely in demand and track that demand. But they might also want to try some technology gambits, like open source or mobile development.

Architects can utilize social media to enhance their technical breadth. Using media like Twitter professionally, architects should find technologists whose advice they respect. This allows to build a network on new, interesting technologies to assess and keep up with the rapid changes in the technology world.

Self-Assessment Questions

Chapter 1: Introduction

  1. What are the 4 dimensions that define software architecture?

Knowledge of the architecture structure, architecture characteristics, architecture decisions, and design principles.

  1. What is the difference between an architecture decision and a design principle?

Decisions: what is and what is not allowed, rules for a system how it should be constructed. Design principles: guidelines for constructing systems.

  1. List the eight core expectations of a software architect.

Make architecture decisions. Continually analyze the architecture. Keep current with the latest trends. Ensure compliance with decisions. Diverse exposure and experience. Have business domain knowledge. Posses interpersonal skills. Understand and navigate politics.

  1. What is the First Law of Software Architecture.

Everything in software architecture is a trade-off.

Chapter 2: Architectural thinking

  1. Describe the traditional approach of architecture versus development and explain why that approach no longer works.

In a traditional model the architect is disconnected from the development teams, and as such the architecture rarely provides what it was originally set out to do. Architect defines architecture characteristics, selects architecture patterns and styles, then these artifacts are handed off to the development teams.

Boundaries between architects and developers must be broken down. Unlike the old-school waterfall approaches to static and rigid software architecture, the architecture of today’s systems changes and evolves every iteration. A tight collaboration is essential for the success.

  1. List the three levels of knowledge in the knowledge triangle and provide an example of each.

Stuff you know: Python

Stuff you know you don’t know: Deep Learning

Stuff you don’t know you don’t know: 🤷‍

  1. Why is it more important for an architect to focus on technical breadth rather than technical depth?

Architects must make decisions that match capabilities to technical constraints, a broad understanding of a wide variety of solutions is valuable.

  1. What are some of the ways of maintaining your technical depth and remaining hands-on as an architect?
  • do frequent proof-of-concepts
  • whenever possible, write best production-quality code (even when doing POCs) — POC code often remains in the repository and becomes the reference or guiding example
  • tackle technical debt stories or architecture stories, freeing the development team up to work on the critical function user stories
  • work on bug fixes
  • create simple command-line tools and analyzers to help the development team with their day-to-day tasks
  • do code reviews frequently

Chapter 3: Modularity

  1. What is meant by the term connascence?

Two components mare connascent if a change in one would require the other to be modified in order to maintain teh overall correctness of the system.

Connascence allows us to go beyond the binary of “coupled” and “not coupled”, serving as a tool to measure coupling and describe how bad it is under different levels and kinds.

  1. What is the difference between static and dynamic connascence?

Static connascence refers to source-code-level coupling – name (multiple entities must agree on the name), type ( multiple entities must agree on the type), meaning (multiple entities must agree on the meaning of particular values), position (multiple entities must agree on the order of the values), algorithm (multiple entities must agree on a particular algorithm).

Dynamic connascence analyzes calls at runtime – execution (order of execution), timing (timing of the execution of multiple components), values (several values relate to one another), identity (several values relate to one another and must change together).

  1. What does the connascence of type mean? Is it static or dynamic connascence?

[STATIC] Multiple components must agree on the type of entity.

  1. What is the strongest form of connascence?

Identity. Multiple components must reference the same entity. For example when 2 independent components must share and update a common data source.

  1. What is the weakest form of connascence?

Name. Multiple components must agree on the name.

  1. Which is preferred within code base — static or dynamic connascence?

Static. Architects have a harder time determining connascence because we lack tools to analyze runtime calls as effectively as we can analyze the call graph.

Chapter 4: Architecture Characteristics Defined

  1. What three criteria must an attribute meet to be considered an architecture characteristic?
  • specifies a non-domain design consideration
  • influences some structural aspect of the domain
  • is critical or important to application success
  1. What is the difference between an implicit characteristic and an explicit one? Provide an example of each.

Implicit – appears in requirements, necessary for project success. Domain knowledge required to uncover such characteristics.

Explicit – characteristic listed in the requirements.

  1. Provide an example of an operational characteristic.

Availability, Continuity, Performance, Reliability, Recoverability, Scalability, …

  1. Provide an example of a structural characteristic.

Configurability, Extensibility, Maintainability, …

  1. Provide an example of a cross-cutting characteristic.

Accessibility, Authentication, Authorization, Legal, Security, Privacy, …

  1. Which architecture characteristic is more important to strive for — availability or performance?

The ultimate answer for architectural questions: _it depends on …

Chapter 5: Identifying Architectural Characteristics

  1. Give a reason why it is a good practice to limit the number of characteristics an architecture should support.

Over-specifying architecture characteristics may kill the project. Example: The Vasa – a Swedish warship, it was supposed to be magnificent, turned out to be too heavy, too complicated.

Keep the design simple.

  1. True or false: most architecture characteristics come from business requirements and user stories

True.

  1. If a business stakeholders states that time-to-market is the most important business concern, which architecture characteristic would the architecture need to support?

Agility, testability, deployability

  1. What is the difference between scalability and elasticity?

Scalability – the ability to handle a large number of concurrent users without serious performance degradation.

Elasticity – the ability to handle bursts of requests.

  1. You find out that your company is about to undergo several major acquisitions to significantly increase its customer base. Which architectural characteristics should you be worried about?

Interoperability, scalability, adaptability, extensibility.

Chapter 6: Measuring and Governing Architecture Characteristics

  1. Why is cyclomatic complexity such an important metric to analyze for architecture?

Overly complex code represents a code smell – it harms virtually every one of the desirable characteristics.

  1. What is an architecture fitness function? How can they be used to analyze an architecture?

Any mechanism that provides an objective integrity assessment of some architecture characteristic or combination of architecture characteristics. Many tools may be used to implement fitness functions: metrics, monitors, unit tests, chaos engineering, …

  1. Provide an example of an architecture fitness function to measure the scalability of an architecture?

Code automatic scalability tests and compare results.

  1. What is the most important criteria for an architecture characteristic to allow architects and developers to create fitness functions?

Architects must ensure that developers understand the purpose of the fitness function before imposing it on them.

Chapter 7: Scope of Architecture Characteristics

  1. What is an architectural quantum, and why is it important to architecture?

The architectural quantum is the smallest possible item that needs to be deployed in order to run an application.

  1. Assume a system consisting of a single user interface with four independently deployed services, each containing its own separate database. Would this system have a single quantum or four quanta? Why?

4 because each service can be deployed separately.

  1. Assume a system with an administration portion managing static reference data (such as the product catalog, and warehouse information) and a customer-facing portion managing the placement of orders. How many quanta should this system be and why? If you envision multiple quanta, could the admin quantum and customer-facing quantum share a database? If so, in which quantum would the database need to reside?

2 quantas – ordering and a warehouse management, separate databases.

Chapter 8: Component-Based Thinking

  1. We define the term component as a building block of an application – something the application does. A component usually consist of a group of classes or source files. How are components typically manifested within an application or service?

Components – the physical manifestation of a module. Components offer a language-specific mechanism to group artifacts together, often nesting them to create stratification. Components also appear as subsystems or layers in architecture, as the deployable unit of work for many event processors.

  1. What is the difference between technical partitioning and domain partitioning? Provide an example of each.

Technical partitioning – organizing architecture based on technical capabilities (presentation, business, service, persistence).

Domain partitioning – a modeling technique for decomposing complex systems. In DDD the architect identifies domains independent and decoupled from each other. The microservices architecture is based on this philosophy.

  1. What is the advantage of domain partitioning?

Better reflects the kinds of changes that most often occur on projects.

  1. Under what circumstances would technical partitioning be a better choice over domain partitioning?

Separation based on technical partitioning enables developers to find certain categories of code base quickly, as it is organized by capabilities.

  1. What is the entity trap? Why is it not a good approach for component identification?

Arises when the architect incorrectly identifies the database relationships ads workflows in the application, a correspondence that rarely manifests in the real world. This anti-pattern indicates lack of thought about the actual workflows of the application. Components created with entity-trap tend to be too coarse-grained.

Chapter 9: Foundations

  1. List the eight fallacies of distributed computing.

Latency is Zero, Bandwidth is Infinite, The Network is Reliable, The Network is Secure, The Topology Never Changes, There is Only One Administrator, Transport Cost is Zero, The Network is Homogenous

  1. Name three challenges that distributed architectures have that monolithic architectures don’t.

Debugging a distributed architecture, Distributed transactions, Contract maintenance and versioning.

  1. What is stamp coupling?

Requesting/receiving too much data whereas only a small subset of data is needed — 2000 req x 10kB VS 2000 req x 100kB

  1. What are some ways of addressing stamp coupling?
  • create private RESTful API endpoints
  • use field selectors in the contract
  • use GraphQL
  • use internal messaging endpoints

Fonte: https://github.com/pkardas/notes/blob/master/books/fundamentals-of-architecture.md#preface-invalidating-axioms

Architecture – Abbreviations

SOLID

SRP – Single Responsibility Principle

A class should have only one reason to change, so in order to reduce reasons for modifications – one class should have one responsibility. It is a bad practise to create classes doing everything.

Why is it so important that class has only one reason to change? If class have more than one responsibility they become coupled and this might lead to surprising consequences like one change breaks another functionality.

You can avoid these problems by asking a simple question before you make any changes: What is the responsibility of your class / component / micro-service? If your answer includes the word “and”, you’re most likely breaking the single responsibility principle.

OCP – Open-Closed Principle

Classes, modules, functions, etc. should be open to extension but closed to modification.

Code should be extensible and adaptable to new requirements. In other words, we should be able to add new system functionality without having to modify the existing code. We should add functionality only by writing new code.

If we want to add a new thing to the application and we have to modify the “old”, existing code to achieve this, it is quite likely that it was not written in the best way. Ideally, new behaviors are simply added.

LSP – Liskov Substitution Principle

This rule deals with the correct use of inheritance and states that wherever we pass an object of a base class, we should be able to pass an object of a class inheriting from that class.

Example of violation:

class A:
    def foo() -> str:
        return "foo"


class B(A):
    def foo(bar: str) -> str:
        return f"foo {bar}"

B is not taking the same arguments, meaning A and B are not compatible. A can not be used instead of B, and B can not be used instead of A.

ISP – Interface Segregation Principle

Clients should not be forced to depend upon interfaces that they do not use. ISP splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them.

Example of violation:

class Shape:
    def area() -> float:
        raise NotImplementedError

    def volume() -> float():
        raise NotImplementedError

2D triangle does not have volume, hence it would need to implement interface that is not needed. In order to solve this, there should be multiple interfaces: Shape and 3DShape.

DIP – Dependency Inversion Principle

High-level modules, which provide complex logic, should be easily reusable and unaffected by changes in low-level modules, which provide utility features. To achieve that, you need to introduce an abstraction that decouples the high-level and low-level modules from each other.

Entities must depend on abstractions, not on concretions. It states that the high-level module must not depend on the low-level module, but they should depend on abstractions.

For example password reminder should not have knowledge about database provider (low level information).

DRY – Don’t Repeat Yourself

“Every piece of knowledge must have a single, unambiguous, authoritative representation within a system”. When the DRY principle is applied successfully, a modification of any single element of a system does not require a change in other logically unrelated elements.

KISS – Keep It Simple, Stupid

The KISS principle states that most systems work best if they are kept simple rather than made complicated; therefore, simplicity should be a key goal in design, and unnecessary complexity should be avoided.

ACID

Atomicity

Each transaction is either properly carried out or the process halts and the database reverts back to the state before the transaction started. This ensures that all data in the database is valid.

Consistency

A processed transaction will never endanger the structural integrity of the database. Database is always in consistent state.

Isolation

Transactions cannot compromise the integrity of other transactions by interacting with them while they are still in progress.

Durability

The data related to the completed transaction will persist even in the cases of network or power outages. If a transaction fails, it will not impact the manipulated data.

BASE

Basically Available

Ensure availability of data by spreading and replicating it across the nodes of the database cluster – this is not done immediately.

Soft State

Due to the lack of immediate consistency, data values may change over time. The state of the system could change over time, so even during times without input there may be changes going on due to ‘eventual consistency’, thus the state of the system is always ‘soft’.

Eventually Consistent

The system will eventually become consistent once it stops receiving input. The data will propagate to everywhere it should sooner or later, but the system will continue to receive input and is not checking the consistency of every transaction before it moves onto the next one.

CAP

In theoretical computer science, the CAP theorem states that it is impossible for a distributed data store to simultaneously provide more than two out of the following three guarantees:

Consistency

Every read receives the most recent write or an error. Refers to whether a system operates fully or not. Does the system reliably follow the established rules within its programming according to those defined rules? Do all nodes within a cluster see all the data they are supposed to? This is the same idea presented in ACID.

Availability

Every request receives a (non-error) response, without the guarantee that it contains the most recent write. Is the given service or system available when requested? Does each request get a response outside of failure or success?

Partition Tolerance

Represents the fact that a given system continues to operate even under circumstances of data loss or system failure. A single node failure should not cause the entire system to collapse.

NF

Database normalisation is the process of structuring a database, usually a relational database, in accordance with a series of so-called normal forms in order to reduce data redundancy and improve data integrity.

1NF

To satisfy 1NF, the values in each column of a table must be atomic.

2NF

Must be in 1NF + single column primary key (no composite keys).

3NF

Must be in 2NF + no transitive functional dependencies.

Transitive Functional Dependencies – when changing a non-key column, might cause any of the other non-key columns to change. For example:

3nf-violation

Fonte: https://github.com/pkardas/notes/blob/master/patterns/abbreviations.md

API Canônica

Uma API canônica é uma interface de programação de aplicação (API) projetada para ser a representação oficial, ou “fonte única da verdade”, de um sistema ou domínio. O conceito de canônica refere-se a algo que segue um padrão autorizado ou é a forma mais pura e completa de algo.

No contexto de APIs, isso significa que a API canônica é a interface principal, geralmente abstrata e agnóstica à tecnologia, que expõe o modelo de domínio de maneira consistente e clara para consumo por diferentes partes do sistema ou por sistemas externos.

Características principais de uma API canônica:

  1. Consistência:
    Uma API canônica garante que diferentes consumidores (módulos internos, sistemas externos, etc.) acessem as mesmas regras e dados de forma consistente, sem variações ou duplicações em diferentes partes do sistema.
  2. Independência de implementação:
    Ela é projetada para ser neutra em relação a detalhes de implementação. Ou seja, ela descreve a interação com o sistema de maneira lógica e orientada ao domínio, sem expor detalhes técnicos ou internos, como infraestruturas ou frameworks específicos.
  3. Modelagem orientada ao domínio (DDD):
    APIs canônicas geralmente são construídas com base em modelos de domínio bem definidos, conforme os princípios de Domain-Driven Design. Cada endpoint ou operação exposta pela API reflete as operações de negócio reais, em vez de operações puramente técnicas.
  4. Contrato Estável:
    A API canônica geralmente apresenta um contrato estável e bem-definido, o que significa que ela pode evoluir sem quebrar a compatibilidade com os consumidores existentes. Isso permite atualizações e mudanças no sistema subjacente sem afetar diretamente os clientes que consomem essa API.
  5. Facilidade de integração:
    APIs canônicas padronizam a interface entre sistemas, facilitando a integração de novos componentes ou serviços. A interoperabilidade é simplificada, pois a API segue uma estrutura que pode ser consumida por diferentes tipos de clientes, como front-ends, back-ends ou terceiros.
  6. Unificação dos dados e regras de negócio:
    A API canônica centraliza e unifica o acesso aos dados e às regras de negócio, o que evita redundâncias e inconsistências. Isso garante que todos os consumidores obtenham a mesma visão e apliquem as mesmas regras de maneira padronizada.

Exemplo prático:

Em um sistema de e-commerce com um domínio que inclui clientes, pedidos e produtos, uma API canônica exporia operações que permitem a criação de pedidos, consulta de produtos, gerenciamento de clientes, etc., de forma que todos os serviços relacionados interajam com esses dados e regras de uma maneira consistente.

  • Operações do domínio:
    • Criar um pedido (/orders/create)
    • Consultar um produto (/products/{id})
    • Gerenciar clientes (/customers/{id}/update)

Benefícios de usar uma API canônica:

  • Reduz complexidade e duplicidade: Uma API canônica elimina a necessidade de várias APIs especializadas ou duplicadas para diferentes sistemas, centralizando as operações.
  • Facilita manutenção e evolução: Com um contrato estável e bem definido, a API pode ser evoluída sem grandes impactos para os consumidores.
  • Melhor modelagem de negócio: Reflete com precisão os processos de negócio e o modelo de domínio, melhorando a clareza e a robustez do sistema.

Essencialmente, a API canônica é um ponto de acesso estruturado e padronizado para todo o domínio de um sistema, garantindo consistência e governança.

Benefícios do API Gateway

Aqui, pretendo levantar os benefícios na utilização de um API Gateway.

Benefícios

  • Evita expor a API para cada micro-serviço
  • Não havendo exposição da API consumidora, reduzindo a superfície de ataque potencial
  • Abstração dos micro-serviços, tanto na parte de endpoints quanto payload
  • Atua como Load Balancer
  • Pode gerenciar Black List e White List
  • Atua na Autenticação e Autorização de APIs
  • Permite a transformação de formatos, manipulação de estruturas e validações de campos
  • Pode compor dados, integrando várias APIs (veja o pattern API Composition)
  • Pode atuar como BFF – Backend For Frontend, simplificando o payload e reduzindo tráfego
  • Permite controle de requisições como Rate Limit
  • Mitiga riscos de OWASP
  • Permite controle de chamadas, gerando relatórios, importantes para monetização da API
  • Monitora e faz tracing das chamadas
Multiples endpoints
API Composition
The Role of API Microgatway in Microservices
API Microgateway Concept
API Microgateway DevOps Cycle
API Microgateway DevOps Cycle

Exemplo API – Binary vs Base64

Este post, esclarece as diferenças de uma API que permite integrar arquivos, através de arquivo binário e base 64. Um ponto importante é que utilizando o formato Base 64, o payload aumenta 33% (em média), nas chamadas GET/POST.

O exemplo utiliza Spring Boot.

Desenho da Solução

A solução utiliza REST API, armazenando o arquivo em File System (/uploads/) no local onde a aplicação está rodando.

Swagger UI

De forma a facilitar o entendimento a API, o projeto conta com o Swagger UI, através do Spring Fox.

Para acessar o Swagger UI, basta subir a aplicação e acessar http://localhost:8080/swagger-ui.html.

Postman

GET – List Files

GET – Specif File (obtenção de arquivo binário)

GET – Specif File 64 (obtenção do arquivo em base64 – em torno de 33% maior que o binário) – Verifique o tamanho em Content-Length (12.764) – O arquivo binário tem 9.572 bytes.

POST – Post File

POST – Post File 64

Código

O código-fonte pode ser baixado no Github.

Cinco pilares IASA

Estratégia de tecnologia do negócio: os arquitetos precisam ter um entendimento básico do negócio; do contrário não conseguirão dar suporte aos objetivos da organização ou aos objetivos dos clientes. Esses conhecimentos compreendem assuntos financeiros, estratégias de inovação de TI e técnicas de validação, assim como conceitos da indústria, tendências, padrões e compliance (aderência a padrões, regulamentos etc.).

Ambiente de TI: os arquitetos devem ter a “capacidade de verificar a solução e a maturidade organizacional em aspectos funcionais e de procedimentos da empresa”. O ambiente de TI envolve a implementação de elementos relacionados ao processo de desenvolvimento, o gerenciamento de projetos, a utilização de plataformas e frameworks, as mudanças e ativos gerenciais, a governança, além dos testes e controle de qualidade. Por exemplo, arquitetos devem estar alinhados com as tendências de mercado, entender os benefícios e limitações de uma determinada tecnologia, e também conhecer metodologias e tecnologias usadas em um determinado ambiente.

Atributos de qualidade: o atributos de qualidade são mapeados pelo IASA em quatro categorias – qualidades que definem aspectos de usabilidade, aspectos de desenvolvimento como mudanças de requisitos, questões operacionais como performance, além de requisitos de segurança. Tais qualidades são tipicamente requisitos transversais, levando a escolhas importantes, baseadas em limitações de tempo, custo, requisitos e recursos. Wilt enfatiza que os atributos de qualidade devem ser medidos e monitorados constantemente. Devem também ser viáveis: um cliente pode estar interessado em “cinco noves” de disponibilidade, mas pode não querer pagar por tal nível.

Projeto: a capacidade de criar um bom projeto arquitetural é a “principal ferramenta de um arquiteto, ao entregar uma estratégia e um produto para o negócio”. Como Wilt enfatiza, o design não se trata apenas da criação de uma arquitetura; inclui a revisão de todo o projeto. Não é só questão de “belos diagramas”, mas sim de “justificações, razões e ponderações”, quando for necessário tomar decisões. Habilidades necessárias nessa área incluem conhecimentos em técnicas e metodologias de design. E, é claro, arquitetos devem conhecer ferramentas e artefatos de design, como patterns, estilos e views. Para fazer as escolhas corretas sobre o design de um projeto, os arquitetos devem sempre alinhar suas decisões aos requisitos do negócio.

Dinâmica interpessoal: a dinâmcia entre pessoas inclui gerenciar e influenciar pessoas em um contexto de um projeto ou ambiente de TI. Wilt explica que há diversas habilidades necessárias nesse contexto. É necessário lidar com a cultura e com a relação com os clientes, além de lidar com os membros da equipe em um projeto. E embora a maioria dos arquitetos não detenha responsabilidades gerenciais, é necessário que possuam habilidades de liderança e gestão. Além disso, habilidades de negociação e colaboração são requisitos essenciais, assim como escrever e bem e ser capaz de realizar apresentações eficazes.

Arquitetura de micro-serviços

A arquitetura de micro-serviços pode trazer muitos benefícios para o desenvolvimento de software. Seus principais pontos fortes são a escalabilidade, a resiliência da aplicação, facilidade de implantação e aumento na eficiência da manutenção dos sistemas.

Nesse artigo, vamos entender um pouco melhor sobre a organização de um micro-serviço e as camadas o compõe, definindo o seu ecossistema e explicando como cada parte se relaciona entre si.

O ecossistema da arquitetura de microsserviços

Construir, padronizar e manter a infraestrutura de uma maneira estável, escalável, tolerante a falhas e confiável é essencial para o sucesso das operações de um micro-serviço .

Existem vários modelos distintos que sugerem como um ecossistema de micro-serviços deve ser organizado. Um modelo interessante e bem estruturado é o descrito por Susan J. Fowler, em seu livro intitulado “Production-Ready Microservices”.

Segunda ela, o ecossistema de micro-serviços pode ser dividido em quatro “camadas”, sendo elas: Hardware, comunicação, plataforma de aplicações e micro-serviços.

Apesar das camadas estarem todas interligadas, estabelecer essa divisão nos ajuda a entender melhor as diferentes responsabilidades e os diferentes módulos que compõem um ecossistema da arquitetura de micro-serviços.

Hardware

Hardware são os computadores e equipamentos onde os micro-serviços são armazenados e executados. Estes servidores podem estar dentro da empresa, ou pertencerem a provedores de infraestrutura em nuvem, como Amazon Web Services, Google Cloud Platform ou Windows Azure.

Existem algumas soluções que visam diminuir a dificuldade de se gerenciar estes equipamentos, como o emprego de tecnologias de conteinerização e clusterização para o armazenamento dos micro-serviços.

É importante que os servidores sejam providos de mecanismos de monitoramento e logging para identificar problemas de falhas de disco, rede ou processamento, por exemplo. Em um ecossistema de grande diversidade e dinamismo, é importante ter à disposição ferramentas que evidenciem dados da saúde das máquinas onde esses micro-serviços operam e mantenham um histórico destas informações. Desta maneira, eventuais problemas podem ser rapidamente identificados e resolvidos, uma vez que são facilmente detectados e rastreados. Adicionalmente, um mecanismo de monitoramento bem estruturado permite que seja possível acompanhar o impacto que a evolução das aplicações provoca na infraestrutura como um todo.

Comunicação

A Comunicação engloba todo o conjunto responsável por permitir que a interação entre micro-serviços ocorra, e é composta por elementos chave como os endpoints de APIService Discovery e Service Registry, e Load Balancers.

Endpoints de API

Dado uma API de um micro-serviço, seus endpoints são os pontos através dos quais toda a comunicação externa acontece. É nos endpoints que o micro-serviço envia e recebe informações de outros micro-serviços ou aplicações.

Service Discovery e Service Registry

Em um ecossistema de micro-serviços executados em nuvem, as configurações de rede mudam dinamicamente dadas suas características de escalabilidade, falhas e atualizações.  Diante deste cenário dinâmico, é necessário um mecanismo que mantenha a localização mais recente e atualizada de cada serviço.  Os micro-serviços registram a si mesmos no registrador de serviços quando são instanciados, e removidos quando são encerrados ou quando apresentam alguma falha.

Quando um serviço precisa se comunicar com outro, ele recorre ao Service Discovery, em busca da localização mais atualizada deste serviço. Este gerenciamento é um ponto importante e demanda muita atenção na configuração de um ecossistema de micro-serviços.

Load Balancer

Os balanceadores de carga são os responsáveis por rotear as requisições vindas dos clientes para as instâncias do micro-serviço requisitado, garantindo que nenhum servidor seja sobrecarregado e maximizando sua velocidade e capacidade. Se a instância de um determinado micro-serviço cair, o balanceador de carga para de rotear requisições de clientes para esta instância. Similarmente, quando uma nova instância fica disponível o balanceador começa a repassar requisições para ela automaticamente.

Plataforma de aplicações

A Plataforma de aplicações é a terceira camada, e engloba todas as ferramentas que são independentes de um micro-serviço. Estas ferramentas devem ser construídas e dispostas de maneira que o time de desenvolvimento não tenha que se preocupar com nada além da lógica de sua própria aplicação.

Padrões nos processos de desenvolvimento com uso de repositórios de código como GitHub e Bitbucket, por exemplo, e mirroring de ambiente de produção são eficientes para manter a base de código organizada, e simular todas as dependências que a aplicação terá quando for ao ar.

Builds centralizados e automatizados com integração e deploys contínuos são essenciais. Dependendo do tamanho de sua aplicação e do número de micro-serviços que ela possui, dezenas de deploys podem ocorrer diariamente. Por isso, é importante que as ferramentas sejam corretamente configuradas, e que sejam capazes de executar testes automaticamente, adicionar novas dependências conforme necessário, e preparar os releases a medida que novas versões são codificadas.

Por último, ter um mecanismo de log centralizado e monitoramento a nível de micro-serviço é crucial para entender eventuais problemas que ocorrem no serviço implementado. Dado que a natureza de micro serviços é de sofrer alterações constantemente, os logs permitem entender o que aconteceu no sistema em um momento específico. O monitoramento, por sua vez, é utilizado para verificar a saúde e status de um serviço em tempo real.

Micro-serviços

Os micro-serviços concentram a lógica para resolver o problema para o qual se propõe. A ideia é que o serviço seja totalmente abstraído dos demais componentes explicados acima, sem contato com as especificidades de hardware, service registry e service discovery, balanceamento de carga e processos de deploy, por exemplo. O micro-serviço em si consiste apenas do código e configurações específicas que devem ser aplicadas sobre ele para que possa entregar as funcionalidades para qual foi idealizado.

De maneira geral, este é um modelo de ecossistema da arquitetura de micro-serviços. Para serem aplicados em projetos reais, os tópicos citados devem ser estudados e compreendidos mais a fundo, tendo sempre em mente que esse tipo de arquitetura possui componentes muito dinâmicos, e que estão em constante aprimoramento.