Sage-Code Laboratory

Software Architecture

Software architecture is a comprehensible way of describing the components and functions of a software system. The purpose of this discipline is to get an abstract level of understanding for the reasons and values of the design choices.

Motivation

Software architecture is a Computer Science domain. Usually a software architect is also highly trained and experienced software developer. An architect has a leading role in a software project.

Architects are involved in the initial phase of the project and can move between projects, unlike developers who stick with one single project for a longer time. After an architecture is establish the project no longer require an architect.

Having an architecture design has a positive influence for the quality of software implementation. It can also contribute to cost reduction by elimination of risks for selecting the wrong technology. When the system is well designed then the team members can understand and implement code much faster by looking at the architecture documentation and make parts of the system that match well together, enabling the delivery on time and budget.


Page bookmarks


Use these bookmarks to read your favorite topic.


Architectural principles

When you design an architecture you must consider several aspects.

  1. Multiple stakeholders: Applications are usually design for multiple category of users: business managers, owners, users and operators. Design must consider the security and access to different application features by different stakeholders.
  2. Separation of concerns: This is a way to reduce complexity level of software components. Each component must be simple and must perform a single job. Another component is responsible for dispatching the jobs and orchestrate the workflow.
  3. Conceptual integrity: architecture of a software system represents an overall vision of what it should do and how. The architect assumes the role of "keeper of the vision", making sure that additions to the system are in line with the architecture.
  4. Safety guardrails: when you design an architecture you create restriction rules or constrains for specific components. For example in a 3 tier architecture the user interface can communicate only with business layer but not directly with the database.
  5. Foolproof safety: means infallible, or so simple or well-made that nothing can go wrong. It's synonyms are reliable, guaranteed, flawless. There's no such word as foolproof. If a fool is lacking in good sense, the opposite is someone shrewd.

System quality

In the past the focus of designers was to resolve multiple requirements and implement features for the system as fast as possible. This approach can lead to accumulation of technical dept and poor quality. Any project who do not focus on higher quality is doomed to failure.

Software Quality

System attributes

I engineering we have a theory that analyze systems. This theory include concepts and principles that can be extended to software. Next we enumerate some of these concepts:

Quality Attribute Description
Fault-tolerance The ability of a system to continue to operate even when some of its components fail.
Backward compatibility The ability of a system to continue to work with older versions of itself or with other systems that are not compatible with the latest version.
Extensibility The ability of a system to be extended with new features and functionality without affecting the existing functionality.
Reliability The ability of a system to work correctly even when there are errors.
Maintainability The ability of a system to be maintained and updated without affecting the existing functionality.
Availability The ability of a system to be available to users when they need it.
Efficiency The ability of a system to use its resources (such as time, memory, and processing power) in an effective and efficient manner.
Security The ability of a system to protect its data from unauthorized access, data breaches, and other attacks.
Usability The ability of a system to be used by users to achieve their goals effectively and efficiently.
Portability The ability of a system to be transferred to a new environment without affecting the existing functionality.

Your project should address and monitor all these aspects of quality. Identification of quality issues is a profession. There are quality specialists that can perform code review and quality assessment. These persons are very expensive and difficult to have in a company, therefore Software Developers must cover some of these skills.

Code Quality

One of most important concerns of Software Architecture is to establish rules and guidelines for making code of higher quality. After many years of practice we have come to appreciate for some design patterns that can be used to create better code. Next we explain the attributes and considerations for making your code sage.

Code attributes

To achieve greater software quality, you start with the source code. If this is not clean then the entire codebase suffer and the final software product will have lower quality. We are pointing out top quality attributes, so that you and your team can learn how to write better code.
# Code attribute Description
1 comprehensive readable, consistent, organized
2 documented use comments and annotations
3 modular use separation of concerns
4 testable make small sub-programs and functions
5 maintainable refactoring friendly, easy to debug

