Software Architecture

Growing software

Linux kernel - number of lines of code (forrás: Wikipedia)

The more, the better?

if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent"

E.W. Dijkstra EWD 1036


Every line of code written comes at a price: maintenance. To avoid paying for a lot of code, we build reusable software. The problem with code re-use is that it gets in the way of changing your mind later on.

tef - Write code that is easy to delete, not easy to extend

Complex Software

How to measure? - Cyclomatic complexity

Cyclomatic complexity measures the number of linearly independent paths through the method, which is determined by the number and complexity of conditional branches. A low cyclomatic complexity generally indicates a method that is easy to understand, test, and maintain. The cyclomatic complexity is calculated from a control flow graph of the method and is given as follows:

cyclomatic complexity = the number of edges - the number of nodes + 1

where a node represents a logic branch point and an edge represents a line between nodes.

The rule reports a violation when the cyclomatic complexity is more than 25.

CA1502: Avoid excessive complexity

Issues with cyclomatic complexity

  • Not every statement is equal
    • if, while, for and case statements considered as identical
  • Nesting
    • it doesn’t account for nesting

NPATH complexity

The NPath complexity of a method is the number of acyclic execution paths through that method. A threshold of 200 is generally considered the point where measures should be taken to reduce complexity.

NPathComplexity

Consider writing a unit test and you have a function with an NPath complexity of 16. This means that if you need want 100% code coverage you need to test for 16 possible outcomes and that would end up in pretty messy tests.

Niklas Modess - NPath complexity and cyclomatic complexity explained

Complex vs. complicated

Michael Bykovski: Simple vs. Complicated vs. Complex vs. Chaotic

Complexity: Accidental vs. Essential

Accidental Complexity is something that can be simplified by a new idea, design, technique, procedure or approach. Essential Complexity is something that can't be simpler or something that loses value when it becomes simpler. Identifying the difference between accidental and essential complexity is a fundamental design technique.

John Spacey - Complexity: Accidental vs. Essential

What is Software Architecture

"Architecture" is a term that lots of people try to define, with little agreement. There are two common elements: One is the highest-level breakdown of a system into its parts; the other, decisions that are hard to change.

Martin Fowler - Patterns of Enterprise Application Architecture

All architecture is design but not all design is architecture. Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change.

Grady Booch

In most successful software projects, the expert developers working on that project have a shared understanding of the system design. This shared understanding is called ‘architecture.’ This understanding includes how the system is divided into components and how the components interact through interfaces. These components are usually composed of smaller componnets, but the architecture only includes the components and interfaces that are understood by all the developers.

Ralph Johnson, XP mailing list

Miért kell ez?

Architecture is the decisions that you wish you could get right early in a project

-- Ralph Johnson

  • https://gbksoft.com/blog/why-you-need-a-software-architect-for-your-project/
  • https://www.martinfowler.com/articles/designDead.html#SoIsDesignDead
  • https://www.codeproject.com/Articles/1064240/Introduction-to-Software-Architecture

Hogyan lesz egy ilyenünk?

Architecture decision records

Alább látható a Michael Nygard féle sablon: Documenting Architecture Decisions

# ADR template by Michael Nygard

This is the template in [Documenting architecture decisions - Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions).
You can use [adr-tools](https://github.com/npryce/adr-tools) for managing the ADR files.

In each ADR file, write these sections:

# Title

## Status

What is the status, such as proposed, accepted, rejected, deprecated, superseded, etc.?

## Context

What is the issue that we're seeing that is motivating this decision or change?

## Decision

What is the change that we're proposing and/or doing?

## Consequences

What becomes easier or more difficult to do because of this change?

Design Principles

4C: Complete, Compliant, Clear, Concise

Rob Pike's 5 Rules of Programming

  1. You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.
  2. Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.
  3. Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.)
  4. Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures.
  5. Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.

Pike's rules 1 and 2 restate Tony Hoare's famous maxim "Premature optimization is the root of all evil." Ken Thompson rephrased Pike's rules 3 and 4 as "When in doubt, use brute force.". Rules 3 and 4 are instances of the design philosophy KISS. Rule 5 was previously stated by Fred Brooks in The Mythical Man-Month. Rule 5 is often shortened to "write stupid code that uses smart objects".

forrás

Zen of Python1

The Zen of Python is a collection of 19 "guiding principles" for writing computer programs that influence the design of the Python programming language. 2

  1. Beautiful is better than ugly.
  2. Explicit is better than implicit.
  3. Simple is better than complex.
  4. Complex is better than complicated.
  5. Flat is better than nested.
  6. Sparse is better than dense.
  7. Readability counts.
  8. Special cases aren't special enough to break the rules.
  9. Although practicality beats purity.
  10. Errors should never pass silently.
  11. Unless explicitly silenced.
  12. In the face of ambiguity, refuse the temptation to guess.
  13. There should be one-- and preferably only one --obvious way to do it.
  14. Although that way may not be obvious at first unless you're Dutch.
  15. Now is better than never.
  16. Although never is often better than right now.
  17. If the implementation is hard to explain, it's a bad idea.
  18. If the implementation is easy to explain, it may be a good idea.
  19. Namespaces are one honking great idea -- let's do more of those!

Zen of Zyg3

  • Communicate intent precisely.
  • Edge cases matter.
  • Favor reading code over writing code.
  • Only one obvious way to do things.
  • Runtime crashes are better than bugs.
  • Compile errors are better than runtime crashes.
  • Incremental improvements.
  • Avoid local maximums.
  • Reduce the amount one must remember.
  • Focus on code rather than style.
  • Resource allocation may fail; resource deallocation must succeed.
  • Memory is a resource.
  • Together we serve the users.

3 https://ziglang.org/documentation/0.8.0/#Zen

The 23 Gang of Four Design Patterns

Teljes összefoglaló, ahol mindegyikhez van magyarázat, UML diagram és C# kód.

Abstract FactoryFacadeProxy
AdapterFactory MethodObserver
BridgeFlyweightSingleton
BuilderInterpreterState
Chain of ResponsibilityIteratorStrategy
CommandMediatorTemplate Method
CompositeMementoVisitor
DecoratorPrototype

Topologies

Introduction to Software Architecture

Layered Architechture

Message Bus Architecture

Server-Client Architecture

C4 model

Level 1: System Context diagram

Shows the software system you are building and how it fits into the world in terms of the people who use it and the other software systems it interacts with.

Simon Brown - The C4 Model for Software Architecture

Level 2: Container diagram

Zooms into the software system, and shows the containers (applications, data stores, microservices, etc.) that make up that software system. Technology decisions are also a key part of this diagram.

Simon Brown - The C4 Model for Software Architecture

Level 3: Component diagram

Zooms into an individual container to show the components inside it. These components should map to real abstractions (e.g., a grouping of code) in your codebase.

Simon Brown - The C4 Model for Software Architecture

Level 4: Code

Finally, if you really want or need to, you can zoom into an individual component to show how that component is implemented.

Simon Brown - The C4 Model for Software Architecture

Versioning

Semantic Versioning

Calendar Versioning

  • "CalVer is a versioning convention based on your project's release calendar, instead of arbitrary numbers."
  • YYYY.MINOR.MICRO
  • website

ZeroVer: 0-based Versioning

  • "Your software's major version should never exceed the first and most important number in computing: zero."
  • e.g.: 0.4.1
  • website