Let's say I have a controller called MessageReceiverController
which is a controller of an API that other services can call and include messages in the requests.
For each of the messages the controller receives, it will process it and then send it to API_A
. If response from API_A
is successful, it will send the message to API_B
too. There are a few operations to perform based on this logic.
When I'm writing my controller and service for the controller, should I split the operations in the service class or should I combine all of them into a single method in the service class and then let the controller call that one single method to perform everything?
To make things clearer, here are some pseudocodes as examples of what I mean.
Example 1
In this example, the actions are merged into a single method in the service class. I may have split the actions within the service class for clarify but the controller is essentially only calling a method in its service that performs multiple actions.
class MessageReceiverService {
private _sendToApi(message, apiUrl) {
return this.request.post(apiUrl, {
body: message
});
}
processAndSendAll(messages) {
// Put all the actions together into a single method in the service
foreach (message in messages) {
message.data = 'Process message with some data';
const response = this._sendToApi('http://API_A', {
body: message
});
if (response.status === 200) {
this._sendToApi('http://API_B', {
body: message
})
}
}
}
}
class MessageReceiverController {
receiveAction(messages) {
this.messageReceiverService.processAndSendAll(messages);
return { status: 200 }
}
}
Example 2
Or should I split the actions in the service class and then make use of the controller class to perform the individual actions like so? I don't feel like this is a good approach because it feels like part of the logic is leaked into the controller, but I might be wrong.
class MessageReceiverService {
process(message) {
message.data = 'Process message with some data';
return message;
}
send(message, apiUrl) {
this.request.post(apiUrl, {
body: message
})
}
}
class MessageReceiverController {
receiveAction(messages) {
foreach (message in messages) {
const processedMessage = this.messageReceiverService.process(message);
const response = this.messageReceiverService.send(processedMessage, 'http://API_A');
if (response.status === 200) {
this.messageReceiverService.send(processedMessage, 'http://API_B')
}
}
return { status: 200 }
}
}
Example 3
Or, lastly, should I split the actions but encapsulate the loops and some logic in the service class like in this example? In this case, the controller is almost doing like "Action 1, Action 2, Action 3... and so on". However, it may not be very efficient in the code as, in this case, the loop could have just looped through the messages once instead of twice. Again, I'm not really sure what would be the right approach and this is one of the ideas that came to me.
class MessageReceiverService {
processAllMessages(messages) {
foreach (message in messages) {
message.data = 'Process message with some data';
}
return messages;
}
sendAllToApi(messages) {
foreach (message in messages) {
const response = this.request.post('http://API_A', {
body: message
});
if (response.status === 200) {
this.request.post('http://API_B', {
body: message
})
}
}
}
}
class MessageReceiverController {
receiveAction(messages) {
const processedMessages = this.messageReceiverService.processAllMessages(messages);
this.messageReceiverService.sendAllToApi(processedMessages);
return { status: 200 }
}
}
So, when it comes to operations in controller that consist of multiple actions within it, how should I organise the logic in the controller and its service? Is it better to have the controller only be calling a single method on the service to perform its action or it is it better to split them into multiple methods in the service class for the controller to call?
Which of the examples I have above is more appropriate, or if neither of them are, how should I write my controller and service classes?