Note: Source code quality do not imply "performance" or "reliability", nor "efficiency" or "business value". Indeed these are also attributes to consider for software quality but they are related to final product not the source code. First think how developers write code and next be concerned about other quality aspects. We believe that code must be beautiful then correct then fast then efficient, in this order.

Making Documentation

Most languages are capable of self documented source code, using comments and annotations. It is important to know, some annotations can be parsed by a special program and converted in HTML pages automatically.

In our articles we use examples and comments to explain the essentials. Once you grasp the basics and start codding you will need more. There is nothing better or more complete than a good reference manual. Find it and read it!

We search the internet for add free documentation. Most of the time a computer language has a home page and reference manuals. We use some of these references ourselves when we make tutorial articles.

Design principles

When you design an application or a system you should describe some of your design principles and make them public. If you do not have time to make your own principles use next generic principles instead:

Modular: a system is an aggregation of multiple sub-systems. The sub-systems collaborate and communicate using messages and rules. If your system is monolithic it will be harder to build, test and maintain. Apply KISS principles (Keep it Simple Stupid). This means just design the features that you need. Architectures that are more complex than necessary will result in sub-optimal systems. Breaking this rule is called over-engineering. This should be avoided.

Holistic: A good system must define terminology and principles for definition of components and relations between them. A metaphor could help for building a theory using existing therms and analogy from real life.

Brilliance: A system architecture must be conceptual elegant, but architects should not be blinded by the beauty of creation, and always review features with a pragmatic and detail-oriented eye.

Coding Rules

We describe next some rules that you can use in your future software projects to guide your design choices. These will help you establish built-in quality. Some of these principles are using common sense and look obvious but some other may surprise you.

Basic rules

  1. If the code is difficult to read it is wrong;
  2. Split complex problems into simple parts;
  3. Create reusable code. Do'nt repeat yourself;
  4. Create comprehensive comments inside your code.
  5. When you are not sure use parametrized sub-programs;

Sage-Code Advices

Next table show you advices that can be an example of principles an architect should enumerate in architecural runway principles. These are Sage-Code advices, you can modify and add new advices for your own organization.

Advice Comments
Never release or deploy untested software. This is one of the most important rules in software engineering. It is essential to test your software thoroughly before releasing it to the public.
Store testing code and application code together. This will make it easier to maintain and update your tests.
Save and version control your configuration files. This will help you to track changes to your configuration files and to restore them if necessary.
Start your source files with a short comment. This will help you to understand the purpose of the file and to document your code.
Do not stay astray from left side of the screen. This will help to make your code more readable and easier to maintain.
Short lines of code are better than long lines. This will make your code easier to read and understand.
Group global variables and constants in records or structures. This will make your code more organized and easier to understand.
Create a local scope if possible. Local is better then the global. This will help to prevent name collisions and to make your code more readable.
It is better to define global constants than to use magic literals. This will make your code more readable and easier to understand.
Use comments in your code and make references to documentation. This will help to document your code and to make it easier to understand.
Create subroutines only if you need to. Subroutine call can be expensive. This will help to improve the performance of your code.
Avoid unnecessary data movement by using references. This will help to improve the performance of your code.
Favor explicit declarations against type inference or gradual types. This will help to make your code more readable and easier to understand.
Favor explicit loop and stacks over recursive functions. This will help to improve the performance of your code and to make it easier to understand.
Favor different identifiers over subroutine overloading. This will help to make your code more readable and easier to understand.
Do not be afraid of long identifier names for subroutines and variables. This will help to make your code more readable and easier to understand.
Do not be afraid of long processes: create subroutines only when necessary. This will help to improve the performance of your code.
Do not be afraid to do refectory whenever you think is necessary. This will help to improve the quality of your code.
Do not create functionality that is not required: let the future to care about itself. This will help to keep your code lean and easy to maintain.
Favor declarative programming over imperative programming. This will help to make your code more readable and easier to understand.
Favor imperative programming over functional programming. This will help to make your code more efficient.
Favor functional programming over object oriented programming. This will help to make your code more modular and easier to test.
Avoid deep class trees. They are hard to understand and debug. This will help to make your code more readable and easier to maintain.
Avoid classes with features and favor mix-in classes or traits instead. This will help to make your code more modular and easier to test.
Favor precondition checking over exception handling. This will help to improve the performance of your code.
Favor efficient algorithms over parallel computing. This will help to improve the performance of your code.

