What is Single Responsibility Principle ?
Published: 2022-08-12 10:12:00


SOLID is an acronym is invented by [Uncle Bob](https://en.wikipedia.org/wiki/Robert_C._Martin), so we can remember these core concepts for clean coding better. The first letter stands for **Single Responsibility Principle** (SRP). SRP says that a class or a function should be responsible only for one thing.



## SRP in Functional Programming


The SRP says one class or one function should be responsible only for one thing. For instance, if we have a function that is responsible for reading a data and mutating another data, then there are two reasons to change. The reasons are, if the implementation of reading a data from a database or mutating a data changes, we need to modify the whole function. 

For this kind of situations, there is `interface` in object-oriented programming languages. But for functional programming generally there is no implementation like that because we don't use classes in functional programming languages(FPL).

	Note: There is interface implementation in Typescript, so if you 
	use Typescript for FPL, you can create an interface for 
	SRP.


In the example below, you can see the bad implementation of a function where it violates the SRP.

	Note: I'll use the React library to demonstrate the concept.

```js
// bad example
let handleFetching = async () => {

	// 1. read data from somewhere
	let res = await fetch("some.url").then(res => res.json())

	if(res != null)
	{
		//2. mutate the state
		setData(res.data);
	}

}

```

As you can see in the `handleFetching` function, there are two responsibilities. The first one is reading data from somewhere and the second one is mutating some state or data. So if the implementation changes for these two different responsibilities, we need to change `handleFetching` function. Also, it makes hard to test this function where we need to test these two responsibilities.

```js
// good example
let handleFetching = async () => {

	// 1. read data from somewhere
	let res = await getData();
	return res
}

let getData = async () => {
// get data implementation goes here
}

useEffect(() => {
	let res = handleFetching()
	if(res != null)
	{
		//2. mutate the state
		setData(res.data);
	}
}, [])

```

As you can see in the good example, we made every function responsible for only one thing. The `handleFetching` function now responsible only for fetching data and not mutating some state. The `getData` is responsible for getting data from somewhere etc. So we separated all responsibilities to the different functions, so we can test them separately.


## SRP in OOP
Similar to functional programming, we can analyze a function to determine it is responsible for one thing or not. If there are multiple responsibilities for a function or a service, we should separate those responsibilities.

In the code below, you can see the bad example.

	Note: I'll use c# programming language to demonstrate the concept.

```c#
//bad example
public async Task<Something> GetSomethingById(int id)
{
	var something = await _somethingRepo.GetOneAsync(x => x.id == id);

	// violates the SRP 
	var url = "google.com";
	var client = new WebClient();
	var reply = client.DownloadString(url);
	something.reply = reply;

	
} 
```

As you can see, in the `GetSomethingById` method we get data from repository, and we update the reply property using `DownloadString`method. So there are two different responsibilities for this function, one is getting data, the other reason is mutating a property.


```c#
// bad example
class FoodDelivery
{
	private List<Food> foods;

	public Food MakeFood(string name)
	{
		
	}

	public Food GetFood(int id, int price)
	{
		
	}
	
	public void DeliverFood(string path)
	{
		
	}

}
```

In this example, we can see that `FoodDelivery` class has three different methods and all of them are responsible from different logic. If we change an implementation from any of them, it could affect other functions. For example, if we change `MakeFood` method, maybe we need to update some logic inside `DeliverFood` method. And also `MakeFood` and `GetFood` functions don't relate to food delivery business. So let's see how can we turn this bad example to the good one by separating logic to different services.

```c#
//good example
public interface IFoodGetter{
	Food GetFood(int id, int price);
}


public interface IFoodMaker{
	Food MakeFood(string name);
}

public class FoodGetter : IFoodGetter {
	public Food GetFood(int id, int price){
		//implementation goes here
	}
}

public class FoodMaker : IFoodMaker {
	public Food MakeFood(string name){
		//implementation goes here
	}
}

class FoodDelivery
{
	private List<Food> foods;
	private readonly IFoodGetter _foodGetter;
	private readonly IFoodMaker _foodMaker;

	public FoodDelivery(IFoodGetter foodGetter, IFoodMaker foodMaker){
		foodGetter = _foodGetter;
		foodMaker = _foodMaker;
	}

	public void DeliverFood(string path)
	{
		var food = _foodGetter.GetFood(1,20);
			
		if(food == null){
			food = _foodMaker.MakeFood("food_name");
		}

		//delivery implementation goes here
		
	}

}
```

In the example above, we created two different services such as `FoodGetter`, `FoodMaker` to separate business logic. And `FoodDelivery` class is only responsible for delivering food. If we need to change some implementation in `FoodGetter` service, we can change it inside that service. And also using interfaces we can create mock implementation of those services so we can test them without connecting to real database etc.