I have been reading the Gang Of Four, in order to solve some of my problems and came across the Mediator pattern.
I had earlier used Observer in my projects for making some GUI application. I am a bit confused as I do not find great difference between the two. I browsed to find the difference but could not find any apt answer for my query.
Could some one help me to differentiate between the two with some good example which clearly demarcates the two?
The Observer pattern:
Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
The Mediator pattern:
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
Source: dofactory
Example:
The observer pattern:
Class A, can have zero or more observers of type O registered with it. When something in A is changed it notifies all of the observers.
The mediator pattern:
You have some number of instances of class X (or maybe even several different types:X, Y & Z), and they wish to communicate with each other (but you don't want each to have explicit references to each other), so you create a mediator class M. Each instance of X has a reference to a shared instance of M, through which it can communicate with the other instances of X (or X, Y and Z).
In the original book that coined the terms Observer and Mediator, Design Patterns, Elements of Reusable Object-Oriented Software, it says that the Mediator pattern can be implemented by using the observer pattern. However it can also be implemented by having Colleagues (which are roughly equivalent to the Subjects of the Observer pattern) have a reference to either a Mediator class or a Mediator interface.
There are many cases when you would want to use the observer pattern, they key is that an object should not know what other objects are observing it's state.
Mediator is a little more specific, it avoids having classes communicate directly but instead through a mediator. This helps the Single Responsibility principle by allowing communication to be offloaded to a class that just handles communication.
A classic Mediator example is in a GUI, where the naive approach might lead to code on a button click event saying "if the Foo panel is disabled and Bar panel has a label saying "Please enter date" then don't call the server, otherwise go ahead", where with the Mediator pattern it could say "I'm just a button and have no earthly business knowing about the Foo panel and the label on the Bar panel, so I'll just ask my mediator if calling the server is O.K. right now."
Or, if Mediator is implemented using the Observer pattern the button would say "Hey, observers (which would include the mediator), my state changed (someone clicked me). Do something about it if you care". In my example that probably makes less sense then directly referencing the mediator, but in many cases using the Observer pattern to implement Mediator would make sense, and the difference between Observer and Mediator would be more one of intent than a difference in the code itself.
Observer
1. Without
Client1: Hey Subject, when do you change?
Client2: When did you change Subject? I have not noticed!
Client3: I know that Subject has changed.
2. With
Clients are silent.
Some time later ...
Subject: Dear clients, I have changed!
Mediator
1. Without
Client1: Hey Taxi1, take me some where.
Client2: Hey Taxi1, take me some where.
Client1: Hey Taxi2, take me some where.
Client2: Hey Taxi2, take me some where.
2. With
Client1: Hey TaxiCenter, please take me a Taxi.
Client2: Hey TaxiCenter, please take me a Taxi.
These patterns are used in different situations:
The mediator pattern is used when you have two sub-systems with some dependency and one of them is due for a change, and since you might not want to change the system that depends on the other, you may want to introduce a mediator which will decouple the dependency between them. That way, when one of the sub-systems changes, all you have to do is to update the mediator.
The observer pattern is used when a class wants to allow other classes to register themselves and receive notifications upon events, e. g. ButtonListener etc.
Both of these patterns allow for lesser coupling, but are quite different.
Lets go by an example: consider you want to build two application:
Chat application.
Emergency ambulance operator application.
mediator
Building the chat application you will be choosing the mediator design pattern.
The persons may be joining and leaving the chat at any given time, so it does not make any sense to keep direct reference between two persons chatting.
We still need to facilitate a communication between two persons and allow them have a chat.
Why will we prefer the mediator? just have a look at its definition:
With the mediator pattern, communication between objects is
encapsulated within a mediator object. Objects no longer communicate
directly with each other, but instead communicate through the
mediator. This reduces the dependencies between communicating objects,
thereby reducing coupling.
How is the magic works? First we will create the chat mediator and make the persons objects register to it, so it will have two directional connection with every single person (the person can send message using the chat mediator cause it ha access to it, and the chat mediator will access the received method of the person object cause he also has access to it)
function Person(name) {
let self = this;
this._name = name;
this._chat = null;
this._receive(from, message) {
console.log("{0}: '{1}'".format(from.name(), message));
}
this._send(to, message) {
this._chat.message(this, to, message);
}
return {
receive: (from, message) => { self._receive(from, message) },
send: (to, message) => { self._send(to, message) },
initChat: (chat) => { this._chat = chat; },
name: () => { return this._name; }
}
}
function ChatMediator() {
let self = this;
this._persons = [];
return {
message: function (from, to, message) {
if (self._persons.indexOf(to) > -1) {
self._persons[to].receive(from, message);
}
},
register: function (person) {
person.initChat(self);
self._persons.push(person);
}
unRegister: function (person) {
person.initChat(null);
delete self._persons[person.name()];
}
}
};
//Usage:
let chat = new ChatMediator();
let colton = new Person('Colton');
let ronan = new Person('Ronan');
chat.register(colton);
chat.register(ronan);
colton.send(ronan, 'Hello there, nice to meet you');
ronan.send(colton, 'Nice to meet you to');
colton.send(ronan, 'Goodbye!');
chat.unRegister(colton);
observer
Building the 911 call application you will be choosing the observer design pattern.
Each ambulance observer object wishes to be informed when there is an emergency state, so he can drive the address and give help.
The emergency operator observable keep reference to each on of the ambulance observers and notify them when help is needed (or generating event).
Why will we prefer the observer? just have a look at its definition:
An object, called the subject, maintains a list of its dependents,
called observers, and notifies them automatically of any state
changes, usually by calling one of their methods.
function AmbulanceObserver(name) {
let self = this;
this._name = name;
this._send(address) {
console.log(this._name + ' has been sent to the address: ' + address);
}
return {
send: (address) => { self._send(address) },
name: () => { return this._name; }
}
}
function OperatorObservable() {
let self = this;
this._ambulances = [];
return {
send: function (ambulance, address) {
if (self._ambulances.indexOf(ambulance) > -1) {
self._ambulances[ambulance].send(address);
}
},
register: function (ambulance) {
self._ambulances.push(ambulance);
}
unRegister: function (ambulance) {
delete self._ambulances[ambulance.name()];
}
}
};
//Usage:
let operator = new OperatorObservable();
let amb111 = new AmbulanceObserver('111');
let amb112 = new AmbulanceObserver('112');
operator.register(amb111);
operator.register(amb112);
operator.send(amb111, '27010 La Sierra Lane Austin, MN 000');
operator.unRegister(amb111);
operator.send(amb112, '97011 La Sierra Lane Austin, BN 111');
operator.unRegister(amb112);
The Differences:
The chat mediator has two way communication between the persons objects (send and receive) wheres the operator observable has only one way communication (It tell the ambulance observer to drive and finish).
The chat mediator can make the persons objects interact between them (even if it not a direct communication), the ambulances observers only registers to the operator observable events.
Each person object has a reference to the chat mediator, and also the chat mediator keep reference to the every one of the persons. Wheres the ambulance observer does not keep reference to the operator observable, only the operator observable keep reference to every ambulance observer.
Although both of them are used for organised way of telling about state changes, they're slightly different structurally and semantically IMO.
Observer is used to broadcast a state change of a particular object, from the object itself. So the change happens in the central object that is also responsible for signalling it. However, in Mediator, state change can happen in any object but it's broadcasted from a mediator. So there's a difference in the flow. But, I don't think this affects our code behaviour. We can use one or another to achieve the same behaviour. On the other hand, this difference might have some affects on conceptual understanding of the code.
See, the primary purpose of using patterns is rather to create a common language between developers. So, when I see a mediator, I personally understand multiple elements trying to communicate over a single broker/hub to reduce communication noise (or to promote SRP) and each object is equally important in terms of having the ability of signalling a state change. For example, think of multiple aircrafts approaching to an airport. Each should communicate over the pylon (mediator) rather than communicating with each other. (Think of 1000 aircrafts communicating with each other when landing - that would be a mess)
However, when I see an observer, it means there're some state changes I might be care about and should register/subscribe to listen particular state changes. There's a central object responsible for signalling state changes. For example, if I care about a specific airport on my way from A to B, I can register to that airport to catch some events broadcasted like if there's an empty runway or something like that.
Hope it's clear.
#cdc explained the difference in intent excellently.
I will add some more info on top it.
Observer : Enables notification of a event in one object to different set of objects ( instances of different classes)
Mediator: Centralize the communication between set of objects, created from a particular class.
Structure of Mediator pattern from dofactory:
Mediator: Defines an interface for communication between Colleagues.
Colleague: Is an abstract class, which defines the events to be communicated between Colleagues
ConcreteMediator: Implements cooperative behavior by coordinating Colleague objects and maintains its colleagues
ConcreteColleague: Implements the notification operations received through Mediator, which has been generated by other Colleague
One real world example:
You are maintaining a network of computers in Mesh topology. If a new computer is added Or existing computer is removed, all other computers in that network should know about these two events.
Let's see how Mediator pattern fits into it.
Code snippet:
import java.util.List;
import java.util.ArrayList;
/* Define the contract for communication between Colleagues.
Implementation is left to ConcreteMediator */
interface Mediator{
public void register(Colleague colleague);
public void unregister(Colleague colleague);
}
/* Define the contract for notification events from Mediator.
Implementation is left to ConcreteColleague
*/
abstract class Colleague{
private Mediator mediator;
private String name;
public Colleague(Mediator mediator,String name){
this.mediator = mediator;
this.name = name;
}
public String toString(){
return name;
}
public abstract void receiveRegisterNotification(Colleague colleague);
public abstract void receiveUnRegisterNotification(Colleague colleague);
}
/* Process notification event raised by other Colleague through Mediator.
*/
class ComputerColleague extends Colleague {
private Mediator mediator;
public ComputerColleague(Mediator mediator,String name){
super(mediator,name);
}
public void receiveRegisterNotification(Colleague colleague){
System.out.println("New Computer register event with name:"+colleague+
": received #"+this);
// Send further messages to this new Colleague from now onwards
}
public void receiveUnRegisterNotification(Colleague colleague){
System.out.println("Computer left unregister event with name:"+colleague+
":received #"+this);
// Do not send further messages to this Colleague from now onwards
}
}
/* Act as a central hub for communication between different Colleagues.
Notifies all Concrete Colleagues on occurrence of an event
*/
class NetworkMediator implements Mediator{
List<Colleague> colleagues = new ArrayList<Colleague>();
public NetworkMediator(){
}
public void register(Colleague colleague){
colleagues.add(colleague);
for (Colleague other : colleagues){
if ( other != colleague){
other.receiveRegisterNotification(colleague);
}
}
}
public void unregister(Colleague colleague){
colleagues.remove(colleague);
for (Colleague other : colleagues){
other.receiveUnRegisterNotification(colleague);
}
}
}
public class MediatorPatternDemo{
public static void main(String args[]){
Mediator mediator = new NetworkMediator();
ComputerColleague colleague1 = new ComputerColleague(mediator,"Eagle");
ComputerColleague colleague2 = new ComputerColleague(mediator,"Ostrich");
ComputerColleague colleague3 = new ComputerColleague(mediator,"Penguin");
mediator.register(colleague1);
mediator.register(colleague2);
mediator.register(colleague3);
mediator.unregister(colleague1);
}
}
output:
New Computer register event with name:Ostrich: received #Eagle
New Computer register event with name:Penguin: received #Eagle
New Computer register event with name:Penguin: received #Ostrich
Computer left unregister event with name:Eagle:received #Ostrich
Computer left unregister event with name:Eagle:received #Penguin
Explanation:
Eagle is added to network at first through register event. No notifications to any other colleagues since Eagle is the first one.
When Ostrich is added to the network, Eagle is notified : Line 1 of output is rendered now.
When Penguin is added to network, both Eagle and Ostrich have been notified : Line 2 and Line 3 of output is rendered now.
When Eagle left the network through unregister event, both Ostrich and Penguin have been notified. Line 4 and Line 5 of output is rendered now.
How About this explanation
Technically both Observer and Mediator are the same and are used to provide decoupled way for component communication, but usage is different.
While obeserver notifies subscribed components about state changes (creation of new db record, for instance), the mediator commands registered components to do something related to business logic flow (sending email to user for password reset).
Observer
Notification consumers are responsible to subscribe in order to receive notifications
Notification processing is not part of business flow
Mediator
Explicit registration required to connect "publisher" and "consumers"
Notification processing is part of specific business flow
Related
I am working on a distributed algorithm and decided to use a Akka to scale it across machines. The machines need to exchange messages very frequently and these messages reference some immutable objects that exist on every machine. Hence, it seems sensible to "compress" the messages in the sense that the shared, replicated objects should not be serialized in the messages. Not only would this save on network bandwidth but it also would avoid creating duplicate objects in the receiver side whenever a message is deserialized.
Now, my question is how to do this properly. So far, I could think of two options:
Handle this on the "business layer", i.e., converting my original message objects to some reference objects that replace references to the shared, replicated objects by some symbolic references. Then, I would send those reference objects rather than the original messages. Think of it as replacing some actual web resource with a URL. Doing this seems rather straight-forward in terms of coding but it also drags serialization concerns into the actual business logic.
Write custom serializers that are aware of the shared, replicated objects. In my case, it would be okay that this solution would introduce the replicated, shared objects as global state to the actor systems via the serializers. However, the Akka documentation does not describe how to programmatically add custom serializers, which would be necessary to weave in the shared objects with the serializer. Also, I could imagine that there are a couple of reasons, why such a solution would be discouraged. So, I am asking here.
Thanks a lot!
It's possible to write your own, custom serializers and let them do all sorts of weird things, then you can bind them at the config level as usual:
class MyOwnSerializer extends Serializer {
// If you need logging here, introduce a constructor that takes an ExtendedActorSystem.
// class MyOwnSerializer(actorSystem: ExtendedActorSystem) extends Serializer
// Get a logger using:
// private val logger = Logging(actorSystem, this)
// This is whether "fromBinary" requires a "clazz" or not
def includeManifest: Boolean = true
// Pick a unique identifier for your Serializer,
// you've got a couple of billions to choose from,
// 0 - 40 is reserved by Akka itself
def identifier = 1234567
// "toBinary" serializes the given object to an Array of Bytes
def toBinary(obj: AnyRef): Array[Byte] = {
// Put the code that serializes the object here
//#...
Array[Byte]()
//#...
}
// "fromBinary" deserializes the given array,
// using the type hint (if any, see "includeManifest" above)
def fromBinary(
bytes: Array[Byte],
clazz: Option[Class[_]]): AnyRef = {
// Put your code that deserializes here
//#...
null
//#...
}
}
But this raises an important question: if your messages all references data that is shared on the machines already, why would you want to put in the message the pointer to the object (very bad! messages should be immutable, and a pointer isn't!), rather than some sort of immutable, string objectId (kinda your option 1) ? This is a much better option when it comes to preserving the immutability of the messages, and there is little change in your business logic (just put a wrapper over the shared state storage)
for more info, see the documentation
I finally went with the solution proposed by Diego and want to share some more details on my reasoning and solution.
First of all, I am also in favor of option 1 (handling the "compaction" of messages in the business layer) for those reasons:
Serializers are global to the actor system. Making them stateful is actually a most severe violation of Akka's very philosophy as it goes against the encapsulation of behavior and state in actors.
Serializers have to be created upfront, anyway (even when adding them "programatically").
Design-wise, one can argue that "message compaction is not a responsibility of the serializer, either. In a strict sense, serialization is merely the transformation of runtime-specific data into a compact, exchangable representation. Changing what to serialize, is not a task of a serializer, though.
Having settled upon this, I still strived for a clear separation of "message compaction" and the actual business logic in the actors. I came up with a neat way to do this in Scala, which I want to share here. The basic idea is to make the message itself look like a normal case class but still allow these messages to "compactify" themselves. Here is an abstract example:
class Sender extends ActorRef {
def context: SharedContext = ... // This is the shared data present on every node.
// ...
def someBusinessLogic(receiver: ActorRef) {
val someData = computeData
receiver ! MyMessage(someData)
}
}
class Receiver extends ActorRef {
implicit def context: SharedContext = ... // This is the shared data present on every node.
def receiver = {
case MyMessage(someData) =>
// ...
}
}
object Receiver {
object MyMessage {
def apply(someData: SomeData) = MyCompactMessage(someData: SomeData)
def unapply(myCompactMessage: MyCompactMessage)(implicit context: SharedContext)
: Option[SomeData] =
Some(myCompactMessage.someData(context))
}
}
As you can see, the sender and receiver code feels just like using a case class and in fact, MyMessage could be a case class.
However, by implementing apply and unapply manually, one can insert its own "compactification" logic and also implicitly inject the shared data necessary to do the "uncompactification", without touching the sender and receiver. For defining MyCompactMessage, I found Protocol Buffers to be especially suited, as it is already a dependency of Akka and efficient in terms of space and computation, but any other solution would do.
This is a question regarding the concept of OOP.
Let's say I'm creating a game and I have a few objects:
Field - representig some field on the map.
User - representing a player.
Item - representing an item that user can have (for example shovel)
Now I know that player can dig a field using shovel. And this action will be a method of one of those classes. Is there some rule to determine which of those classes should have this method.
The most obvious performer of this action is the player (User), so User class could have method like digField(Field field). But actually the field itself is most affected by this action, so maybe it shold be the Field class method, like dig(User performer) or dig(Item toolUsed). Or maybe the Item itself should have a child class like Tool with a method like digField(Field field).
There are lots of ways to solve this problem and I was just wondering if there is some kind of simple best practice there.
Like said in other answers, it depends on what else is happening (or can happen in the future).
For example, for digging there can be some options:
user.digField(field, tool): this way can be helpful when your user also needs to spend time, or maybe he gets tired, i.e. use this way if you want to FOCUS on the user.
field.dig(user, tool): this way can be helpful when the field itself should be focussed on, like setting the status of the field.
tool.dig(user, field): this way can be used to change e.g. the status of the tool, or the maintenance needed.
However, in most cases there are a multiple of statuses/changes need to be set. So maybe it is best to create a separate class Action like:
public class Action
{
public void DigField(User user, Location location, Tool tool)
{
user.Status = Digging;
user.Energy -= 50;
location.Status = Digging;
tool.Status = Digging;
tool.Usage++;
}
}
As you can see this function may grow as action might get more complex. So what is a good way to call separate functions in the appropriate classes, like a mix:
public class Action
{
public void DigField(User user, Location location, Tool tool)
{
user.DigField();
location.Dig();
tool.Dig();
}
}
public class User
{
public void DigField()
{
Status = Digging;
Energy -= 50;
}
}
public class Field
{
public void Dig()
{
Status = Digging;
}
}
public class Tool
{
public void Dig()
{
Status = Digging;
Usage++;
}
}
This has the advantage to keep the functionality where it belongs.
Nothing prevents you from passing parameters, like if the energy drain for auser depends on the type of field, use:
public class User
{
public void DigField(Field field)
{
Status = Digging;
Energy -= field.Type == Clay ? 30 : 20;
}
}
It depends on the rest of your game. You can't architect your classes without thinking about all of it. So questions such as:
Are there many tools, do they perform different actions on different objects?
Are there many types of land masses (field, stream, etc)
Does the user have any effect (such as with strength) on the action
These types of questions are useful to think about before laying out your classes. As an example, if you have many different tools, then you could tie the digging with the shovel, which will detail what it does to different types of land (and which ones it can work with). Then maybe there is a tractor, which does something different to the land.
One last thought, the closer your classes match the real world, the better the classes work as the code expands. In other words, if you were describing a shovel to someone who has never seen one, your class should model itself after that kind of description.
This not a case of overloading, I think you have recognise the complexity but you are trying to escape it. It's been you take time to model it now,it may be costly later.
Here is what I think:
User object performs the action so it must have the User.Dig() method. Maybe you can decide to pass in an Item object (eg Shovel).
Field object reacts to the action (Dig) of the User object. You now have to determine what this reaction is. Also you determine what the action is.
Like you said there are likely many approach and I think game engines have solved problems like this but I don't use them so I can't recommend. If I would have to model what explain I first try out Observable Pattern https://en.wikipedia.org/wiki/Observer_pattern?wprov=sfla1
Good luck
I have a sample(incomplete) class like
class ABC{
public:
void login();
void query_users();
//other methods
private:
//member data
}
This class should be used in a way that login needs to be called first and then only other methods like query_users, etc., can be called. Login sets some private member data for the other methods to use. Is there any simpler way to achieve this other than calling a function that checks if the member data is set at the start of every other method in the class?
There are two general approach I know of, and they differ a good bit. You'll have to pick the appropriate mechanism for the task - in standard class-based OO languages (e.g. Java/C++/C#/Python), they are the only two approaches I know of. (There may be other approaches in different paradigms that I am unfamiliar with.)
1. Check the state.
This is done in many classes already that have to track the state of the system/backing resource. Two common examples are (file) stream and database connections.
A "template" might look like:
void Logon(credentials) { ..; loggedOn = true }
void DieUnlessLoggedIn { if (!loggedOn) { throw .. } }
void DoStuff () { DieUnlessLoggedIn(); .. }
While the above approach is pretty generic, some languages may support invariants (Eiffel), decorations (Python), annotations, AOP, or other assertion mechanisms.
This approach is useful for dynamic state in a mutable world: e.g. what happens after "Logout"? The state for DoStuff is invalid again until a re-logon (if it's allowed). However, this approach cannot be used for compile-time checks in general in mainstream OOP languages because the run-time state simply is not available at compile-time.
2. Use multiple types to represent state.
Create two separate types, such that type ServiceLogon (method Logon) creates ServiceAccess (method DoStuff). Thus DoStuff can only be called (on type ServiceAccess) after created from Logon (on ServiceLogon). This works well to enforce calling order semantics in static languages with member hiding - because programs won't compile if it's wrong.
login = new ServiceLogon(credentials)
access = login.Logon();
access.DoStuff(); // can't be called before obtained via Logon
Using the type to encode additional state can be overly complex as it can fracture a class-based type system, but is useful in "builder" and "repository" patterns and such; basically, ask if the type warrants being split to maintain SRP, then considering this approach.
This approach cannot handle things like "logout" entirely without incorporating state checking as type ServiceAccess would (in the clean sense) always represent the same state due to it being encoded in the type.
1. & 2. Use state checking and state/role-specific types.
A hybrid is totally acceptable, of course, and the above two approaches are not mutually exclusive. It may make sense to separate the roles making one type (and thus methods invoked upon it) dependent upon another method while still checking runtime state as appropriate. As per above, #1 is really good for runtime guards (which can be highly dynamic) while #2 can enforce certain rules at compile-time.
What you can do is to create instances of ABC form a static factory method that returns the instance you can use. In pseudo-code:
abc = ABC.login(); //sets all the state
users = abc.query_users();
I am not sure this is the best way but you can make login() private and call it as part of the constructor, which would ensure that login() is called at time of object creation itself and after that only any other functions can be called (unless you have static functions)
class ABC{
public ABC(credentials){
login(credentails);
}
public:
void query_users();
//other methods
private:
void login();
//member data
}
It will already work first when it goes from the top down. If you want to make sure that login is successful then call the other methods from inside the login() method.
like:
public void login(){
//do login code
if(//code for login check){
//run other methods
}
else{
login(); //re-run login workings
}
}
If you really want to follow good patterns you might try making as many of your classes immutable as possible.
This would imply that your constructor sets the total state (does the entire login) and then the order of the method calls is totally irrelevant.
Well, in this post, I get to the conclusion that is better to work with services in per call mode, because it's more efficient. This makes me to have data context with a short life, the life of the method that I call.
In this example, I see how to modify data of a list of elements, only is needed to set the state of the entity to modified.
However, how could I do with one operation, modifies and updates, for example?
One case can be this. I have books and authors, and the client application have a view with two datagrids, one for authors and other for books. The user can add authors and modify their information in the first datagrid and do the same with the books in the second datagrid. Also can assign books to their authors.
I have the POCO classes, so I have a author class with a property that is a list of books. Well, I can add books to this list, and then when I call the service method updateAuthors, I only need to use the class of author as parameter, EF knows what to do with the books. It is not needed to pass the book too.
But what happens when in the list of books there are new books and also books that exists but its information is modified?
In the example of the post that I mention in the beginning it says how to do it when all the entity are modify, but if I want to add new registers, I need to set the state to add. So if there is mixed entities, how can I do it? does it exist any pattern or a some way to do this? I have to set the state of all the books? I can know the state of the books, because I use an autonumeric as ID, so if the ID is 0 is a new register, in other case is a modification.
Thanks.
Daimroc.
EDIT: Perhaps I don't be very clear in my question. What I want to know is how I can save the changes of many entities at once. For example, I have the Authors, Books and Custormers. I Add, modify and delete information of many of them. In my WCF client I have method to save changes of Authors, other method to save changes of books and other method to save changes of Customers.
How my service is per call, I need to make three calls, one for each type of entities, and this are independents. However, if I use directly entity framework, I can do many changes to many type of entities and I only need to call savechanges once, it make all the work. How can I do the same with WCF and POCO entities?
I am reading about self tracking entities, buy I have the same problem, I can use Applychanges(entity) but if I am not wrong, it applies changes only to one entity. do I need to call N times if I did changes to many entities?
Thanks.
Not sure if this will answer your question, but here is my suggestion:
Manage the state on your POCO entities by using flags (IsNew, IsDirty, IsDeleted);
When you pass the POCO entities to the object context, use the ObjectStateManager to change the attached entity state;
Recursively loop through the list of children entities and apply the same approach.
EDIT:
The following code is the AuthorStateManager class:
public partial class AuthorStateManager : IStateManager<Author, Context>
{
private IStateManager<Book, Context> _BookStateManager = new BookStateManager();
public void ChangeState(Author m, Context ctx)
{
if (m == null) return;
ctx.Authors.Attach(m);
if (m.IsDeleted)
{
ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Deleted);
}
else
{
if (m.IsNew)
{
ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Added);
}
else
{
if (m.IsDirty)
{
ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Modified);
}
}
}
SetRelationsState(m, ctx);
}
private void SetRelationsState(Author m, Context ctx)
{
foreach (Book varBook in m.Books)
{
_BookStateManager.ChangeState(varBook, ctx);
}
}
}
where Authors is the ObjectSet, m is a POCO entity of type Author, ctx is the object context, and SetRelationsState is the method that loops through all the children state managers to update their state.
After changing the state, in my repository object I call ctx.SaveChanges(). This is the Update method in AuthorRepository class:
public Author Update(Author m, bool commit)
{
_AuthorStateManager.ChangeState(m, _ctx);
if (commit)
{
_ctx.SaveChanges();
}
return m;
}
_BookStateManager is a private member of BookStateManager type which modifies the Book state in its own ChangeState() method.
I suggest you make the State Manager classes implement an interface called IStateManager, which has the ChangeState() method.
It seems a bit convoluted, but it gets easier if you generate code for these classes.
If you want to perform multiple actions in a single service call, then the action to take need to move from being a method call to an object. For example, you might have a InsertCustomerAction class which has a Customer instance tied to it. All of these actions would have a base class (Action) and your WCF method would take in a collection of Action instances.
In trying to centralize how items are added, or removed from my business entity classes, I have moved to the model where all lists are only exposed as ReadOnlyCollections and I provide Add and Remove methods to manipulate the objects in the list.
Here is an example:
public class Course
{
public string Name{get; set;}
}
public class Student
{
private List<Course>_courses = new List<Course>();
public string Name{get; set;}
public ReadOnlyCollection<Course> Courses {
get{ return _courses.AsReadOnly();}
}
public void Add(Course course)
{
if (course != null && _courses.Count <= 3)
{
_courses.Add(course);
}
}
public bool Remove(Course course)
{
bool removed = false;
if (course != null && _courses.Count <= 3)
{
removed = _courses.Remove(course);
}
return removed;
}
}
Part of my objective in doing the above is to not end up with an Anemic data-model (an anti-pattern) and also avoid having the logic that adds and removes courses all over the place.
Some background: the application I am working with is an Asp.net application, where the lists used to be exposed as a list previously, which resulted in all kinds of ways in which Courses were added to the Student (some places a check was made and others the check was not made).
But my question is: is the above a good idea?
Yes, this is a good approach, in my opinion you're not doing anything than decorating your list, and its better than implementing your own IList (as you save many lines of code, even though you lose the more elegant way to iterate through your Course objects).
You may consider receiving a validation strategy object, as in the future you might have a new requirement, for ex: a new kind of student that can have more than 3 courses, etc
I'd say this is a good idea when adding/removing needs to be controlled in the manner you suggest, such as for business rule validation. Otherwise, as you know from previous code, there's really no way to ensure that the validation is performed.
The balance that you'll probably want to reach, however, is when to do this and when not to. Doing this for every collection of every kind seems like overkill. However, if you don't do this and then later need to add this kind of gate-keeping code then it would be a breaking change for the class, which may or may not be a headache at the time.
I suppose another approach could be to have a custom descendant of IList<T> which has generic gate-keeping code for its Add() and Remove() methods which notifies the system of what's happening. Something like exposing an event which is raised before the internal logic of those methods is called. Then the Student class would supply a delegate or something (sorry for being vague, I'm very coded-out today) when instantiating _courses to apply business logic to the event and cancel the operation (throw an exception, I imagine) if the business validation fails.
That could be overkill as well, depending on the developer's disposition. But at least with something a little more engineered like this you get a single generic implementation for everything with the option to add/remove business validation as needed over time without breaking changes.
I've done that in the past and regretted it: a better option is to use different classes to read domain objects than the ones you use to modify them.
For example, use a behavior-rich Student domain class that jealously guards its ownership of courses - it shouldn't expose them at all if student is responsible for them - and a StudentDataTransferObject (or ViewModel) that provides a simple list of strings of courses (or a dictionary when you need IDs) for populating interfaces.