Solution Architecture vs. Software Architecture

Solution Architecture

The term "solution architecture" is used to describe the process of developing, documenting, and reviewing with relevant stakeholders a multi-dimensional architecture construct that enables a specific business or operational outcome. The target architecture that enables this outcome is defined within the context of all impacted and applicable architecture domains such as business, data, application, technology, integration, security, etc. A solution architecture document will elaborate and further decompose the target architecture into architecture deliverables for each architecture domain. For example, the solution architecture for a loan application digital channel at a fictional bank to allow bank’s customers to apply for a loan online will require an impact assessment of each architecture domain. Each domain will address the needs and concerns of the impacted stakeholders who are bound by that domain such as business, technology, operational, risk, legal, etc…
Image title
Let’s try to segregate some of these concerns into specific architecture domains:
  • Business Architecture: How does a customer apply for a loan online?
  • Data Architecture: What information is needed to enable loan risk assessment and processing? How to manage customer info with maximum security, integrity and optimal cost, performance, reliability, consistency?
  • Application Architecture: What UX, process management, and functional system components/services are needed to enable customer loan application via mobile and web devices?
  • Integration Architecture: How will the distributed application component and services talk to each other?
  • Security Architecture: How to properly verify and authenticate customer identity? How to ensure that customer data is secure in a distributed environment? How to prevent unauthorized data access and data theft over the wire?
  • Technology Architecture: How to configure supporting infrastructure for high availability and recoverability in case of system or facility failure?
  • DevOps Architecture: How to enable rapid product delivery and continuous maintenance?
The solution architecture that best addresses these concerns will be derived by applying a formal architecture development process and incorporating established organization’s architecture principles and reference architecture in order to define the most optimal technology solution that delivers the desired business outcome. The solution architecture must be well documented and presented to the project and architecture review boards to ensure that it satisfies the project constraints and technology standards established by the enterprise/chief architect.
The figure above is a sample of a few common solution architecture diagrams for a loan application use case. Please note that the actual solution architecture document will also contain a detail description of each domain target architecture and gaps. Other architecture artifacts such as catalogs and matrices may be used.

Software Architecture

Once the solution architecture is defined, reviewed, and approved, software architecture can now be developed as part of the Design or Architectural Runway SDLC phase. The primary focus of software architecture is to define and document software structure and behavior in order to enable software engineering and delivery based on known functional and non-functional requirements. This is quite different from the goal of solution architecture, which is to define app, data, infra architecture building blocks, dependencies, and address all relevant stakeholders’ concerns. Software architect, usually also a technology SME, will use architecture styles, object oriented analysis and software design patterns to design client and server side software components that implement the web/mobile customer experience (CX), process management, functional and data management application architecture blocks defined in the solution architecture document. As I mentioned, the focus of software architecture is to enable application development and delivery. The software engineering diagrams that I found most useful in my days as a software architect are the domain object model class, service component, sequence, and deployment diagrams.
Image title
  • Domain Object Model Class Diagram is essential in defining a consistent data format for information management, persistence, and sharing.
  • Services Component Diagram breaks down system functional services into self-contained API components that can be implemented as microservices
  • Sequence Diagram demonstrates how software modules and distributed components integrate with one another in a context of each use case.
  • Deployment Diagram is necessary to demonstrate software deployment on compute and middleware infrastructure in order to engineer a DevOps pipeline, manage software/infrastructure dependencies, and design for performance and failure

Vừa quản lý vừa thực hiện dự án, liệu có tốt ?

