Software Design Principles

Software Design Principles

Software Architecture

Software architecture at high level has patterns that define the overall shape and structure of software applications.A level down, architecture that is specifically related to the purpose of the software application.Coming another step down it involves the modules and their interconnections, this is the field that concerns us the most as this is the field of application of design principles and patterns.

Software design when new looks perfect. The design of many software applications begins as a vital image in the minds of its designers. At this stage it is clean, elegant, and compelling. But with time changing requirements can introduce unplanned and new dependencies that can degrade the design and with it the maintainability of the software.We, as software engineers, know full well that requirements change. Indeed, most of us realise that the requirements document is the most volatile document in the project. If our designs are failing due to the constant rain of changing requirements, it is our designs that are at fault.Thus the software design should be such that it can cater to the changing requirements and the changes introduced to fulfil the requirements should also abide by the good design principles.

 Four Primary Symptoms of Rotting Design

Rigidity -  Rigidity is the tendency for software to be difficult to change, even in simple ways. Every change causes a cascade of subsequent changes in dependent modules

Fragility - Closely related to rigidity is fragility. Fragility is the tendency of the software to break in many places every time it is changed.

Immobility - Immobility is the inability to reuse software from other projects or from parts of the same project. This happens because of cascade of dependencies associated with the desirable part of the code that makes separation of desirable from undesirable code a lot of effort and time.

Viscosity -  Viscosity comes in two forms: viscosity of the design, and viscosity of the environment.When the design preserving methods are harder to employ than the hacks, then the viscosity of the design is high.Viscosity of environment comes about when the development environment is slow and inefficient, hence to reduce burden on environment the design goes for a toss.

Thus to guide the software design we have principles that help to manage dependencies between modules and keep them under check to prevent the rotting.A design rots because of a common thread that the modules have undesirable dependencies and are coupled.Some of these principles will be discussed below.

  • SOLID

SOLID is an acronym formed by the names of 5 design principles centred around better code design, maintainability, and extendability. The principles were first introduced by Robert Martin (more familiar in the developer circles as Uncle Bob) in his 2000 paper Design Principles and Design Patterns. These principles are Object Oriented design principles.

Single Responsibility Principle - This principle says that a code component should just have one responsibility which means it should just have a single reason to change.For example this is a clear violation of single responsibility as this class has text edit as well as text printing responsibilities while we could have segregated them easily to make the class look simple. Spring framework also demonstrates the abidance of single responsibility by having different layers each having its own responsibility like controller has light weight methods and service layer handles all the business logic and repository layer has the responsibility to deal with data bases. 

class Text {
 
 String text;
 
 String getText() { ... }

 void setText(String s) { ... }
 
 /*methods that change the text*/

 void allLettersToUpperCase() { ... }

 void findSubTextAndDelete(String s) { ... }

 /*method for formatting output*/

  void printText() { ... }
}

Open/Close Principle - Modules should be open for extension but closed for modification.We want to be able to change what the modules do(extend behaviour), without changing the source code of the modules(closed for modifications). All of these techniques are based upon abstraction. Indeed, abstraction is the key to the OCP. The below example abides to OCP as a new shape addition requires no code changes for already existing code.

No alt text provided for this image

Liskov Substitution Principle - Derived classes must be usable through the base class interface without the need for the user to know the difference.This simply means that if one class is derived from another we should be able to easily substitute the derived class in place of the base class without hampering any functionality and hence without the user noticing the change and if we are not possible to do the substitution its a failure to abide by this principle and hence the inheritance relationship we used is not the correct one.

No alt text provided for this image

Interface Segregation Principle – Many client specific interfaces are better than one general purpose interface. If there is a service that is accessed by different types of clients each requiring to call different methods then rather than loading the service with all the methods the clients need, we can have specific interfaces for each client which our service can implement. This reduces rigidity and allows for better maintainability .

No alt text provided for this image

Dependency Inversion Principle – Depend upon Abstractions. Do not depend upon concretions.If the OCP(open/close principle) states the goal of OO architecture, the DIP states the primary mechanism. Dependency Inversion is the strategy of depending upon interfaces or abstract functions and classes, rather than upon concrete functions and classes.

