This is my code snippet
public class Notation : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Notes _note;
}
How to write public event PropertyChangedEventHandler PropertyChanged; in UML Class diagram properly?
First, I think it's:
+PropertyChanged: PropertyChangedEventHandler
But then, I realized that it doesn't represent the event part of the code.
Any idea?
Here is the UML stereotype in the game. Just stereotype this property:
Note that _note is a plain, private property.
You can define receptions in class definition. Reception is type of behavioral feature. If you define it, instance of class can accept signal events from environment.
Other way to define events in UML is using behavioral diagrams.
Activity diagram has event element to accept events of specific types during execution.
State Machine diagram has transitions with trigger definition, which represents event acceptance as well.
Interaction diagram represents events as receiving or sending messages.
Behavior definitions (represented by behavioral diagrams) can be assigned to class definition as classifier behavior or owned behaviors. Owned behavior definition defines ability of owning class to react on event occurrences.
Your example just defines attribute of class, but not ability to accept event by class instance.
Related
I am trying to find a way to render UI buttons (actions) depending on the object state. Is there a way to ask the state machine: "show me events that are applicable for a given state ?" Example of confguration:
public class OfcProjectVersionSMConfiguration extends EnumStateMachineConfigurerAdapter<OfcProjectVersionStates, OfcProjectVersionEvents>
....
public void configure(StateMachineTransitionConfigurer<OfcProjectVersionStates, OfcProjectVersionEvents> transitions) throws Exception {
transitions
.withExternal().source(OfcProjectVersionStates.DRAFT).target(OfcProjectVersionStates.DRAFT).event(OfcProjectVersionEvents.U)
.and()
.withExternal().source(OfcProjectVersionStates.DRAFT).target(OfcProjectVersionStates.DELETED).event(OfcProjectVersionEvents.D)
....
I found out that this would work, but not sure is this the right way.
public abstract class GenericEnumStateMachineUtils extends StateMachineUtils {
public static <S, E> Collection<E> findEventsForState(StateMachine<S, E> stateMachine, S state) {
Collection<E> eventsForState = stateMachine.getTransitions().stream().filter(p -> p.getSource().getId().equals(state)).map(p -> p.getTrigger().getEvent()).collect(Collectors.toCollection(ArrayList::new));
return eventsForState;
}
Unfortunately we don't have any reliable ways to know if machine in a particular state would be applicable to process/accept a certain events. Having events as enums you'd know possible possible values but then if events are strings you have infinite list of possible values unless you store those externally in a list.
It gets even more complicated if you have deep nested hierarchical states where you may have different events and if lowest active state don't accept event its then offered to its parent state and so on.
Trouble is that there may be guards doing dynamic evaluations and asking a question of what events machine would accept is like predicting what machine will do in a future.
I have a signal produced from a module. I want to define a signal listener class in another module but whenever I want to subclass it from CIListener, it says it cannot make a new instance from my subclassed listener because the CIListener class is a pure virtual class (interface class). But I have re-declared or redefined all the pure virtual methods in my listener class. Instead when I user CListener class to subclass my listener it works! Do I have to subclass from CIListener?
I guess you believe that you have re-defined all pure methods, but in fact the compiler thinks otherwise. There are 7 pure virtual methods that should be implemented with the proper signatures. If you want to support only certain data types (as it is in most cases) I would suggest to implement (extend) the cListener as it is just a NOP implementation of the cIListener interface (with all its methods throwing a datatype not supported error). Be sure to see whether you indeed override the necessary methods. You may use the override C++ keyword in your method definition.
Should domain events be dispatched according to event classes, or classes and a topic?
For example, I have the following event:
class UserRegisteredEvent implements INonTransactionalEvent{
public Timestamp: TTimestamp;
}
And an event manager,
class EventManager {
/** Omitted **/
}
Udi Dahan proposes that events are first class objects, and I like that. There is a UserRegisteredEvent object, an OrderComplete object. My question is, does the type itself get bound to the event handlers? For example, should I just pass the event object to the publish method?
EventManager.Publish(new UserRegisteredEvent(1));
This means each handler is bound to a single class type, which seems limiting. While YAGNI may be true, is the following not more powerful:
EventManager.Publish(new UserRegisteredEvent(1), Events.UserRegistered)
Whereby the event topic is what the handlers bind to. This way, handlers can benefit from inheritance. If type safety or usage of a ubiquitous language was an issue, one could do:
EventManager.UserRegisteredEvent(1)
Which is simply a short method to the longer publish version. This annoys me a little, as it means the class must be altered for every new event, which seems unnecessary (and indeed, not necessary if using the above method).
While I've only seen events get published as classes with no topic, is this limiting, or has anyone run into issues with this?
Domain events don't really require a specific implementation. After all they are just semantic DTOs. I don't understand what you're trying to accomplish, but unless you're building a service bus you just send the event object to be handled by whatever handlers are configured.
The Event doesn't know about the handlers, the handlers don't know about each other, the bus knows how to send the event to the handlers. And you want a handler to explicitly handle only 1 event, SRP . You can combine implementations of related handlers into one class, but that's an implementation detail.
If you really feel like introducing topics, I'd do it through interface inheritance. For instance:
interface IUserEvent : INonTransactionalEvent { ... }
class UserRegisteredEvent implements IUserEvent {
public Timestamp: TTimestamp;
}
The impact in your code and language would be negligible, you can keep using a generic Publish method accepting INonTransactionalEvent and you can also easily refactor your topics.
I will explain with an example. My GWT project has a Company module, which lets a user add, edit, delete, select and list companies.
Of these, the add, edit and delete operations lands back the user on the CompanyList page.
Thus, having three different events - CompanyAddedEvent, CompanyUpdatedEvent and CompanyDeletedEvent, and their respective event handlers - seems overkill to me, as there is absolutely not difference in their function.
Is it OK to let a single event manage the three operations?
One alternative I think is to use some event like CompanyListInvokedEvent. However, somewhere I think its not appropriate, is the event actually is not the list being invoked, but a company being added/updated/deleted.
If it had been only a single module, I would have get the task done with three separate events. But other 10 such modules are facing this dilemma. It means 10x3 = 30 event classes along with their 30 respective handlers. The number is large enough for me to reconsider.
What would be a good solution to this?
UPDATE -
#ColinAlworth's answer made me realize that I could easily use Generics instead of my stupid solution. The following code represents an event EntityUpdatedEvent, which would be raised whenever an entity is updated.
Event handler class -
public class EntityUpdatedEvent<T> extends GwtEvent<EntityUpdatedEventHandler<T>>{
private Type<EntityUpdatedEventHandler<T>> type;
private final String statusMessage;
public EntityUpdatedEvent(Type<EntityUpdatedEventHandler<T>> type, String statusMessage) {
this.statusMessage = statusMessage;
this.type = type;
}
public String getStatusMessage() {
return this.statusMessage;
}
#Override
public com.google.gwt.event.shared.GwtEvent.Type<EntityUpdatedEventHandler<T>> getAssociatedType() {
return this.type;
}
#Override
protected void dispatch(EntityUpdatedEventHandler<T> handler) {
handler.onEventRaised(this);
}
}
Event handler interface -
public interface EntityUpdatedEventHandler<T> extends EventHandler {
void onEventRaised(EntityUpdatedEvent<T> event);
}
Adding the handler to event bus -
eventBus.addHandler(CompanyEventHandlerTypes.CompanyUpdated, new EntityUpdatedEventHandler<Company>() {
#Override
public void onEventRaised(EntityUpdatedEvent<Company> event) {
History.newItem(CompanyToken.CompanyList.name());
Presenter presenter = new CompanyListPresenter(serviceBundle, eventBus, new CompanyListView(), event.getStatusMessage());
presenter.go(container);
}
});
Likewise, I have two other Added and Deleted generic events, thus eliminating entire redundancy from my event-related codebase.
Are there any suggestions on this solution?
P.S. > This discussion provides more insight on this problem.
To answer this question, let me first pose another way of thinking about this same kind of problem - instead of events, we'll just use methods.
In my tiered application, two modules communicate via an interface (notice that these methods are all void, so they are rather like events - the caller doesn't expect an answer back):
package com.acme.project;
public interface CompanyServiceInteface {
public void addCompany(CompanyDto company) throws AcmeBusinessLogicException;
public void updateCompany(CompanyDto company) throws AcmeBusinessLogicException;
public void deleteCompany(CompanyDto company) throws AcmeBusinessLogicException;
}
This seems like overkill to me - why not just reduce the size of this API to one method, and add an enum argument to simplify this. This way, when I build an alternative implementation or need to mock this in my unit tests, I just have one method to build instead of three. This gets to be clearly overkill when I make the rest of my application - why not just ObjectServiceInterface.modify(Object someDto, OperationEnum invocation); to work for all 10 modules?
One answer is that you might want want to drastically modify the implementation of one but not the others - now that you've reduced this to just one method, all of this belongs inside that switch case. Another is that once simplified in this way, the inclination often to further simplify - perhaps to combine create and update into just one method. Once this is done, all callsites must make sure to fulfill all possible details of that method's contract instead of just the one specific one.
If the receivers of those events are simple and will remain so, there may be no good reason to not just have a single ModelModifiedEvent that clearly is generic enough for all possible use cases - perhaps just wrapping the ID to request that all client modules refresh their view of that object. If a future use case arises where only one kind of event is important, now the event must change, as must all sites that cause the event to be created so that they properly populate this new field.
Java shops typically don't use Java because it is the prettiest language, or because it is the easiest language to write or find developers for, but because it is relatively easy to maintain and refactor. When designing an API, it is important to consider future needs, but also to think about what it will take to modify the current API - your IDE almost certainly has a shortcut key to find all invocations of a particular method or constructor, allowing you to easily find all places where that is used and update them. So consider what other use cases you expect, and how easily the rest of the codebase can be udpated.
Finally, don't forget about generics - for my example above, I would probably make a DtoServiceInterface to simplify matters, so that I just declare the one interface with three methods, and implement it and refer to it as needed. In the same way, you can make one set of three GwtEvent types (with *Handler interfaces and possibly Has*Handlers as well), but keep them generic for all possible types. Consider com.google.gwt.event.logical.shared.SelectionEvent<T> as an example here - in your case you would probably want to make the model object type a parameter so that handlers can check which type of event they are dealing with (remember that generics are erased in Java), or source from one EventBus for each model type.
After my wonderings on the events registration (you can find here ViewModel Event Registration and ViewModel Lifetime), now I'm thinking about viewmodel tombstoning:
In case of Tombstoning, is the ViewModel serialization a good approach ?
I'm thinking about the case in which different viewmodels have a reference to the same class. In case of Viewmodels serialization and deserialization the referenced class instance could have duplicated instance, isn't it ?
Wouldn't be better to have specialized state classes whose unique purpose in to contain all the app data, everyviewmodel get data (i mean reference to the data) from there and update the data in there and the app think only to serialize those specialized class ?
Any experience on this subject is appreciated.
Regards
SkyG
Caliburn Micro has a lot of this built in to the framwork allowing you to save properties of a view model or the entire graph to both phone state and app settings. You just need to create a class and inherit from StorageHandler.
public class PivotPageModelStorage : StorageHandler<PivotPageViewModel>
{
public override void Configure()
{
this.ActiveItemIndex().InPhoneState().RestoreAfterViewLoad();
}
}
And to your other posted question. CM has a nice way of handling the forced view first approach on the phone. It allows you to do page navigation by specifying the VM and it will handle the rest. And as a bonus, if you specify parameters to pass CM will pull them off the query string and populate properties on the target VM.
public void GotoPageTwo()
{
navigationService.UriFor<PivotPageViewModel>().WithParam(x => x.NumberOfTabs, 5).Navigate();
}