Một thực tế tương đối phổ biến là có những người được giao làm công tác quản lý dự án nhưng đồng thời cũng được yêu cầu phải đảm nhiệm một phần công việc thực hiện dự án. Giải pháp này có thể phù hợp nhất định đối với một số vấn đề. Tuy nhiên, nếu đó là một đội dự án thực sự gồm một vài nhân viên, thì nhà quản lý dự án chắc chắn sẽ bị giằng xé giữa công việc quản lý và yêu cầu phải hoàn thành phần việc của một nhân viên. Tất nhiên là phần việc trực tiếp này phải được ưu tiên vì nếu không, dự án sẽ không đạt tiến độ theo bảng tiến độ. Hệ quả là phần nhiệm vụ công tác quản lý sẽ không được hoàn thành. Nhà quản lý có thể hy vọng rằng đội dự án sẽ tự thu xếp được, nhưng sự thực thì không phải như vậy. Hơn nữa, nếu đội dự án có thể tự quản lý, thì ngay từ đầu dự án đã chẳng cần phải có một nhà quản lý dự án nữa (đến đây, mong bạn hãy nhớ lại những phân tích của chúng ta về tầm quan trọng của công tác quản lý dự án).

  Thật không may cho nhà quản lý dự án đó. Khi tổng kết và đánh giá kết quả thực hiện nhiệm vụ, nhà quản lý sẽ được nhận xét rằng năng lực quản lý của anh ta chưa ổn và cần phải được cải thiện. Thực sự thì ngay từ ban đầu, chỉ nên phân công nhà quản lý đảm nhiệm công tác quản lý dự án mà thôi.

  Đúng vậy, đối với các đội dự án quy mô nhỏ, từ 3 đến 4 người, thì nhà quản lý dự án có thể đảm nhiệm một phần công việc chuyên môn nào đó. Nhưng với các đội dự án có quy mô lớn hơn thì bạn không thể vừa làm việc vừa quản lý, bởi bạn sẽ liên tục bị xao nhãng khỏi công việc chuyên môn mỗi khi các thành viên khác trong đội dự án cần đến bạn.

  Một trong những nguyên nhân của tình trạng này là do các tổ chức không hiểu đầy đủ về công tác quản lý dự án và cho rằng một cá nhân có thể làm cả hai việc trong một dự án. Hệ quả của việc này là trong công ty, gần như ai cũng đều tìm cách thử sức trong công tác quản lý các dự án. Lẽ thường thì chắc chắn chỉ có một vài người làm tốt, còn một số người khác tỏ ra hoàn toàn không có khả năng. Tôi phát hiện ra một cách tiếp cận tốt hơn nhiều, đó là lựa chọn một vài cá nhân có năng lực, đam mê công tác quản lý dự án và giao cho họ quản lý một số dự án nhỏ. Như vậy, các nhân viên “kỹ thuật” (với nghĩa rộng của từ này) rảnh tay tập trung vào công việc kỹ thuật mà không phải lo lắng về các vấn đề hành chính; đồng thời các nhà quản lý dự án lại có cơ hội phát triển và tinh thông thực sự trong “nghề” quản lý dự án của mình.

Cloud Native Application Architecture












Introduction

Cloud native is an approach for building applications as micro-services and running them on a containerised and dynamically orchestrated platforms that fully exploits the advantages of the cloud computing model. Cloud-native is about how applications are created and deployed, not where. Such technologies empower organisations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. These applications are built from the ground up, designed as loosely coupled systems, optimised for cloud scale and performance, use managed services and take advantage of continuous delivery to achieve reliability and faster time to market. The overall objective is to improve speed, scalability and, finally, margin.
Speed — Companies of all sizes now see a strategic advantage in being able to move quickly and get ideas to market fast. By this, we mean moving from months to get an idea into production to days or even hours. Part of achieving this is a cultural shift within a business, transitioning from big bang projects to more incremental improvements. At its heart, a Cloud Native strategy is about handling technical risk. In the past, our standard approach to avoiding danger was to move slowly and carefully. The Cloud Native approach is about moving quickly by taking small, reversible and low-risk steps.
Scalability — As businesses grow, it becomes strategically necessary to support more users, in more locations, with a broader range of devices, while maintaining responsiveness, managing costs and not falling over
Margin — In the new world of cloud infrastructure, the strategic goal is to be to pay for additional resources only as needed — as new customers come online. Spending moves from up-front CAPEX (buying new machines in anticipation of success) to OPEX (paying for additional servers on-demand).

Role Of CNCF

