How do I design an Actor model? - oop

I am trying to implement an Actor model in Java.
I have started with the following [class diagram].
As you can see, the ActorRunner created in the ActorContext is responsible for controlling the life cycle of the actors: it has the message queue and it calls the process() method of the actor for each received message in its loop (run()). Actors simply implement the Actor interface with the single process() method.
Now, I want to add a decorator (Decorator pattern) and be able to decorate the send() and process() methods. However, since the Actor interface does not have the send() I cannot decorate it and spawn a decorated actor with ActorContext.spawnActor().
How can I modify the design to suit my needs?

Related

Should behaviors be exposed through the Actor object or can it be done on any object?

Lets say we are writing a Seat Booking functionality in object oriented programming. User is the primary actor here. We might implement the booking flow as follows
var booking = user.BookSeat(seatid);
Subsequently, the user might Cancel the booking. In proper object oriented design, should this operation be exposed through the actor ie the user object(representing the real world user) as follows?
user.CancelBooking(booking);
or can it be called directly on the booking object?
booking.Cancel();

How to share a util object which is not thread safe in light-4j handler

I have generated code from an openapi yaml file. I'm implementing the handleRequest methods. I need to share the same instance of a "Util" object to reuse it in all the handleRequest calls. Could you please tell me where to store my Util object instance?
My Util class is not thread safe, so I should have one instance for each client thread.
If your class is thread safe, the best place is https://www.networknt.com/concern/service/
If the object is not thread safe then save one object per thread with ThreadLocal. That means one request might be calling two or more instance of util objects when a request is dispatched from an IO thread to a worker thread.
If it's actually a util object can you make it stateless so that it is thread safe? Maybe add an additional context type object for the state if you really need it. Attaching it to the exchange as an attachment could work.

How do I gracefully avoid dependencies on infrastructure services from domain entities using DDD?