Conclusion:

These are just a few of the many good practices that can help you to write better software. By following these practices, you can improve the quality, performance, and maintainability of your code.

Naming Conventions

The name of identifiers in a language can support several characters. In most languages identifier name usually starts with lowercase letters (a..z) or capital letters (A..Z) followed by one or more characters or numbers. No special characters or spaces are permitted in the name except underscore ("_").

A variable name can start or terminate with underscore or can contain underscores. The underscore is equivalent to space. So the identifiers that have space in a JSON or in a database can be mapped to internal variables that use an underscore instead of a space as identifier.

Examples: These are invalid identifiers:

Examples: These are valid identifiers:

Naming variables

Variables usually have a meaning or a purpose therefore variable must have a proper name. Variables can’t use as names the language reserved keywords. Therefore we advise for variables to use a prefix all the time.

"v_" is a good prefix for variables; "p_" is a good prefix for parameters;

Using prefix is good but sometimes this is not good enough. When this is the case, you can give creative names to variables to make your code even more readable.

Example: In next Python example we name a logical variable: URGENT and use "==" operator. By not using a prefix for logical variable we make a very readable program.

# python code
URGENT = True
if situation == URGENT:
    print("this is an emergency")
else:
    print("this is a normal situation")
pass # end if

Your convention: You may setup your own naming conventions. Just make sure all developers in your team follow the same convention. Otherwise some developers will use one style while others will try to use something different and your conceptual brilliance will be shadowed by a messy implementation.

Automatic Formatting

Avoid it! It can cause a disaster when your code is versioned. Automatic formatting is available for some languages and is a program that modify your source code to look nice. I strongly advice against it. You can be fired if you do not listen this advice.

Doing automating formatting for totally new code can be beneficial for learning how your code should look like. You can apply automatic formatting in early stage of a new file but never to an older file. Later code review will be impossible. I advice you to do only manual code re-formatting.

Design Patterns

A design pattern is a general, reusable solution to a commonly occurring problem in software architecture within a given context. There are many recognized architectural patterns and styles. We will elaborate this topic in next article.

Application Tiers

In many software systems we use a database on a server to organize large amount of data. When we use a database server the application is centralized. A database can be used in many different architecture patterns:

What is Client – Server ?

In picture below we can see the general idea of a client-server architecture. All clients are connected to a central server that store the database. The client send messages to the server and receive information. This way all the clients can communicate to the server but they can't communicate to each-other.

data center

Distributed Architecture

What is n-tier architecture?

In this architecture there are several clients connected in a local network. The clients are connector through a "router". The router is connected to an "application server" that is also connected to a database server. Of course, other local networks can be connected to the same "data center".

data center

Multi Tier Architecture

What is peer-to-peer architecture?

A peer-to-peer (P2P) architecture consists of a decentralized network of peers - nodes that are both clients and servers. P2P networks distribute the workload between peers, and all peers contribute and consume resources within the network without the need for a centralized server.

peer 2 peer

P2P Architecture

What is a web service?

A service in general is a kind of application that do not have user interface of it's own. This application start automatic when the server start and resides in memory until the server is shut-down. A web service is a small program that is run by a application server. A web service can create JSON response stream or file on request. The application server can send this response to client using http protocol.

What is a dynamic web page?

The dynamic web page is a special HTML page that is loaded in the web browser and has JavaScript code inside. So the web browser now is smart and has a user interface ready for interaction. Inside the HTML we have AJAX application based on JavaScript. This can send request and receive response from a Web Service. The client application will use JavaScript to parse JSON data and modify the page content.