Cloud Native Computing Foundation is an open source software foundation housed in the Linux Foundation and includes big names such as Google, IBM, Intel, Box, Cisco, and VMware etc, dedicated to making cloud-native computing universal and sustainable. Cloud native computing uses an open source software stack to deploy applications as microservices, packaging each part into its own container, and dynamically orchestrating those containers to optimize resource utilisation. According to the FAQ on why CNCF is needed — Companies are realising that they need to be a software company, even if they are not in the software business. For example, Airbnb is revolutionising the hospitality industry and more traditional hotels are struggling to compete. Cloud native allows IT and software to move faster. Adopting cloud-native technologies and practices enables companies to create software in-house, allows business people to closely partner with IT people, keep up with competitors and deliver better services to their customers.

Cloud Native Design Principles

Designed As Loosely Coupled Microservices

Microservice is an approach to develop a single application as a suite of small services, each running in their own process and communicating using lightweight protocols like HTTP. These services are built around business capabilities and are independently deployable by fully automated deployment machinery.

Developed With Best-of-breed Languages And Frameworks

Each service of a cloud-native application is developed using the language and framework best suited for the functionality. Cloud-native applications are polyglot. Services use a variety of languages, runtimes and frameworks. For example, developers may build a real-time streaming service based on WebSockets, developed in Node.js, while choosing Python for building a machine learning based service and choosing spring-boot for exposing the REST APIs. The fine-grained approach to developing microservices lets them choose the best language and framework for a specific job.

Centred Around APIs For Interaction And Collaboration

Cloud-native services use lightweight APIs that are based on protocols such as representational state transfer (REST) to expose their functionality. Internal services communicate with each other using binary protocols like Thrift, Protobuff, GRPC etc for better performance

Stateless And Massively Scalable

A cloud-native app stores its state in a database or some other external entity so instances can come and go. Any instance can process a request. They are not tied to the underlying infrastructure which allows the app to run in a highly distributed manner and still maintain its state independent of the elastic nature of the underlying infrastructure. From a scalability perspective, the architecture is as simple as just by adding commodity server nodes to the cluster, it should be possible to scale the application

Resiliency At The Core Of the Architecture

According to Murphy’s law — “Anything that can fail will fail”. When we apply this to software systems, In a distributed system, failures will happen. Hardware can fail. The network can have transient failures. Rarely, an entire service or region may experience a disruption, but even those must be planned for. Resiliency is the ability of a system to recover from failures and continue to function. It’s not about avoiding failures, but responding to failures in a way that avoids downtime or data loss. The goal of resiliency is to return the application to a fully functioning state following a failure. Resiliency offers the following:
  • High Availability — the ability of the application to continue running in a healthy state, without significant downtime
  • Disaster Recovery — the ability of the application to recover from rare but major incidents: non-transient, wide-scale failures, such as service disruption that affects an entire region
One of the main ways to make an application resilient is through redundancy. HA and DR are implemented using multi node clusters, Multi region deployments, data replication, no single point of failure, continuous monitoring etc.
Following are some of the strategies for implementing resiliency:
  • Retry transient failures — Transient failures can be caused by momentary loss of network connectivity, a dropped database connection, or a timeout when a service is busy. Often, a transient failure can be resolved simply by retrying the request
  • Load balance across instances — Implement cluster everywhere. Stateless applications should be able to scale by adding more nodes to the cluster
  • Degrade gracefully — If a service fails and there is no failover path, the application may be able to degrade gracefully while still providing an acceptable user experience
  • Throttle high-volume tenants/users — Sometimes a small number of users create excessive load. That can have an impact on other users, reducing the overall availability of your application
  • Use a circuit breaker — The circuit breaker pattern can prevent an application from repeatedly trying an operation that is likely to fail. The circuit breaker wraps calls to a service and tracks the number of recent failures. If the failure count exceeds a threshold, the circuit breaker starts returning an error code without calling the service
  • Apply compensating transactions. A compensating transaction is a transaction that undoes the effects of another completed transaction. In a distributed system, it can be very difficult to achieve strong transactional consistency. Compensating transactions are a way to achieve consistency by using a series of smaller, individual transactions that can be undone at each step.
