How does the direction of a message could determine the method of a class (of a sequence diagram actor) ? I'd say the actor sending the message is the one having the method. Am I correct ?
And the classes For that are
Am I right or is it the other way around ?
"Sending a message" is in most cases the same as "calling a method", which means that if an actor sends a message to the computer, then the computer needs to understand it / implement a method.
There is a difference (see here 1) but essentially you "send a message" to an object, and the object decides what to do with it, in most cases it implements an appropriate method.
So to answer your question, the receiver of the message send should implement a method for it, not the sender.
Perhaps a pseudocode can also illustrate it:
class A {
function hello() {
b.someMessage();
c.otherMessage();
}
}
class B {
function someMessage() {
this.selfMessage();
}
}
Related
I've been struggling with this for a few days now, and I'm still not clear on the correct approach. I've seen many examples online, but each one does it differently. The options I see are:
Pass only primitive values
Pass the complete model
Pass new instances of value objects that refer to changes in the domain/model
Create a specific DTO/object for each event with the data.
This is what I am currently doing, but it doesn't convince me. The example is in PHP, but I think it's perfectly understandable.
MyModel.php
class MyModel {
//...
private MediaId $id;
private Thumbnails $thumbnails;
private File $file;
//...
public function delete(): void
{
$this->record(
new MediaDeleted(
$this->id->asString(),
[
'name' => $this->file->name(),
'thumbnails' => $this->thumbnails->toArray(),
]
)
);
}
}
MediaDeleted.php
final class MediaDeleted extends AbstractDomainEvent
{
public function name(): string
{
return $this->payload()['name'];
}
/**
* #return array<ThumbnailArray>
*/
public function thumbnails(): array
{
return $this->payload()['thumbnails'];
}
}
As you can see, I am passing the ID as a string, the filename as a string, and an array of the Thumbnail value object's properties to the MediaDeleted event.
How do you see it? What type of data is preferable to pass to domain events?
Updated
The answer of #pgorecki has convinced me, so I will put an example to confirm if this way is correct, in order not to change too much.
It would now look like this.
public function delete(): void
{
$this->record(
new MediaDeleted(
$this->id,
new MediaDeletedEventPayload($this->file->copy(), $this->thumbnail->copy())
)
);
}
I'll explain a bit:
The ID of the aggregate is still outside the DTO, because MediaDeleted extends an abstract class that needs the ID parameter, so now the only thing I'm changing is the $payload array for the MediaDeletedEventPayload DTO, to this DTO I'm passing a copy of the value objects related to the change in the domain, in this way I'm passing objects in a reliable way and not having strange behaviours if I pass the same instance.
What do you think about it?
A domain event is simply a data-holding structure or class (DTO), with all the information related to what just happened in the domain, and no logic. So I'd say Create a specific DTO/object for each event with the data. is the best choice. Why don't you start with the less is more approach? - think about the consumers of the event, and what data might they need.
Also, being able to serialize and deserialize the event objects is a good practice, since you could want to send them via a message broker (although this relates more to integration events than domain events).
in class standard class Dialog exist an Object declare (in classDeclaration)
Object caller;
In this class I'm able to get the caller class name. For example:
if (caller.name() == classStr(MyCallerClass) )
{
// manage-pass variable in caller class
}
If I catch in the IF, I want to pass a parameter in parm method in to MyCallerClass.
How I can pass a simple parameter? For example:
if (caller.name() == classStr(MyCallerClass) )
{
// MyCallerClass.myParmMethod(parameter);
}
Thanks.
Just call the method:
if (caller.name() == classStr(MyCallerClass))
caller.myParmMethod('abc');
As caller is of type Object the compiler accepts any method name, it uses duck typing.
A run time error happens if caller does not have the method.
That said, you should not change the standard Dialog class.
You might extend the class, though this is unlikely to be the right thing.
What you should do depends on information you do not give.
The correct & safe way is:
MyCallerClass myCalss;
if (caller && classidget(caller) == classnum(MyCallerClass))
{
myClass = caller;
myClass.myParmMethod('abc');
}
See examples in form.init methods.
So, let's say I need to get a list of favorite books for an Android app.
I have the list of ids, but I can only get one book at a time, so, I don't really have a bookAPI.getFavoriteBooks(listOfFavoriteIds) method call (the server doesn't have an endpoint for that), but instead I'd have to call bookAPI.getBook(id) for each id in the list to get all the favorite books, and after I get them I should return a list with the results.
The answers I've found so far assume that there's a method Observable<List<Book>> getFavoriteBooks(List<Integer> ids)I could call, but in this case I don't have that.
Is there a way of solving this question using RxAndroid and Retrofit 2?
It's hard to say from your question if this fits your needs, but you could try:
Observable.fromIterable(listOfIds)
.flatMap(new Function<Integer, ObservableSource<Book>>() {
#Override
public ObservableSource<Book> apply(Integer integer)
throws Exception {
return bookApi.getBook(id);
}
})
.toList()
Let me explain what's happening here. fromIterable creates an observable that emits each element in the iterable as an event. In this case it will emit each book id.
You then flat map said observable to your api observable. So in this case you're mapping each emitted Id to an observable that emits each book from the api.
Finally, you collect all the emitted books as a list. Once you subscribe to this stream it will have a list as a single event:
// whatever way you get the above stream
.subscribe(new Consumer<List<Book>>() {
#Override
public void accept(List<Book> result) throws Exception {
// do whatever you want with result
}
});
Just make sure to use the right schedulers for your use case.
(Careful because this subscribe call doesn't handle errors, but I guess you can figure that out pretty easily)
I would like to have a test that goes through all methods available in a controller and retrieves roles associated with these methods. I understand that it should be a functional test (as opposed to a unit test), but I still do not know how to request the list of roles associated with a method.
Let's say I have this controller:
#Secured("hasAnyRole('ROLE_1')"
class MyController {
def methodA() {}
#Secured("hasAnyRole('ROLE_2')"
def methodB() {}
}
In my test I would like to have something like this:
assertEquals(['ROLE_1'],getRoles(MyController.class, "methodA"))
assertEquals(['ROLE_1', 'ROLE_2'],getRoles(MyController.class, "methodB"))
Any suggestions?
Thanks.
You can do this with the Reflection API. Something like:
Method m = MyController.class.getMethod("methodB");
Annotation[] annos = m.getAnnotations();
But I don't think that's a good validation for your method, since it only ensure that you write the role name correctly. I think it's better you try to call the action and check if the process redirect to denied.
#TestFor(MyController)
class MyControllerTests {
#Test
void shouldRedirectToDenied() {
SpringSecurityUtils.doWithAuth('username') {
controller.methodB()
assert controller.response.redirectedUrl == '/login/denied'
}
}
}
The doWithAuth closure will mock an authentication for the username, so it's the same to say: "do this code as if the username was logged in successfully".
It seems that you will need to use functional tests indeed. See Burt's comment. I'm still think that's not a valid effort create a test only to validate if the method have the annotation.
Let's consider a simple Groovy DSL
execute {
sendNotification owner
sendNotification payee
}
The implementation of execute is
public static void execute(Closure dslCode) {
Closure clonedCode = dslCode.clone()
def dslDelegate = new MyDslDelegate(owner: 'IncCorp', payee: 'TheBoss')
clonedCode.delegate = dslDelegate
clonedCode.call()
}
and custom Delegate is
public static class MyDslDelegate {
def owner
def payee
void sendNotification(to) {
println "Notification sent to $to"
}
}
The expected result of running execute block is
Notification sent to IncCorp
Notification sent to TheBoss
the actual one is
Notification sent to class package.OwnerClassName
Notification sent to TheBoss
The problem is owner is a reserved property in the Groovy Closure itself and no resolveStrategy options help to replace owner value with custom value from delegate due to Groovy getProperty implementation for Closure
public Object getProperty(final String property) {
if ("delegate".equals(property)) {
return getDelegate();
} else if ("owner".equals(property)) {
return getOwner();
...
} else {
switch(resolveStrategy) {
case DELEGATE_FIRST:
...
}
My question is how some one can outcome this limitation and use owner property name in a custom DSL?
This is a bit of a hack, but this should get you what you want, without altering Groovy source:
public static void execute(Closure dslCode) {
Closure clonedCode = dslCode.clone()
def dslDelegate = new MyDslDelegate(owner: 'IncCorp', payee: 'TheBoss')
clonedCode.#owner = dslDelegate.owner
clonedCode.resolveStrategy = Closure.DELEGATE_ONLY
clonedCode.delegate = dslDelegate
clonedCode.call()
}
Ref: Is it possible to change the owner of a closure?
The simple answer is no, you can't. 'owner' is a reserved keyword in Groovy, and therefore by definition cannot be used as an arbitrary symbol. Even if there is a way to hack around this, you're far better off just using a name that doesn't conflict with the implementation of the language- this is especially true in Groovy, which keeps promising to redesign its MOP completely, meaning that any hack you implement may well stop working in future versions.
Perhaps the question would make more sense if you explained why you are willing to offer a bounty and search for a way of hacking around this problem, rather than just changing the name to something different and avoiding the problem entirely. Reserved symbols are a pretty fundamental limitation of a language, and ever attempting to work around them seems very unwise.