What is a cloud architecture?

This is general concept of a cloud based architecture. The server is somewhere on the internet and can be one or more servers. Clients are devices and computers distributed over the world.

data center

Cloud Architecture

What is a server-less architecture?

Serverless computing (or serverless for short), is an execution model where the cloud provider (AWS, Azure, or Google Cloud) is responsible for executing a piece of code by dynamically allocating the resources.

Serverless is sometimes referred to as “Functions as a Service” or “FaaS”. Following are the FaaS offerings of the major cloud providers:

Clarification:

Serverless architecture is very different from P2P. It does involve servers, except these servers are not dedicated to your application. Servers are shared between many applications. You pay only for the resources used and not for renting and locking resources for a period of time..

Terminology:

Serverless technology is based on stateless functions that run inside a container. This need a "warm-up" time you have to consider when you call a function. The duration of cold start depends on the runtime (language) and the function size. The architecture of serverless applications must consider these challenges.

Building a Website

To build a website you can use HTML/CSS and JavaScript. HTML/CSS are not Turing complete programming languages. You can do static pages using only HTML. Fortunately the web browsers are programmable platforms. You can interact with these programs using JavaScript.

General approach

Your career will greatly benefit from making a website. You should follow these basic principles:

  1. Make it work
  2. Make it right
  3. Make it fast
  4. Keep it simple

In this order, but number 4 should be considered from start. Complexity can kill a project sooner or later. Making a site work is not so simple and is the first step because you must start with a prototype and then improve.

Front End - HTML5

To do the front-end you need HTML+CSS & JavaScript. If you learn these languages you can make websites but also desktop applications. HTML+CSS are two languages actually. But you learn them together. Some people argue that these are not languages but do not listen to them. These both are programming languages, more precise: data oriented language.

JavaScript is very specific to web programming. It can be used for making a dynamic website. Usually belong to front-end design but can be used also for back-end programming. It has a very small runtime and it can be executed into a browser.

Back end JavaScript

You can write back-end programs using any of the following languages: Python, Java, Julia, Go, Ruby … In general each language has it's own back-end framework. Though when you use a framework it become fuse what part is the front end (View/Model) and what part is the back-end (Model/Controller)

JavaScript has evolved and now you can do the back-end using JavaScript. Using same language for both back-end and front-end can be appealing. This will give you productivity.

For JavaScript back-end you need to use a Node.JS engine and a Web Framework. This framework can be one of: {Ember, Angular, React or Vue}. I think the best framework right now is Vue. React is now more popular and used by companies. Angular people say is overengineered and will be abandoned by Google sooner or later.

Back end Alternatives

Select one of the languages: {Python, Ruby, Julia, Go, Rust, C++, Java, Scala}. These are used for server-side/(back-end) and system programming. These languages are preferred by back-end developers. If you learn at least one language in this category you can perform professional development tasks in a company. You should apply for a job or continue your freelancing activity on next level.

  1. Python is a mandatory language for freelancers. I prefer Ruby, but Python is more popular and is on high demand. Python is not so easy to learn as JavaScript.It is because Python is a multi-paradigm language while JavaScript is a functional language. If you learn python as your first computer language you will understand JavaScript faster.
  2. C language is as easy to learn, but is less useful for freelancers. It is more used for System Programming by companies. Do not start learning the programming concepts using this language. You will have hard time understanding and will get irreparable "brain damage" that is hard to fix later using another language. We recommend Rust instead of C as your first system language.
  3. Go and Rust languages are almost in competition. Rust is better then Go, but Go is more easy to learn than Rust. As a freelancer, you should learn Go but a system programmer should learn Rust. Chose your language careful since Rust is more difficult than Go and both are more difficult to learn than C. However C is not very friendly and unsafe while Rust and Go both are safe languages.
  4. Ruby, Julia and Python languages are in tight competition. Julia is very new but not at all behind. Now you can learn and use Julia for finding a job. This is a very good language in my opinion. I like Julia a lot but I prefer to use Ruby since Julia is not yet available on Amazon AWS cloud and is not yet popular.
  5. Java and SQL are traditional back-end languages. These you should be learning in school. So we do not focus on these languages. However we will have an introductory tutorial to get you started. You can learn these languages if you are looking for a permanent position in a company but these are not good languages for a startup project. Both SQL and Java are harshly criticized and replaced by NoSQL and functional programming languages like Julia, Go and Rust.