Testing for resiliency — Normally resiliency testing cannot be done the same way that you test application functionality (by running unit tests, integration tests and so on). Instead, you must test how the end-to-end workload performs under failure conditions which only occur intermittently. For example: inject failures by crashing processes, expired certificates, make dependent services unavailable etc. Frameworks like chaos monkey can be used for such chaos testing.

Packaged As Lightweight Containers And Orchestrated

Containers make it possible to isolate applications into small, lightweight execution environments that share the operating system kernel. Typically measured in megabytes, containers use far fewer resources than virtual machines and start up almost immediately. Docker has become the standard for container technology. The biggest advantage they offer is portability.
Cloud-native applications are deployed using Kubernetes which is an open source platform designed for automating deployment, scaling, and management of containerised applications. Originally developed at Google, Kubernetes has become the operating system for deploying cloud-native applications. It is also one of the first few projects to get graduated at CNCF.

Agile DevOps & Automation Using CI/CD

DevOps, the amalgamation of “development” and “operations describes the organisational structure, practices, and culture needed to enable rapid agile development and scalable, reliable operations. DevOps is about the culture, collaborative practices, and automation that aligns development and operations teams so they have a single mindset on improving customer experiences, responding faster to business needs, and ensuring that innovation is balanced with security and operational needs. Modern organisations believe in merging of development and operational people and responsibilities so that one DevOps team carries both responsibilities. In that way you just have one team who takes the responsibility of development, deployment and running the software in production.
Continuous Integration & Continuous Delivery
Continuous integration (CI) and continuous delivery (CD) is a set of operating principles that enable application development teams to deliver code changes more frequently and reliably. The technical goal of CI is to establish a consistent and automated way to build, package, and test applications. With consistency in the integration process in place, teams are more likely to commit code changes more frequently, which leads to better collaboration and software quality.
Continuous delivery picks up where continuous integration ends. CD automates the delivery of applications to selected infrastructure environments. It picks up the package built by CI, deploys into multiple environments like Dev, QA, Performance, Staging runs various tests like integration tests, performance tests etc and finally deploys into production. Continuous delivery normally has few manual steps in the pipeline whereas continuous deployment is a fully automated pipeline which automates the complete process from code checkin to production deployment.

Elastic — Dynamic scale-up/down

Cloud-native apps take advantage of the elasticity of the cloud by using increased resources during a use spike. If your cloud-based e-commerce app experiences a spike in use, you can have it set to use extra compute resources until the spike subsides and then turn off those resources. A cloud-native app can adjust to the increased resources and scale as needed.

Software Architecture - The Difference Between Architecture and Design

Image result for software architecture

Many people don’t really know the difference between software architecture and software design. Even for developers, the line is often blurry and they might mix up elements of software architecture patterns and design patterns. As a developer myself, I would like to simplify these concepts and explain the differences between software design and software architecture. In addition, I will show you why it is important for a developer to know a little bit about software architecture and a lot of software design. So, let’s start.

The Definition of Software Architecture

In simple words, software architecture is the process of converting software characteristics such as flexibility, scalability, feasibility, reusability, and security into a structured solution that meets the technical and the business expectations. This definition leads us to ask about the characteristics of a software that can affect a software architecture design. There is a long list of characteristics which mainly represent the business or the operational requirements, in addition to the technical requirements.

The Characteristics of Software Architecture

As explained, software characteristics describe the requirements and the expectations of a software in operational and technical levels. Thus, when a product owner says they are competing in a rapidly changing markets, and they should adapt their business model quickly. The software should be “extendable, modular and maintainable” if a business deals with urgent requests that need to be completed successfully in the matter of time. As a software architect, you should note that the performance and low fault tolerance, scalability and reliability are your key characteristics. Now, after defining the previous characteristics the business owner tells you that they have a limited budget for that project, another characteristic comes up here which is “the feasibility.”
Here you can find a full list of software characteristics, also known as “quality attributes,” here.

Software Architecture Patterns

