19 CEO Dashboard Examples for Business Leaders
Let's rewind to the 1990s. Data used to be stored on servers and CEOs relied on basic tools to make optimal decisions. No dashboards, nothing. When you use Power BI with a solid...
Kapil Panchal - September 23, 2021
Listening is fun too.
Straighten your back and cherish with coffee - PLAY !
In C#, SOLID design principles are basic design principles. SOLID Principles enable us to overcome most of the design problems. In the 1990s, Robert Martin compiled these principles. These principles provided us with many ways to overcome tight coupled code and least encapsulation.
Usually, Developers start the application building process with good and clean designs according to their experience. But, as time passes, applications might develop bugs. The application has to be changed for every new feature or change request. After a long time, we might need to put more effort, even for small tasks and it might require a lot of time and energy. But as they are part of software development, we cannot refuse them as well.
Here are few design issues which are causing damage in any software in most cases:
To overcome these issues, we can implement the following tactics:
Here, SOLID stands for as shown below:
S = Single Responsibility Principle
O = Open Closed Principle
L = Liskov Substitution Principle
I = Interface Segregation Principle
D = Dependency Inversion Principle
As per the concepts of the Single Responsibility Principle, every module of the software must have only a single reason to change. Everything in that particular class
This means, that every single class or class-like structure in our code must have only one job to perform. All the things in that class must be related to one single purpose. Our class must not be multifunctional at all.
The Single Responsibility Principle represents a way of recognizing classes at the App’s design phase making you think of all the ways a class can change. When you see an excellent clarity of operation requests, a fine separation of responsibilities occurs.
Let us comprehend this with an example.
public class UserService { EmailService _emailService; DbContext _dbContext; public UserService(EmailService aEmailService, DbContext aDbContext) { _emailService = aEmailService; _dbContext = aDbContext; } public void Register(string email, string password) { if (!_emailService.ValidateEmail(email)) throw new ValidationException("Email is not an email"); var user = new User(email, password); _dbContext.Save(user); emailService.SendEmail(new MailMessage("myname@mydomain.com", email) {Subject="Hi. How are you!"}); } } public class EmailService { SmtpClient _smtpClient; public EmailService(SmtpClient aSmtpClient) { _smtpClient = aSmtpClient; } public bool virtual ValidateEmail(string email) { return email.Contains("@"); } public bool SendEmail(MailMessage message) { _smtpClient.Send(message); } }
The Open/closed principle says "A software module/class is opened for the extension and closed for editing".
Here, "Open for extension" means that we should design our module/class so that the new feature can only be added when new requirements are generated. Here, "Open for extension" means that we should design our module/class so that the new functionality can only be added when new requirements are created. We should never tamper with it until we find some bugs. As mentioned, a class should be open for extensions, we can use inheritance for this. OK, let's take one example.
public class Rectangle: Shape { public double Height {get;set;} public double Width {get;set;} public override double Area() { return Height * Width; } } public class Circle: Shape { public double Radius {get;set;} public override double Area() { return Radius * Radius * Math.PI; } } public class AreaCalculator { public double TotalArea(Shape[] arrShapes) { double area=0; foreach(var objShape in arrShapes) { area += objShape.Area(); } return area; } }
Now our code tracks SRP and OCP at once. When you introduce a new form deriving from the abstract class "Shape", you do not need to change the class "AreaCalculator".
The Liskov Substitution Principle (LSP) states that "you should be able to use any derived class instead of a parent class and have it behave in the same manner without modification". It guarantees that a derived class does not affect the behavior of the parent class, in other words, that a derived class must be substitutable for its basic class.
This principle is just an extension of the Open-Closed Principle and it means that we need to make sure that the new derived classes extend the basic classes without changing their behavior. I will explain it by employing a concrete example that violates the LSP.
A dad is a doctor and his son wants to be a cricket player. So here the son cannot replace his father even if the two belong to the same family hierarchy.
public class SqlFileManager { public string GetTextFromFiles(ListaLstReadableFiles) { StringBuilder objStrBuilder = new StringBuilder(); foreach(var objFile in aLstReadableFiles) { objStrBuilder.Append(objFile.LoadText()); } return objStrBuilder.ToString(); } public void SaveTextIntoFiles(List aLstWritableFiles) { foreach(var objFile in aLstWritableFiles) { objFile.SaveText(); } } }
The principle of segregation of interfaces stipulates that customers should not be forced to implement interfaces they do not use. Rather than a fat interface, many small interfaces are preferred depending on method groups, each serving as a sub-module.
It may be defined differently. An interface should be closer to the code which uses it than to the code which implements it. So the methods of the interface are defined by the methods that the client code needs instead of the methods that the class implements. As a result, clients should not be forced to depend on interfaces they do not use.
As with classes, each interface needs to have a specific purpose/responsibility (see SRP). You should not have to implement an interface when your object does not share this goal. The larger the interface, the more likely it is that it includes methods that not every implementer can do. That's the essence of the Interface Segregation Principle. Let's start with an example.
public class TeamLead: IProgrammer, ILead { public void AssignTask() { //Code to assign a Task } public void CreateSubTask() { //Code to create a sub-task from a task. } public void WorkOnTask() { //code to implement to work on the Task. } }
The Dependency Inversion Principle says that all the high-level modules and classes must not depend on low-level modules and classes. All must depend upon abstractions. Also, abstractions must not depend upon details of it, instead, they should depend upon abstractions.
public class DataExporter { public void ExportDataFromFile() { ExceptionLogger _exceptionLogger; try { //code to export data from files to database. } catch(IOException ex) { _exceptionLogger = new ExceptionLogger(new DbLogger()); _exceptionLogger.LogException(ex); } catch(SqlException ex) { _exceptionLogger = new ExceptionLogger(new EventLogger()); _exceptionLogger.LogException(ex); } catch(Exception ex) { _exceptionLogger = new ExceptionLogger(new FileLogger()); _exceptionLogger.LogException(ex); } } }
In this article, we discussed the C# SOLID principles for better coding standards and how to make it as fruitful as possible. We also saw a few examples to deeply understand these concepts.
Build Your Agile Team
Let's rewind to the 1990s. Data used to be stored on servers and CEOs relied on basic tools to make optimal decisions. No dashboards, nothing. When you use Power BI with a solid...
Imagine walking into a meeting where critical decisions need to be made—fast. You need clear, flexible data that you can analyze on the spot. But what if your insights are locked inside...
Clear insights mean smarter decisions, and this is what data storytelling does. It helps you speak a language that you quickly understand. Like for example, you are a CTO dealing with...