High level modules depend upon lower level modules, which depend upon yet lower level modules, etc.. A little thought should expose this dependency structure as intrinsically weak. The high level modules deal with the high level policies of the application. These policies generally care little about the details that implement them. Why then, must these high level modules directly depend upon those implementation modules? An object oriented architecture shows a very different dependency structure, one in which the majority of dependencies point towards abstractions. Moreover, the modules that contain detailed implementation are no longer depended upon, rather they depend themselves upon abstractions. Thus the dependency upon them has been inverted.

No alt text provided for this image

Apart from the SOLID principles discussed we have some others which help guide the design process and lead to better development.

  • DRY – It stands for Do not Repeat Yourself, this principle states that “Every piece of knowledge(code) must have a single, unambiguous, authoritative representation within a system”. This helps us to write scalable, maintainable and reusable code.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. Additionally, elements that are logically related all change predictably and uniformly, and are thus kept in sync.We can use Abstractions for example to keep common code at one place.
  • KISS – It is an acronym for keep it simple, stupid, is a design principle noted by the U.S. Navy in 1960. 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.
  • YAGNI – It is as acronym for You Arn’t Gonna Need It. This principle states that always implement things when you actually need them never implements things before you need them.Never just foresee that we might need them.
  • Principle of Least Knowledge – Also known as Law of Demeter, it is a is a design principle which provides guidelines for designing a system with minimal dependencies. It is typically summarized as “Only talk to your immediate friends.”The rules promoted by this principle are:
  1. Each unit should have only limited knowledge about other units: only units “closely” related to the current unit.
  2. Each unit should only talk to its friends; don’t talk to strangers.
  3. Only talk to your immediate friends.

And now let’s change a bit the rules above and apply them to object-oriented programming. Imagine that we have a class which implements a given method. This method should only call the following objects:

  1. The object that owns this method.
  2. Objects passed as arguments to the method.
  3. Objects that are dependencies of the owner instance (are held in instance variables).
  4. Any object which is created locally in the method.
  5. Global objects that can be accessed by the owner instance within the method.

Thus we have seen some of the most common design principles that can help develop maintainable and extendible software solutions which don’t rot with time.

Sources of Knowledge

  • https://web.archive.org/web/20150906155800/https://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf
  • https://www.ericfeminella.com/blog/2008/02/02/principle-of-least-knowledge/
  • https://dzone.com/articles/software-design-principles-dry-and-kiss

要查看或添加评论,请登录

Aneshka Goyal的更多文章

  • Introduction to Distributed Tracing

    Introduction to Distributed Tracing

    What is Distributed Tracing? The word tracing is to trace the request as it flows through the system. Since modern…

    2 条评论
  • Introduction to Service Discovery

    Introduction to Service Discovery

    What is Service Discovery? Service Discovery as the name suggests allows us to know or discover where each instance of…

  • Introduction to Micro frontend

    Introduction to Micro frontend

    What is Micro frontend? The term “micro frontends” debuted in the 2016 ThoughtWorks Technology Radar guide. At its…

  • Introduction to Pub-Sub and Streams with Redis&SpringBoot

    Introduction to Pub-Sub and Streams with Redis&SpringBoot

    Publish/Subscribe Problem: Let's say we have synchronous messaging between two components of our system called as…

    2 条评论
  • Introduction to Time Series Database - InfuxDB

    Introduction to Time Series Database - InfuxDB

    What is Time Series Data? As the title of the blog depicts we would be discussing about time series databases and in…

    1 条评论
  • Introduction to Ontology

    Introduction to Ontology

    What is Ontology? An ontology is a formal and structural description of knowledge about a specific domain. Knowledge is…

  • From Java 17 to Java 21 - Features and Benefits

    From Java 17 to Java 21 - Features and Benefits

    Java has been constantly evolving with new features and enhancements. With the recent LTS (Long term support) version…

    2 条评论
  • Vault Authentication and Springboot integration

    Vault Authentication and Springboot integration

    What is Vault? Vault is an identity-based secrets and encryption management system. A secret is anything that we want…

  • Introduction to gRPC with Spring boot

    Introduction to gRPC with Spring boot

    Overview RPC stands for remote procedure calls. In this the client is able to directly invoke a method on server…

    6 条评论
  • Introduction to Triple Crown

    Introduction to Triple Crown

    Organizations are always trying to improve how they work, in order to increase efficiency and reduce errors. This…

    4 条评论

社区洞察

其他会员也浏览了