Most people have probably heard of the term “MicroServices” before. MicroServices is one of many other software architecture patterns such as Layered Pattern, Event-Driven Pattern, Serverless Pattern and many more. Some of them will be discussed later in this article. The Microservices pattern received its reputation after being adopted by Amazon and Netflix and showing its great impact. Now, let’s dig deeper into the architecture patterns.
**A quick note, please don’t mix up design patterns like Factory or adaptor patterns and the architecture patterns. I will discuss them later.

Serverless Architecture

This element refers to the application solution that depends on third-party services to manage the complexity of the servers and backend management. Serverless Architecture is divided into two main categories. The first is “Backend as a service (BaaS)” and the second is “Functions as a Service (FaaS).” The serverless architecture will help you save a lot of time taking care and fixing bugs of deployment and servers regular tasks.
The most famous provider for serverless API is Amazon AWS “Lambda.”
You can read more about this here.

Event-Driven Architecture

This architecture depends on Event Producers and Event Consumers. The main idea is to decouple your system’s parts and each part will be triggered when an interesting event from another part has got triggered. Is it complicated? Let’s simplify it. Assume you design an online store system and it has two parts. A purchase module and a vendor module. If a customer makes a purchase, the purchase module would generate an event of “orderPending” Since the vendor module is interesting in the “orderPending” event, it will be listening, in case one is triggered. Once the vendor module gets this event, it will execute some tasks or maybe fire another event for order more of the product from a certain vendor.
Just remember the event-producer does not know which event-consumer listening to which event. Also, other consumers do not know which of them listens to which events. Therefore, the main idea is decoupling the parts of the system.
If you are interested in learning more about this, click here.

Microservices Architecture

Microservices architecture has become the most popular architecture in the last few years. It depends on developing small, independent modular services where each service solves a specific problem or performs a unique task and these modules communicate with each other through well-defined API to serve the business goal. I do not have to explain more just look at this image.
image from weave-works

Software Design

While software architecture is responsible for the skeleton and the high-level infrastructure of a software, the software design is responsible for the code level design such as, what each module is doing, the classes scope, and the functions purposes, etc.
If you are a developer, it is important for you to know what the SOLID principle is and how a design pattern should solve regular problems.
SOLID refers to Single Responsibility, Open Closed, Liskov substitution, Interface Segregation and Dependency Inversion Principles.
  • Single Responsibility Principle means that each class has to have one single purpose, a responsibility and a reason to change.
  • Open Closed Principle: a class should be open for extension, but closed for modification. In simple words, you should be able to add more functionality to the class but do not edit current functions in a way that breaks existing code that uses it.
  • Liskov substitution principle: this principle guides the developer to use inheritance in a way that will not break the application logic at any point. Thus, if a child class called “XyClass” inherits from a parent class “AbClass”, the child class shall not replicate a functionality of the parent class in a way that change the behavior parent class. So you can easily use the object of XyClass instead of the object of AbClass without breaking the application logic.
  • Interface Segregation Principle: Simply, since a class can implement multiple interfaces, then structure your code in a way that a class will never be forced to implement a function that is not important to its purpose. So, categorize your interfaces.
  • Dependency Inversion Principle: If you ever followed TDD for your application development, then you know how decoupling your code is important for testability and modularity. In other words, If a certain Class “ex: Purchase” depends on “Users” Class then the User object instantiation should come from outside the “Purchase” class.

Design Patterns

  • Factory Pattern: it is the most used design pattern in the OOP world because it saves a lot of time in the future when you have to modify one of the classes you used. Look at this example:
Imagine you want to instantiate a Users() Model Class, there are two ways to do it:
1 — $users = new Users();
2 — $users = DataFactory::get(‘Users’);
I would prefer the second way for two reasons among several ones. First, changing class name from “Users” to “UsersData” will only require one change in one place “inside the data factory” and the rest of your code will be the same. Second, if the class Users start taking parameters like Users($connection); then you also will need to change it in one place not in every function that required Users object. So, if you think the first way is better, think again.
  • Adapter Pattern: Adapter Pattern is one of the structural design patterns. From its name, you would expect that it converts the unexpected usage of class to an expected one.