SOLID in Web Development

SOLID is a set of five principles for object-oriented design (OOD) that are intended to make software more understandable, flexible, and maintainable. The principles are:

SOLID principles can be applied to any programming language, but they are particularly relevant to web development because web applications are often complex and require a lot of code. By following SOLID principles, developers can create web applications that are easier to understand, maintain, and extend.

Here are some examples of how SOLID principles can be applied to web development:

By following SOLID principles, developers can create web applications that are easier to understand, maintain, and extend. This can lead to shorter development cycles, fewer bugs, and happier users.

Setting-up a project

Here's some things you must do to set-up a project. At the beginning you may be working alone but you will probably add some more people in a few months and it's not going so smoothly if you do not set-up the project properly. Let's say you currently work at a company on some big Web development , software & programming projects. You do everything by yourself from back-end to front-end. What is wrong with this?

It is not very good to do all by yourself. In computer programming we work in a team. Somebody is doing something and someone else is doing something different. The collaboration is helping team members to learn from each other. This is how we can build larger projects.

The 10 steps to create a project

  1. First you must learn to use a version control software, preferably git or mercurial. You check-in the empty project from the beginning. Do not wait until the project grow, it may be too late.
  2. Write unit tests. I've always scoffed at them because they only test the cases you've thought of, and you probably already thought of them when you wrote the code you're testing, but once your project grows and you add people to the team, you're going to wish you'd done it.
  3. Have separate development, test and production servers so you can have people looking at your stuff on test while you break stuff on development environment. Use a labeling or branching system in your version control so you can always go back to the code that's running on each server. If a problem comes up in production while you're working on a new whiz-bang new feature in development, you want to be able to put aside the new feature and fix it in the production version.
  4. Deploying code to development should be automatic as soon as you check in. Deploying to test and production should either be automatic or a single click.
  5. Make sure your boss and other stake holders actually look at the site on test before you deploy to production. Try to get some of the people who will actually use the site involved in usability testing. Listen to them, but don't let them design the thing.
  6. Make sure your code has clear division of responsibility- don't mix the access control in the middle of the business logic and the UI.
  7. Use a web framework like Twitter bootstrap. Sometimes you'll be fighting with it, but it will take a lot of the burden of getting a consistent UI off your hands.
  8. Use a good framework like Svelte or Vue for JavaScript back-end.This will organize your application and will have better integration with the front-end.
  9. If you use Python, use a good framework like Django or Flask. Make sure it supports or at least doesn't prevent you from doing AJAX front-end and asynchronous jobs.
  10. If you like higher performance, try to make responsive web pages using Vanilla JavaScript and CSS. Your page should work on any monitor size from very large to very small. Some users have secondary monitor in portrait mode and some are using multiple monitors. Having the applications design for a fix size is a huge mistake.

Hosting:  After you create a web-site on your computer, you have to deploy it to a web host server to be visible over the internet. Hosting a website is not easy. You need a domain name, and this cost's you money. Then you need to know how to connect to the server and upload files.

Blog Articles

For more advanced topics you should follow my blog. I post frequently and you can find valuable resources. I explain fundamental concepts and mention use cases of different technologies. You can create software only if you understand the components you can use to establish a good architecture for your project.

I hope you enjoy this reading. Good luck!


Read next: Design Patterns