Background
Suppose I am tasked with building a system in the domain of notification sending using Domain Driven Design (DDD). One of the key requirements of this system is that it needs to support various "types" of notifications, such as SMS, email, etc.
After several iterations on developing the domain model, I continue to land on having a Notification base class as an entity, with subclasses SMSNotification, EmailNotification, etc. as child classes (each being an entity as well).
Notification
public abstract class Notification extends Entity<UUID> {
//...fields...
public abstract void send();
}
SMSNotification
public class SMSNotification extends Notification {
public void send(){
//logic for sending the SMS notification using an infrastructure service.
}
}
EmailNotification
public class EmailNotification extends Notification {
public void send(){
//logic for sending the email notification using an infrastructure service.
}
}
Problem(s)
With this current design approach, each subclass of Notification is interacting with an infrastructure service, where the infrastructure is tasked with interfacing with some external system.
Eric Evans dedicates a little page space about this on page 107 in his book Domain-Driven Design when introducing the concept of domain services:
..., in most development systems, it is awkward to make a direct interface between a domain object and external resources. We can dress up such external services with a facade that takes inputs in terms of the model, ... but whatever intermediaries we may have, and even though they don't belong to us, those services are carrying out the domain responsibility...
If instead, I procure a SendNotificationService in my domain model using Evans' advice instead of having a send method on each subclass of Notification, I am not sure how I can avoid the need for knowing what type of notification was provided, so that the appropriate infrastructure action can be taken:
SendNotificationService (Domain Service)
public class SendNotificationService {
public void send(Notification notification){
//if notification is an SMS notification...
// utilize infrastructure services for SMS sending.
//if notification is an email notification...
// utilize infrastructure services for email sending.
//
//(╯°□°)╯︵ ┻━┻)
}
}
What am I missing here?
Object oriented design principles are pushing me in favor of having the model first suggested, with the Notification, SMSNotification, and EmailNotification classes. Implementing the send method on each subclass of Notification makes sense, as all notifications need to be sent (justifies its placement in Notification) and each "type" or subclass of Notification will have specialized behavior in how the notification is sent (justifies making send abstract in Notification). This approach also honors Open/Closed Principle (OCP), since the Notification class will be closed to modification, and as new notification types are supported, a new subclass of Notification can be created to extend functionality. Regardless, there seems to be consensus on not having entities interface with external services, as well as not having subclasses of entities at all in DDD.
If the behavior of sending notifications is removed from Notification, then where it is placed must be aware of the "type" of notification, and act accordingly, which I can only conceptualize as chain of if...else... statements, which directly contradicts OCP.
TLDR: If you need some infrastructure logic to be executed against your domain and you need some input to it from domain - don't build it in, just declare intentions with appropriate data/markers. You'll then process this declared intentions later, in infrastructure layer.
Do notifications of various kind differ in any way other that delivery mechanism? If not - there could be enough to use a Notification value object (or Entity, if your domain model requires so) with additional field (Enum, if the list is known, or some kind of marker) to store a delivery method name. Maybe, there could be numerous such methods per single notification instance.
Then you have a business logic - a domain service - to fire a notification. A domain service should only depend on domain vocabulary. E.g NotificationDeliveryMethodProvider.
In your adapters layer you can implement various delivery method providers to interact with infrastructure. And a factory to get providers according to a value in DeliveryMethod enum (or marker).
Basically, it's not an aggregate's responsibility to "send" itself of manipulate in any way. Its responsibility should be to maintain its state, execute state transitions in a consistent way and coordinate states of its enclosed entities/values. And fire events about its state changes.
In one of my projects I used the following subpackages under my domain package:
provides - interfaces of domain services provided to clients
cousumes - interfaces of upstream dependencies
businesslogic - implementation of domain services
values - value objects with code to enforce their invariants
...
Besides domain package there were also:
adapters package dealing with infrastructure
App object, where all interfaces were bound to implementations.
[There could also be] config package, but in my case it was very light.
These domain, adapters, App and config could be deployed as different jar-files with clear dependency structure, if you need to enforce it for somebody other.
I agree with you that the main responsibility of a Notification should be, that it can send itself. That is the whole reason it exists, so it's a good abstraction.
public interface Notification {
void send();
}
The implementations of this interface are the infrastructure services you are looking for. They will not (should not) be referenced directly by other "business" or "core" classes.
Note about making in an Entity: My own takeaway from reading the blue book is, that DDD is not about using Entity, Services, Aggregate Roots, and things like that. The main points are Ubiquitous Language, Contexts, how to work the Domain itself. Eric Evans himself says that this thinking can be applied to different paradigms. It does not have to always involve the same technical things.
Note about the "conventional" design from the other comment (#VoiceOfUnreason): In object-orientation at least, "holding state" is not a real responsibility. Responsibilities can only directly come from the Ubiquitous Language, in other words from the business. "Conventional" (i.e. procedural) design separates data and function, object-orientation does exactly the opposite. So be sure to decide which paradigm you are aiming for, then it may be easier to choose a solution.
After several iterations on developing the domain model, I continue to land on having a Notification base class as an entity, with subclasses SMSNotification, EmailNotification, etc. as child classes
That's probably an error.
public abstract class Notification extends Entity<UUID> {
public abstract void send();
}
That almost certainly is. You can make it work, if you twist enough, but you are going the wrong way around.
The responsibility of the entities in your domain model is the management of state. To also have the entity be responsible for the side effect of dispatching a message across your process boundary violates separation of concerns. So there should be a collaborator.
For Evans, as you will have noted, the collaboration takes the form of a domain service, that will itself collaborate with an infrastructure service to produce the desired result.
The most straight forward way to give the entity access to the domain service is to simply pass the domain service as an argument.
public class SMSNotification extends Notification {
public void send(SMSNotificationService sms) {
//logic for sending the SMS notification using an infrastructure service.
}
The SMSNotification supports a collaboration with an SMSNoticationService provider, and we make that explicit.
The interface you've offered here looks more like the Command Pattern. If you wanted to make that work, you would normally wire up the specific implementations in the constructor
public class SMSCommand extends NotificationCommand {
private final SMSNotificationService sms;
private final SMSNotification notification;
public final send() {
notification.send(sms);
}
}
There are some things you can do with generics (depending on your language choice) that make the parallels between these different services more apparent. For example
public abstract class Notification<SERVICE> extends Entity<UUID> {
public abstract void send(SERVICE service);
}
public class SMSNotification extends Notification<SMSNotificationService> {
public void send(SMSNotificationService service){
//logic for sending the SMS notification using an infrastructure service.
}
}
public class NotificationCommand<SERVICE> {
private final SERVICE service;
private final Notification<SERVICE> notification;
public final send() {
notification.send(service);
}
}
That's the main approach.
An alternative that sometimes fits is to use the poor man's pattern match. Instead of passing in the specific service needed by a particular type of entity, you pass them all in....
public abstract class Notification extends Entity<UUID> {
public abstract void send(SMSNotificationService sms, EmailNotificationService email, ....);
}
and then let each implementation choose precisely what it needs. I wouldn't expect this pattern to be a good choice here, but it's an occasionally useful club to have in the bag.
Another approach that you will sometimes see is to have the required services injected into the entity when it is constructed
SMSNotificationFactory {
private final SMSNotificationService sms;
SMSNotification create(...) {
return new SMSNotification(sms, ...);
}
}
Again, a good club to have in the bag, but not a good fit for this use case -- you can do it, but suddenly a lot of extra components need to know about the notification services to get them where they need to be.
What's best between notification.send(service) and service.send(notification)
Probably
notification.send(service)
using "Tell, don't ask" as the justification. You pass the collaborator to the domain entity, and it decides (a) whether or not to collaborate, (b) what state to pass to the domain service, and (c) what to do with any state that gets returned.
SMSNotification::send(SMSNotificationService service {
State currentState = this.getCurrentState();
{
Message m = computeMessageFrom(currentState);
service.sendMessage(m);
}
}
At the boundaries, applications are not object oriented; I suspect that as we move from the core of the domain toward the domain, we see entities give way to values give way to more primitive representations.
after reading a bit on pure domain models and the fact there shouldn't be any IO in there I'm not sure anymore
It is, in truth, a bit of a tangle. One of the motivations of domain services is to decouple the domain model from the IO -- all of the IO concerns are handled by the domain service implementation (or more likely, by an application/infrastructure service that the domain service collaborates with). As far as the entity is concerned, the method involved is just a function.
An alternative approach is to create more separation between the concerns; you make the orchestration between the two parts explicit
List<SMSRequest> messages = domainEntity.getMessages();
List<SMSResult> results = sms.send(messages)
domainEntity.onSMS(results)
In this approach, all of the IO happens within the sms service itself; the interactions with the model are constrained to in memory representations. You've effectively got a protocol that's managing the changes in the model and the side effects at the boundary.
I feel that Evans is suggesting that service.send(notification) be the interface.
Horses for courses, I think -- passing an entity to a domain service responsible for orchestration of multiple changes within the model makes sense. I wouldn't choose that pattern for communicating state to/from the boundary within the context of a change to an aggregate.

How can I use the Callback result in WCF?

I am new to WCF, and now designing a service with Pub/Sub using callback. I have this stupid question: how can I make use of the callback? Let's say I have the callback interface called ICallback, with one function called ProcessResult(). And I have an implementation class called MyCallback. Then in my client side, I can initialize it like this:
Dim cb As ICallback = New MyCallback()
Dim MyClient = New MyServiceClient(New InstanceContext(cb))
The class MyServiceClient is generated using svcutil.exe. Now whenever the WCF server gets information the client is interested in, it will call the callback function ProcessResult(). All the online examples I found online, for simplicity, just output a line inside the callback function. But in real life I need to pass this information out of the MyCallback class. This is where I lost: since on my client side, my objects are only using the funcitons of the object MyClient, not the cb, how can I implement the ProcessResult() function, so that the client objects can be aware of the fact that this function is called? I can for example raise an event, which is declared in the MyCallback class, inside this function, but since the client side objects don't have a reference to the cb, how can I make any event handler to handle it?
svcutil has an option /async which allow you to generate also async method calls. Isn't it help you?

How to use WCF Message for writing Multiple Objects

I have this requirement, I have two classes Person and Department and i want to send object of these two classes in the System.ServiceModel.Channels.Message? How can i accomplish this. I there any best way alternative to that.
Thanks in advance.
Message class has a static method called CreateMessage which has an overload to take any object that can be serialized.
Create a new datacontract\class with instances of Person and Department object. Pass the wrapper object to CreateMessage to serialize