Imagine that your application deals with Youtube API and in order to get access token, you have to call a function called getYoutubeToken();
So, you called this function in 20 different places in your application.
Then, Google releases new version of Youtube API and they renamed it to getAccessToken();
Now you will have to find and replace the function name everywhere across your application or you can create an Adapter class like the following example:
In this case, you only have to change one line and the rest of your application will keep working as usual.
Since this article does not talk about design patterns in detail, here are some helpful links if you want to learn more:
Remember there is a difference between a software architect and a software developer. Software architects have usually experienced team leaders, who have good knowledge about existing solutions which help them make right decisions in the planning phase. A software developer should know more about software design and enough about software architecture to make internal communication easier within the team.

[Sách Hay] Vận Hành Tinh Gọn - Running Lean - Phần 3

Test Plan triệt để

Sau khi đã viết ra Plan A và xác định các rủi ro cần ưu tiên, giờ thì bạn đã sẵn sàng để test plan một cách triệt để. Trong một startup tinh gọn (Lean Startup), điều này sẽ được thực hiện bằng các thử nghiệm.
Phương pháp Lean Startup có nguồn gốc hoàn toàn từ phương pháp khoa học mà việc thực hiện các thử nghiệm là các hoạt động chính. Chúng ta sẽ bàn cụ thể về các bước thực hiện các thử nghiệm hiệu quả trong Phần III cuốn sách, nhưng bây giờ chúng ta sẽ cùng định nghĩa một thử nghiệm.

Thử nghiệm là gì?

Một chu kỳ của vòng lặp học hỏi (learning) như trên hình 1–6 được gọi là một thử nghiệm.
Hình 1–6. Vòng lặp Build — Measure — Learn (Xây — Đo — Học)
Vòng lặp học hỏi, hay còn gọi là vòng lặp Build — Measure — Lean được xây dựng bởi Eric Ries dùng để mô tả chu trình phản hồi của khách hàng, điều sẽ ảnh hưởng đến việc học hỏi của một Lean Startup.

Chu kỳ bắt đầu bằng giai đoạn Build dựa trên một tập các ý tưởng và các giả thuyết, được dùng để tạo ra những mẫu thử như mockup, code, landing page… nhằm mục đích test giả thuyết. Chúng ta đưa các mẫu thử này đến với khách hàng và “đo đếm” (measuring) phản hồi của họ bằng cách kết hợp các dữ liệu định tính và định lượng. Những dữ liệu này dùng để học hỏi (learning) một cách chi tiết nhằm xác thực hoặc phản biện các giả thuyết ban đầu để điều chỉnh các hành động tiếp theo.

Vòng lặp các pattern

Trong khi một thử nghiệm sẽ giúp bạn xác thực xem một giả thuyết của mô hình kinh doanh đúng hay sai, một chuỗi lặp đi lặp lại nhiều thử nghiệm sẽ giúp chúng ta đạt được một mục tiêu cụ thể, ví dụ mục tiêu product/market fit.
Hình 1–7 thể hiện một vòng lặp gồm nhiều pattern chúng ta sẽ dùng xuyên suốt cuốn sách này.
Hình 1–7. Vòng lặp nhiều pattern.
Hai giai đoạn đầu tiên (Hiểu vấn đề và Xác định giải pháp) sẽ giúp chúng ta xác định problem/solution fit hay còn gọi là đi tìm một vấn đề đáng để giải quyết.
Sau đó, để đạt được mục tiêu problem/market fit, bạn lặp đi lặp lại một quá trình test xem cái bạn xây dựng có phải là cái mà mọi người muốn hay không bằng cách kết hợp 2 bước: thứ nhất là định tính (chất lượng) với quy mô nhỏ, sau đó là định lượng (số lượng) với quy mô lớn.

The Ultimate XP Project

  (Bài chia sẻ của tác giả  Ryo Amano ) Trong  bài viết  số này, tôi muốn viết về dự án phát triển phần mềm có áp dụng nguyên tắc phát triển...