Loosely Coupling in Software Design: A Dash of .NET - Ep. 8
3K views
Feb 23, 2024
Join this live session with Stephen Simon ft. Tural Suleymani for the next episode of A Dash of .NET - live show on February 22, at 09:30 PM (PST). This session talks about the importance of high cohesion and loosely coupling in programming. No matter what languages you're using, they are really important topics to understand
View Video Transcript
0:00
Have you ever been in a situation where you changed one line of code and your entire program
0:09
stopped working? I have been there and I believe you have been there too
0:13
Today we're going to talk about a really interesting topic that is about loose coupling and talk
0:18
about this really interactive topic and something that everyone can relate. We have Tural Sulemani
0:26
I hope that's how you say his last name. He's a senior .NET developer, very active in the community, C-Sharp Content MVP
0:33
And we all love him there. So without any further ado, let's bring Tural
0:37
Hi Tural, welcome to the show. Hey Simon, thank you very much for having me
0:42
How are you doing? I'm doing absolutely great Tural. Thank you for accepting the invitation
0:46
You know, finally we get to meet you and finally the entire community gets to see how handsome
0:52
Tural is. Sounds a little bit scary. Tural, we're going to do chit-chat towards the end of this session. I'm not going to take much of time
0:56
I'll add your screen to the presentation and I'll let you take it from there. Exactly
1:11
Okay, in this session we're going to talk about loose coupling in software design
1:17
I think this is one of the important topics in software design
1:21
And for me, the software design starts from the high cohesion and loose coupling
1:26
This is my personal opinion. Why? Because when you dive into details of software design, you're actually learning the loose
1:34
coupling and high cohesion in more detail. Let's see what we have in our agenda
1:40
We'll talk about the roles of high cohesion and loose coupling in software design
1:44
And of course, we'll dive into details of loose coupling. There are a lot of forms of loose coupling, but I will mention only the most important ones. Okay
1:54
So first things first, let's try to understand first what is modularization
2:01
What is a software? A software is a problem. So there is a problem and we are trying to solve the problem using some sort of programming
2:10
language technologies. So we are building some sort of application. And we are trying to handle complexity in this application using divide and conquer principle. Okay
2:25
So we are dividing a complex software system into smaller, more manageable models with
2:31
clear tasks and boundaries. From the example of microservice, let me explain this concept
2:37
So we have this sort of microservice and microservice consists from smaller services. Okay
2:44
And these services have their own bounded context. And when we are dealing with a big problem, we are trying to divide it into smaller tasks
2:56
You can think about it like a small problem. Okay? Right now we have three small problems
3:03
And in this case, every microservice may have more than one modules
3:10
Actually, they will have a lot of submodules in there. Okay? So in this case, let's say this is our account microservice
3:19
This is our customer microservice. In customer microservice, we have 20 modules
3:24
Here we have 25 submodules. So these submodules should have tightly coupled relation between each other because they have
3:34
one single bounded context. And they have one huge reason to change
3:40
They are tightly coupled. This is the concept of high cohesion inside one module
3:48
But we need to communicate between these modules to have one single application, big application. Okay
3:57
In this case, we are trying to somehow, it doesn't matter, you're building a synchronous
4:02
communication, asynchronous communication between these microservices. At the end, we are trying to have loosely coupled communication between microservices. Why
4:13
Because we need extensibility. We need to change these modules without depending with each other. Okay
4:21
This is how we are dealing with high cohesion and loosely coupling
4:25
In general, we have these loosely coupling elements. These are forms of loosely coupling
4:32
We'll start to talk about content coupling. Then we have a lot of other coupling stuff in this presentation
4:39
I just demoed that with colors that we have these six items
4:45
And first we'll start from content coupling and we'll end with data coupling
4:49
And in the middle, we have different sort of couplings. We'll talk about it
4:54
For me, the high cohesion and loosely coupling, it looks like union symbol. Okay
5:02
You cannot create an application that is fully modular. There is no need to create fully modular application
5:10
Your application should consist from static and dynamic elements. This side, let's say our static elements, this side are our dynamic elements
5:21
So they should live together to have a big application. This is how we are dealing with complexity
5:31
If you think to deal with complexity to make fully dynamic application, this is not correct
5:39
There is no need always to have interfaces, abstract classes everywhere if you're using
5:44
C-sharp language. So your application should consist from static elements and also from the dynamic elements. Okay
5:53
And loosely coupling. Loosely coupling is about unrelated things. So in our previous scenario, there was three microservices
6:03
And these microservices by itself, they are unrelated things. Yeah, of course, from the B context, they are related with each other
6:11
But in general, they are unrelated things. For example, customer is doing with customer things, customer business operations, order
6:21
is dealing with order operations. So they are completely unrelated. It is possible for us just to grab this microservice and use in another context with other applications. Okay
6:33
So loosely coupling occurs between two models. But high cohesion is inside one model
6:41
When you are building an application, you should take into account that you should create
6:48
loosely coupled relation between elements that these elements are unrelated elements. So loosely coupling is about unrelated things that should change independently
7:02
And of course, there are tons of benefits of loosely coupling, high cohesion
7:06
Let's talk about the benefits of loosely coupling. It helps us to increase maintainability, improve reusability
7:13
From the scalability perspective, it is really good to use loosely coupling
7:18
And of course, it provides us a greater flexibility. I don't want to talk much about the theoretical stuff
7:27
You can find more information on the internet. But let's focus on the practical stuff. Okay
7:32
Let's talk about the loosely coupling, the elements of loosely coupling. First one is our content coupling
7:42
This is really important to understand. It doesn't matter if you are a junior developer, middle developer, double middle, triple middle
7:51
It actually doesn't matter if you are a software architect. You should understand this concept, the high cohesion and loosely coupling to write a better code
8:01
This is really important. So what is the content coupling? This content coupling occurs when different modules, let's say we have two modules and
8:11
we want to communicate with each other. They want to communicate with each other
8:16
We are directly referring and manipulating to the second module's internal data or implementation details
8:27
So you should encapsulate your logic and you shouldn't provide your other modules to directly
8:34
interact your module's data structure, internal data and implementation details. This is a simple example here for the content coupling
8:45
For example, some function here. Okay? And we have calculator at the class
8:50
I will show you the example from the C Sharp perspective, but if you know C Sharp, JVA
8:57
doesn't matter. They are high level language. So you should feel confident with these examples
9:03
In my case, what I'm trying to do, I'm trying to calculate first number and second number
9:09
and set result to calculator again. This is a huge problem because the responsibility of calculator is calculate, but you're another
9:21
method trying not to delegate but directly calculate and set results. So you are referring to internal data
9:33
This is our first number. Second number is our internal data. They are just properties
9:41
But you are directly referring to the result. The calculator should encapsulate the calculation logic and should not provide you to set data
9:53
like this. In this case, you should just delegate. You see, we are just delegating the responsibility to calculator and we are getting result from calculator
10:04
That's how it should be. Okay? That's how we are going to avoid this content coupling problem
10:13
And we also have in Visual Studio, we have a second example here
10:19
I've created a lot of interesting examples for you. So let me just open an example here
10:25
So this is just simple cart class. Okay? There is no business logic right now
10:32
What I am trying to do, I'm just trying to, for the cart number, I am trying to assign
10:37
some number. As you can see, this is not a valid number
10:42
But in my case, for my cart, I have getter and setter
10:48
And you may think that if you have a getter and setter, it means you are already encapsulated data
10:54
But this is not an encapsulation. And your class provides us ability to directly set invalid data
11:04
We should avoid this and we need to have additional encapsulation, additional protector
11:12
over our number, not to allow this type of data. Sorry. So this is also going to be our content coupling in this case
11:26
Okay. The second form is common coupling. We have used this common coupling everywhere when you use enums, when you are dealing with
11:37
static variables. So the common coupling refers to a specific type of tight coupling where multiple modules
11:45
within a program share access to the same global data. Of course, in .NET, we have global data concept, but it was implemented in L language
11:56
But in C sharp, we have static variables that we are going to use as a global data
12:02
Let me show you one example here. So in my case, I have, let me just close this. Okay
12:10
I have user session and this user session has the user ID
12:16
This is a static property. Okay. And my logger service is directly using this user sessions user ID
12:25
The problem here is right now I have tightly coupled between logging service and user session
12:32
This is a huge problem. When I want to change this logging sessions, it has direct dependency from user session
12:39
So it is not possible for me to change user session confidently
12:44
This is a big problem. So you need to avoid it. This is a common coupling. Okay
12:47
So you have this shared data among your modules, user session model and logging model
12:54
You need somehow to avoid it and using some sort of abstraction, using interfaces, abstract
13:02
classes, some other techniques, you can easily do it. Right now I have user ID provider as an interface and my user session inherits from a user ID provider
13:14
And in my case, logger service doesn't interact with user ID directly
13:20
I have dependency from the contract rather than implementation. And it helps me to easily change logging service
13:28
And I can easily change the implementation because I have dependency from abstract element
13:36
not the concrete element. This is how we are resolving this common coupling
13:44
Great. So the third one is going to be our external coupling
13:49
I think this is one of the interesting subtopics for loosely coupling
13:55
I will tell you one simple example here. When you are using entity framework directly in your application, it means you have external
14:03
coupling because this is a third part library. This is a different module
14:07
And your application directly depends on your entity framework. This is one of the reasons why people use a repository layer over entity framework
14:18
But entity framework by itself is also a repository with unit of work
14:22
But let's talk about external coupling. External coupling refers to the interdependence of different modules based on factors outside
14:32
the system itself. So in a simple manner, modules relying on a third-party library with no limitation
14:42
We already know that entity framework has its own limitations also. The limitation is not a fact here
14:50
So the problem here is you are depending from some third-part library
14:56
We have a lot of other examples like an application reading product data from a specific data
15:01
format, code interacting directly with specific hardware devices. So you have some sort of dependency from the implementation rather than the abstract element
15:14
In my case, let me show you one example here. This is our customer service, and my customer service depends from customer DB context
15:26
So actually, this customer DB context, as you know, inherits from DB context
15:31
DB context is my entity framework DB context. So we have direct dependency from entity framework
15:40
How you can deal with that? If you really need to isolate your application from entity framework, it doesn't mean that
15:49
if there is external coupling, it is bad. Let's try to avoid it
15:54
No, it depends. I really love the term, it depends on programming, because it really depends
16:01
In your case, the common coupling also may be okay, completely okay
16:07
So applying content coupling, common coupling, external, not content coupling, but common
16:13
external control, stamp coupling, actually depends on your applications from your requirements
16:21
In my case, I have the customer service that depends from entity framework DB context
16:28
If I want to isolate my application from entity framework, of course, I will use the
16:36
additional obstruction, like abstract classes, interfaces, et cetera, additional obstruction using repository, et cetera, to isolate my application from entity framework dependency
16:50
That's how we should deal with external coupling. Of course, not just external coupling, but it is applicable for all sorts of couplings
17:01
If you need to avoid some sort of coupling, we are always trying to add one more obstruction
17:07
over it. This is one of the way of dealing with the issue
17:14
And of course, the other one, the a little bit trick one is going to be about control coupling
17:20
It is also called tell, don't ask principle, okay? Instead of focusing on external factors, control coupling deals with how models influence
17:32
each other's execution. So you have two models, and one model dictates the flow of other model
17:39
This is a big problem. There is a boss who dictates that this model should do like this
17:46
For example, if you have EFLs, switch case type of things in your application, and one
17:52
module dictates how other models should behave. This is about our coupling also
17:59
Let's talk, let me show you one example from control coupling here
18:05
For the control coupling, I have, for example, order processor. In this case, I have two important models, order processor and order, okay
18:14
And order processor is going to be our boss, a leader. And the worker is going to be our order
18:25
And you see, we have is priority Boolean indicator, a flag. So one of the important signs of showing that there is a control coupling in your application
18:37
that it should be some sort of flag that indicates that one model manages another, okay
18:44
In my case, I have a Boolean indicator here. And depending this Boolean value, I have two type of flow for my order
18:55
It means my order is not a full functional, is not independent model
19:01
There is someone who dictates the rules. This is a big problem in our application
19:08
So how to deal with that? Of course, we have a second version here
19:12
Again, we have additional obstruction using interfaces, abstract classes, even using simple class is also obstruction
19:21
So the class is abstract data type. So it is also obstruction
19:27
In my case, we have, I order handler, okay? For order, handle order
19:34
And we have two implementations. Instead of having Boolean indicator with two flows, I have two different implementations here
19:45
And I'm injecting directly the flow itself, rather than allowing order processor to define
19:54
the path to dictate the execution path for my order. This is a little bit tricky
20:03
And the other coupling is going to be our stamp coupling. Yeah, I think we're all faced with this coupling
20:14
The problem here is, let's say you have some sort of a method, okay
20:19
And your method accepts six arguments, let's say. I don't know, four arguments, three arguments
20:26
But you are usually using only two of them, one of them
20:31
It means you have a lot of arguments, or you have one complex argument
20:36
Let's say you have a method that accepts order class as an argument
20:40
But you're using only two or three properties of this order. Instead of having another complex data or multiple small sort of arguments
20:58
you are dealing with a huge complex data, okay? The problem here is, in your case, we have two models are stamped coupled
21:08
if they communicate using a single data structure. Let me show you the example here
21:13
So in my case, we have order service. And order service has send order confirmation email
21:23
And we have customer as an argument. Problem here is, as you can see, I'm using only name
21:29
This is only a requirement for me. Instead of directly accepting string name, I'm using customer
21:35
Because it is easy for me, I don't want to spend more time just typing string name
21:43
I'm just using the customer. And I am trying to make some sort of reusable code
21:50
But there is nothing to reuse. This is a bad habit. You should provide the exact arguments you're using
21:56
So if you have two arguments, you should exactly use them. In most cases, in all .NET platform, for example, for platform invocation
22:07
or all that type of elements, you may say that there is a method that accepts 15, 16, 10 arguments
22:18
And most of them are just nulls, okay? This is also a problem of stamp coupling
22:23
You need to provide only the exact argument count that you are using
22:28
If you need to, for example, name, surname, just provide name, surname
22:32
instead of providing the customer that consists from 10, 11 properties. And how to deal with that is also obvious
22:42
We have I order confirmation data. This is one of the forms of dealing with this issue
22:48
The other one is just doing like this. Oops, let me just copy, paste
22:56
So if you are dealing with just name and surname, just provide string name and string surname
23:06
That's all. And this stamp coupling provides a way for data coupling
23:13
The stamp coupling is actually a one form of data coupling, okay
23:18
The data coupling refers to the degree of interdependence between different modules
23:23
Based on the data they exchange, it means you have the exact arguments you need to use
23:29
In my case, I did a little bit refactoring here, and now I have exact coupling called data coupling, okay
23:41
That's how we are dealing with this problem. As I mentioned, it's really important
23:46
It doesn't matter if you are going to be a software architect
23:52
or if you want to be a senior engineer, you should start to learn the basics
23:58
For me, this is also basics of software development. This is, of course, related to software design
24:08
but this is a basics of software development. So every developer, if you are a junior developer, middle developer, senior, it doesn't matter
24:16
We are using these elements in our daily basis. So you should know the loosely coupling and high equation principles
24:26
And thank you for watching. That's all about this session. Well, that was great, Dhruv
24:35
Thank you so much. I believe you talked so much about loose coupling. I never knew it so much existed
24:41
And I would encourage everyone to go ahead and check the video description
24:45
You'll find Dhruv's all social handles. And also, he has recently published a new Udemy course
24:51
You should also go and check out. You'll find all the details on his LinkedIn
24:55
Thank you so much, Dhruv. Thank you so much for this great session. And thank you so much, everyone, for watching
25:00
We will see you in the next episode of Dashboard.net. See you. Bye-bye