diff --git a/2. Services/2.2 Processings/2.2 Processings.md b/2. Services/2.2 Processings/2.2 Processings.md
index b1025a7..cd78d1a 100644
--- a/2. Services/2.2 Processings/2.2 Processings.md
+++ b/2. Services/2.2 Processings/2.2 Processings.md
@@ -2,7 +2,7 @@
## 2.2.0 Introduction
-Processing services are the layer where a higher order of business logic is implemented. They may combine (or orchestrate) two primitive-level functions from their corresponding foundation service to introduce a newer functionality. They may also call one primitive function and change the outcome with a little bit of added business logic. And sometimes processing services are there as a pass-through to introduce balance to the overall architecture.
+Processing services are the layer where a higher order of business logic is implemented. They may combine (or orchestrate) two primitive-level functions from their corresponding foundation service to introduce newer functionality. They may also call one primitive function and change the outcome with a little bit of added business logic. Sometimes, processing services are there as a pass-through to introduce balance to the overall architecture.
Processing services are optional, depending on your business need - in a simple CRUD operations API, processing services and all the other categories of services beyond that point will cease to exist as there is no need for a higher order of business logic at that point.
@@ -27,11 +27,11 @@ TryCatch(async () =>
});
```
-Processing services make Foundation services nothing but a layer of validation on top of the existing primitive operations. This means that Processing services functions are beyond primitive, and they only deal with local models as we will discuss in the upcoming sections.
+Processing services make Foundation services nothing but a layer of validation on top of the existing primitive operations. This means that Processing services functions are beyond primitive and only deal with local models, as we will discuss in the upcoming sections.
## 2.2.1 On The Map
-When used, Processing services live between foundation services and the rest of the application. they may not call Entity or Business brokers, but they may call Utility brokers such as logging brokers, time brokers, and any other brokers that offer supporting functionality and are not specific to any particular business logic. Here's a visual of where processing services are located on the map of our architecture:
+Processing services live between foundation services and the rest of the application when used. They may not call Entities or Business brokers. Still, they may call Utility brokers such as logging brokers, time brokers, and any other brokers that offer supporting functionality and are not specific to any particular business logic. Here's a visual of where processing services are located on the map of our architecture:
@@ -39,12 +39,12 @@ When used, Processing services live between foundation services and the rest of
-On the right side of a Processing service lies all the non-local models and functionality, whether it's through the brokers or the models that the foundation service is trying to map into local models.
-On the left side of Processing services are pure local functionality, models, and architecture. Starting from the Processing services themselves, there should be no trace or track of any native or non-local models in the system.
+On the right side of a Processing service lies all the non-local models and functionality, whether through the brokers or the models, and the foundation service is trying to map them into local models.
+On the left side of Processing services are pure local functionality, models, and architecture. Starting from the Processing services, there should be no trace or track of any native or non-local models in the system.
## 2.2.2 Characteristics
-Processing services in general are combiners of multiple primitive-level functions to produce a higher-order business logic. but they have many more characteristics than just that, let's talk about those here.
+Processing services, in general, are combiners of multiple primitive-level functions to produce a higher-order business logic. But they have many more characteristics than just that; let's talk about those here.
### 2.2.2.0 Language
@@ -53,7 +53,7 @@ Usually, processing services combine two or more primitive operations from the f
#### 2.2.2.0.0 Functions Language
-At a glance, the Processing services language changes from primitive operations such as `AddStudent` or `RemoveStudent` to `EnsureStudentExists` or `UpsertStudent`. they usually offer more advanced business logic operations to support a higher-order functionality.
+The Processing services language changes from primitive operations such as `AddStudent` or `RemoveStudent` to `EnsureStudentExists` or `UpsertStudent`. They usually offer more advanced business logic operations to support higher-order functionality.
Here are some examples of the most common combinations a processing service may offer:
| Processing Operation | Primitive Functions |
@@ -63,27 +63,27 @@ Here are some examples of the most common combinations a processing service may
| VerifyStudentExists | RetrieveAllStudents |
| TryRemoveStudentAsync | RetrieveStudentById + RemoveStudentByIdAsync |
-As you can see, the combination of primitive functions processing services might also include adding an additional layer of logic on top of the existing primitive operation. For instance, `VerifyStudentExists` takes advantage of the `RetrieveAllStudents` primitive function, and then adds a boolean logic to verify whether the returned student by an Id from a query exists or not before returning a `boolean`.
+As you can see, the combination of primitive functions processing services might also include adding an additional layer of logic on top of the existing primitive operation. For instance, `VerifyStudentExists` takes advantage of the `RetrieveAllStudents` primitive function and then adds a boolean logic to verify the returned student by an Id from a query actually exists or not before returning a `boolean`.
#### 2.2.2.0.1 Pass-Through
-Processing services may borrow some of the terminology a foundation service may use. for instance, in a pass-through scenario, a processing service with be as simple as `AddStudentAsync`. We will discuss the architecture-balancing scenarios later in this chapter.
-Unlike Foundation services, Processing services are required to have the identifier `Processing` in their names. for instance, we say `StudentProcessingService`.
+Processing services may borrow some of the terminology a foundation service uses. For instance, in a pass-through scenario, a processing service could be as simple as `AddStudentAsync`. We will discuss the architecture-balancing scenarios later in this chapter.
+Unlike Foundation services, Processing services are required to have the identifier `Processing` in their names. For instance, we say `StudentProcessingService`.
#### 2.2.2.0.2 Class-Level Language
More importantly, Processing services must include the name of the entity that is supported by their corresponding Foundation service.
-For instance, if a Processing service is dependent on a `TeacherService`, then the Processing service name must be `TeacherProcessingService`.
+For instance, if a Processing service depends on a `TeacherService`, then the Processing service name must be `TeacherProcessingService`.
### 2.2.2.1 Dependencies
-Processing services can only have two types of dependencies. a corresponding Foundation service, or a Utility broker. That's simply because Processing services are nothing but an extra higher-order level of business logic, orchestrated by combined primitive operations on the Foundation level.
-Processing services can also use Utility brokers such as `TimeBroker` or `LoggingBroker` to support its reporting aspect. but it shall never interact with an Entity or Business broker.
+Processing services can only have two types of dependencies: a corresponding Foundation service or a Utility broker. That's simply because Processing services are nothing but an extra higher-order level of business logic orchestrated by combined primitive operations on the Foundation level.
+Processing services can also use Utility brokers such as `TimeBroker` or `LoggingBroker` to support their reporting aspect, but they shall never interact with an Entity or Business broker.
### 2.2.2.2 One-Foundation
-Processing services can interact with one and only one Foundation service. In fact, without a foundation service there can never be a Processing layer. and just like we mentioned above about the language and naming, Processing services take on the same entity name as their Foundation dependency.
-For instance, a processing service that handles higher-order business logic for students will communicate with nothing but its foundation layer, which would be `StudentService` for instance. That means that processing services will have one and only one service as a dependency in its construction or initiation as follows:
+Processing services can interact with only one Foundation service. In fact, without a foundation service, there can never be a Processing layer. And just like we mentioned above about the language and naming, Processing services take on the exact same entity name as their Foundation dependency.
+For instance, a processing service that handles higher-order business logic for students will communicate with nothing but its foundation layer, which would be `StudentService`. That means that processing services will have one and only one service as a dependency in its construction or initiation as follows:
```csharp
public class StudentProcessingService
@@ -99,8 +99,8 @@ However, processing services may require dependencies on multiple utility broker
### 2.2.2.3 Used-Data-Only Validations
-Unlike the Foundation layer services, Processing services only validate what it needs from its input. For instance, if a Processing service is required to validate a student entity exists, and its input model just happens to be an entire `Student` entity, it will only validate that the entity is not `null` and that the `Id` of that entity is valid. the rest of the entity is out of the concern of the Processing service.
-Processing services delegate full validations to the layer of services that is concerned with that which is the Foundation layer. here's an example:
+Unlike the Foundation layer services, Processing services only validate what they need from their input. For instance, if a Processing service is required to validate that a student entity exists, and its input model just happens to be an entire `Student` entity, it will only validate that the entity is not `null` and that the `Id` of that entity is valid. The rest of the entity is out of the Processing service's concern.
+Processing services delegate full validations to the layer of services that are concerned with that, which is the Foundation layer. Here's an example:
```csharp
public ValueTask UpsertStudentAsync(Student student) =>
@@ -121,21 +121,21 @@ TryCatch(async () =>
});
```
-Processing services are also not very concerned about outgoing validations except for what is going to be used within the same routine. For instance, if a Processing service is retrieving a model, and it's going to use this model to be passed to another primitive-level function on the Foundation layer, the Processing service will be required to validate that the retrieved model is valid depending on which attributes of the model it uses.
-For Pass-through scenarios, however, processing services will delegate the outgoing validation to the foundation layer.
+Processing services are also not very concerned about outgoing validations except for what they will use within the same routine. For instance, if a Processing service is retrieving a model and will use this model to be passed to another primitive-level function on the Foundation layer, the Processing service will be required to validate that the retrieved model is valid, depending on which attributes of the model it uses.
+However, processing services will delegate the outgoing validation to the foundation layer for Pass-through scenarios.
## 2.2.3 Responsibilities
-The processing service's main responsibility is to provide higher-order business logic. This happens along with the regular signature mapping and various use-only validations which we will discuss in detail in this section.
+Processing service's main responsibility is to provide higher-order business logic. This happens along with the regular signature mapping and various use-only validations, which we will discuss in detail in this section.
### 2.2.3.0 Higher-Order Logic
-Higher-order business logic are functions that are above primitive. For instance, `AddStudentAsync` function is a primitive function that does one thing and one thing only. But higher-order logic is when we try to provide a function that changes the outcome of a single primitive function like `VerifyStudentExists` which returns a boolean value instead of the entire object of the `Student`, or a combination of multiple primitive functions such as `EnsureStudentExistsAsync` which is a function that will only add a given `Student` model if and only if the aforementioned object doesn't already exist in storage. Here are some examples:
+Higher-order business logic are functions that are above primitive. For instance, `AddStudentAsync` function is a primitive function that does one thing and one thing only. But higher-order logic is when we try to provide a function that changes the outcome of a single primitive function like `VerifyStudentExists`, which returns a boolean value instead of the entire object of the `Student`, or a combination of multiple primitive functions such as `EnsureStudentExistsAsync` which is a function that will only add a given `Student` model if and only if the object mentioned above doesn't already exist in storage. Here are some examples:
#### 2.2.3.0.0 Shifters
-The shifter pattern in higher-order business logic is when the outcome of a particular primitive function is changed from one value to another. Ideally, a primitive type such as a `bool` or `int` is not a completely different type as that would violate the purity principle.
-For instance, in a shifter pattern, we want to verify if a student exists or not. We don't want the entire object, but just whether it exists in a particular system or not. Now, this seems like a case where we only need to interact with one and only one foundation service and we are shifting the value of the outcome to something else. Which should fit perfectly in the realm of the processing services. Here's an example:
+The shifter pattern in a higher-order business logic is when the outcome of a particular primitive function is changed from one value to another. Ideally, a primitive type such as a `bool` or `int` is not a completely different type as that would violate the purity principle.
+For instance, in a shifter pattern, we want to verify whether a student exists. We want only some objects, but we want to know whether they exist in a particular system. Now, this is a case where we only need to interact with one and only one foundation service, and we are shifting the value of the outcome to something else, which should fit perfectly in the realm of the processing services. Here's an example:
```csharp
public ValueTask VerifyStudentExists(Guid studentId) =>
@@ -150,7 +150,7 @@ TryCatch(async () =>
});
```
-In the snippet above, we provided a higher-order business logic, by returning a boolean value of whether a particular student with a given `Id` exists in the system or not. There are cases where your orchestration layer of services isn't really concerned with all the details of a particular entity but just knowing whether it exists or not as a part of an upper business logic or what we call orchestration.
+In the snippet above, we provided higher-order business logic by returning a boolean value indicating whether a particular student with a given `Id` exists in the system. There are cases where your orchestration layer of services isn't really concerned with all the details of a particular entity but just knows whether it exists or not as part of an upper business logic or what we call orchestration.
Here's another popular example of a processing services shifting pattern:
@@ -167,12 +167,12 @@ TryCatch(() =>
});
```
-In the example above, we provided a function to retrieve the count of all students in a given system. It's up to the designers of the system to determine whether to interpret a `null` value retrieved for all students to be an exception case that was not expected to happen or return a `0`; all depending on how they manage the outcome.
-In our case here we validate the outgoing data as much as the incoming, especially if it's going to be used within the processing function to ensure further failures do not occur for upstream services.
+In the example above, we provided a function to retrieve the count of all students in a given system. The system's designers determine whether to interpret a `null` value retrieved for all students as an exception case that was not expected to happen or return a `0`, depending on how they manage the outcome.
+In our case, we validate the outgoing data as much as the incoming data, especially if it will be used within the processing function to ensure further failures do not occur for upstream services.
#### 2.2.3.0.1 Combinations
-The combination of multiple primitive functions from the foundation layer to achieve a higher-order business logic is one of the main responsibilities of a processing service. As we mentioned before, some of the most popular examples are for ensuring a particular student model exists as follows:
+Combining multiple primitive functions from the foundation layer to achieve a higher-order business logic is one of the main responsibilities of a processing service. As we mentioned before, some of the most popular examples are for ensuring a particular student model exists as follows:
```csharp
public async ValueTask EnsureStudentExistsAsync(Student student) =>
@@ -194,22 +194,22 @@ TryCatch(async () =>
});
```
-In the code snippet above, we combined `RetrieveAll` with `AddAsync` to achieve a higher-order business logic operation. The `EnsureAsync` operation needs to verify something or an entity exists first before trying to persist it. The terminology around these higher-order business logic routines is very important. Its importance lies mainly in controlling the expectations of the outcome and the inner functionality. But it also ensures less cognitive resources from the engineers are required to understand the underlying capabilities of a particular routine.
-The conventional language used in all of these services also ensures that redundant capability will not be created mistakenly. For instance, an engineering team without any form of standard might create `TryAddStudentAsync` while already having an existing functionality such as `EnsureStudentExistsAsync` which does the same thing. The convention here with the limitation of the size of capabilities a particular service may have ensured redundant work shall never occur on any occasion.
-There are so many different instances of combinations that can produce a higher-order business logic, for instance, we may need to implement a functionality that ensures a student is removed. We use `EnsureStudentRemovedByIdAsync` to combine a `RetrieveById` and a `RemoveById` in the same routine. It all depends on what level of capabilities an upstream service may need to implement such a functionality.
+In the code snippet above, we combined `RetrieveAll` with `AddAsync` to achieve a higher-order business logic operation. The `EnsureAsync` operation needs to verify something or an entity exists first before trying to persist it. The terminology around these higher-order business logic routines is very important. Its importance lies mainly in controlling the expectations of the outcome and the inner functionality. However, it also ensures that engineers do not require fewer cognitive resources to understand the underlying capabilities of a particular routine.
+The conventional language used in all of these services also ensures that redundant capability will not be created mistakenly. For instance, an engineering team without any form of standard might create `TryAddStudentAsync` while already having an existing functionality such as `EnsureStudentExistsAsync`, which does the same thing. With the limitation of the size of capabilities a particular service may have, the convention here ensured redundant work should never occur on any occasion.
+There are so many different combinations that can produce higher-order business logic. For instance, we may need to implement functionality that ensures a student is removed. We use `EnsureStudentRemovedByIdAsync` to combine a `RetrieveById` and a `RemoveById` in the same routine. It all depends on what level of capabilities an upstream service may need to implement such a functionality.
### 2.2.3.1 Signature Mapping
-Although processing services operate fully on local models and local contracts, they are still required to map foundation-level services' models to their local models. For instance, if a foundation service is throwing `StudentValidationException` then processing services will map that exception to `StudentProcessingDependencyValidationException`. Let's talk about mapping in this section.
+Although processing services operate fully on local models and local contracts, they are still required to map foundation-level services' models to their own local models. For instance, if a foundation service throws `StudentValidationException` then processing services will map that exception to `StudentProcessingDependencyValidationException`. Let's talk about mapping in this section.
#### 2.2.3.1.0 Non-Exception Local Models
-In general, processing services are required to map any incoming or outgoing objects with a specific model of its own. But that rule doesn't always apply to non-exception models. For instance, if a `StudentProcessingService` is operating based on a `Student` model, and there's no need for a special model for this service, then the processing service may be permitted to use the same model from the foundation layer.
+In general, processing services are required to map any incoming or outgoing objects with a specific model of its own. But that rule only sometimes applies to non-exception models. For instance, if a `StudentProcessingService` is operating based on a `Student` model, and there's no need for a special model for this service, then the processing service may be permitted to use the exact same model from the foundation layer.
#### 2.2.3.1.1 Exception Models
-When it comes to processing services handling exceptions from the foundation layer, it is important to understand that exceptions in our Standard are more expressive in their naming conventions and their role than any other model. Exceptions here define the what, where, and why every single time they are thrown.
-For instance, an exception that's called `StudentProcessingServiceException` indicates the entity of the exception which is the `Student` entity. Then it indicates the location of the exception which is the `StudentProcessingService`. Lastly, it indicates the reason for that exception which is `ServiceException` indicating an internal error to the service that is not a validation or a dependency of nature that happened.
+When processing services handle exceptions from the foundation layer, it is important to understand that exceptions in our Standard are more expressive in their naming conventions and role than any other model. Exceptions here define the what, where, and why every single time they are thrown.
+For instance, an exception called `StudentProcessingServiceException` indicates the entity of the exception, which is the `Student` entity. Then, it indicates the location of the exception, which is the `StudentProcessingService`. Lastly, it indicates the reason for that exception, which is `ServiceException`, indicating an internal error to the service that is not a validation or a dependency of nature that happened.
Just like the foundation layer, processing services will do the following mapping to occurring exceptions from its dependencies:
| Exception | Wrap Inner Exception With | Wrap With | Log Level |