Architectural Design Patterns - All you need to know about

Architectural Design Patterns - All you need to know about

Think > Design > Code > Maintain

·

15 min read

By Vikipediaaa , Website: Vikas Saraf

All amazing software in the world have TWO things in common:

  • Great Design
  • Easy Maintainability

50n14v.jpg

As a web developer, one should always architect and design software solutions with maintainability in mind. In this article, we are going to look into detail about different Architectural Patterns and how they are useful.

Contents

Generic

  • KISS (Keep It Simple Silly)
  • YAGNI
  • Do The Simplest Thing That Could Possibly Work
  • Separation of Concerns
  • Keep Things DRY
  • Code For The Maintainer
  • Avoid Premature Optimization
  • Boy-Scout Rule

Inter-Module/Class

  • Minimise Coupling
  • Law of Demeter
  • Composition Over Inheritance
  • Orthogonality
  • Robustness Principle
  • Inversion of Control

Module/Class

  • Maximise Cohesion
  • Liskov Substitution Principle
  • Open/Closed Principle
  • Single Responsibility Principle
  • Hide Implementation Details
  • Curly's Law
  • Encapsulate What Changes
  • Interface Segregation Principle
  • Command Query Separation

KISS (Keep It Simple Silly) :

  • A simple solution is better than a complex one—even if the solution looks stupid.
  • A solution is better when it uses less inheritance, less polymorphism, fewer classes, etc.
  • Simpler solutions are easier to maintain, i.e. detecting and correcting defects is more effective and efficient.

YAGNI (You aren't gonna need it) :

  • don't implement something until it is necessary.
  • The best way to implement code quickly is to implement less of it. The best way to have fewer bugs is to implement less code.

Do The Simplest Thing That Could Possibly Work :

  • First, implement a new capability in the simplest way you can think of that "could possibly work". Don't build a lot of amazing superstructure, don't do anything fancy, just put it in. Use an if statement, even. Make the code pass the UnitTests for the new feature (and all features, as always).

  • Second, and this is critical to the rule, refactor the system to be the simplest possible code including all the features it now has. Follow the rule of OnceAndOnlyOnce and the other code quality rules to make the system as clean as it can possibly be.

  • With each increment of an IterativeDevelopment one should do the simplest thing that could possibly work. To do this, you have to know at least two ways to do the thing. That way, you can at least pick the simpler, if not the simplest.

Separation of Concerns :

  • Separating a computer program into distinct sections, such that each section addresses a separate concern.
  • For example the business logic of the application is a concern and the user interface is another concern. Changing the user interface should not require changes to business logic and vice versa.
  • When concerns are well-separated, individual sections can be reused, as well as developed and updated independently.
  • Break program functionality into separate modules that overlap as little as possible.

Keep things DRY :

  • Each significant piece of functionality in a program should be implemented in just one place in the source code. Where similar functions are carried out by distinct pieces of code, it is generally beneficial to combine them into one by abstracting out the varying parts.
  • Duplication (inadvertent or purposeful duplication) can lead to maintenance nightmares, poor factoring, and logical contradictions.
  • A modification of any single element of a system does not require a change in other logically unrelated elements.
  • Additionally, elements that are logically related all change predictably and uniformly, and are thus kept in sync.
  • Put business rules, long expressions, if statements, math formulas, metadata, etc. in only one place.
  • Identify the single, definitive source of every piece of knowledge used in your system, and then use that source to generate applicable instances of that knowledge (code, documentation, tests, etc).

Code For The Maintainer :

  • Maintenance is by far the most expensive phase of any project.
  • Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.
  • Always code and comment in such a way that if someone a few notches junior picks up the code, they will take pleasure in reading and learning from it.

Avoid Premature Optimization :

  • Don't optimize until you need to, and only after profiling you discover a bottleneck optimize that.
  • After optimization, it might be harder to read and thus maintain.

Minimise Coupling :

  • Coupling between modules/components is their degree of mutual interdependence; lower coupling is better. In other words, coupling is the probability that code unit "B" will "break" after an unknown change to code unit "A".
  • Eliminate, minimise, and reduce complexity of necessary relationships.
  • By hiding implementation details, coupling is reduced.

Law of Demeter :

  • Don't talk to strangers.
  • It usually tightens coupling
  • It might reveal too many implementation details
  • A method of an object may only call methods of :
    • The object itself.
    • An argument of the method.
    • Any object created within the method.
    • Any direct properties/fields of the object.

Composition Over Inheritance

  • Less coupling between classes.
  • Using inheritance, subclasses easily make assumptions and break LSP.
  • Test for LSP (substitutability) to decide when to inherit.
  • Compose when there is a "has a" (or "uses a") relationship, inherit when "is a".

Orthogonality

  • The basic idea of orthogonality is that things that are not related conceptually should not be related in the system.
  • It is associated with simplicity; the more orthogonal the design, the fewer exceptions.
  • This makes it easier to learn, read and write programs in a programming language.
  • The meaning of an orthogonal feature is independent of context; the key parameters are symmetry and consistency.

Robustness Principle

  • Be conservative in what you do, be liberal in what you accept from others
  • In order to be able to evolve services you need to ensure that a provider can make changes to support new demands while causing minimal breakage to their existing clients.
  • Code that sends commands or data to other machines (or to other programs on the same machine) should conform completely to the specifications, but code that receives input should accept non-conformant input as long as the meaning is clear.

Inversion of Control :

  • Inversion of Control is also known as the Hollywood Principle, "Don't call us, we'll call you".
  • It is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework.
  • Inversion of control carries the strong connotation that the reusable code and the problem-specific code are developed independently even though they operate together in an application.
  • Inversion of control is used to increase the modularity of the program and make it extensible.
  • Inversion of control can be implemented using Factory pattern, Service Locator pattern, Dependency Injection, contextualized lookup, Template Method pattern, Strategy pattern

Maximise Cohesion :

  • Cohesion of a single module/component is the degree to which its responsibilities form a meaningful unit; higher cohesion is better.

Liskov Substitution Principle :

  • The LSP is all about the expected behavior of objects.
  • Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.

Open/Closed Principle :

  • Software entities (e.g. classes) should be open for extension, but closed for modification. I.e. such an entity can allow its behavior to be modified without altering its source code.
  • Improve maintainability and stability by minimizing changes to existing code.
  • Write classes that can be extended (as opposed to classes that can be modified).
  • Expose only the moving parts that need to change, hide everything else.

Single Responsibility Principle :

  • Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. Responsibility can be defined as a reason to change, so a class or module should have one, and only one, reason to change.
  • Maintainability: changes should be necessary only in one module or class.

Hide Implementation Details :

  • A software module hides information (i.e. implementation details) by providing an interface, and not leak any unnecessary information.
  • When the implementation changes, the interface clients are using does not have to change.
  • Minimize accessibility of classes and members.
  • Don’t expose member data in public.
  • Avoid putting private implementation details into a class’s interface.
  • Decrease coupling to hide more implementation details.

Curly's Law :

  • Curly's Law is about choosing a single, clearly defined goal for any particular bit of code: Do One Thing.

Encapsulate What Changes :

  • A good design identifies the hotspots that are most likely to change and encapsulates them behind an API. When an anticipated change then occurs, the modifications are kept local.
  • To minimize required modifications when a change occurs
  • Encapsulate the concept that varies behind an API
  • Possibly separate the varying concept into its own module

Interface Segregation Principle :

  • Reduce fat interfaces into multiple smaller and more specific client specific interfaces. An interface should be more dependent on the code that calls it than the code that implements it.
  • If a class implements methods that are not needed the caller needs to know about the method implementation of that class. For example if a class implements a method but simply throws then the caller will need to know that this method shouldn't actually be called.
  • Avoid fat interfaces. Classes should never have to implement methods that violate the Single responsibility principle.

Boy-Scout Rule :

  • The Boy Scouts of America have a simple rule that we can apply to our profession: "Leave the campground cleaner than you found it". The boy-scout rule states that we should always leave the code cleaner than we found it.
  • When making changes to an existing codebase the code quality tends to degrade, accumulating technical debt. Following the boyscout rule, we should mind the quality with each commit. Technical debt is resisted by continuous refactoring, no matter how small.
  • With each commit make sure it does not degrade the codebase quality.
  • Any time someone sees some code that isn't as clear as it should be, they should take the opportunity to fix it right there and then.

Command Query Separation :

  • The Command Query Separation principle states that each method should be either a command that performs an action or a query that returns data to the caller but not both. Asking a question should not modify the answer.
  • With this principle applied the programmer can code with much more confidence. The query methods can be used anywhere and in any order since they do not mutate the state. With commands one has to be more careful.
  • By clearly separating methods into queries and commands the programmer can code with additional confidence without knowing each method's implementation details.
  • Implement each method as either a query or a command
  • Apply naming convention to method names that implies whether the method is a query or a command