update planning variable's property during planning - optaplanner

I am using optaplanner to solve a scheduling problem. For proprietary reasons I am using analogy to ask the question instead of posting the actual problem
I need to do assign books to different people based on some constraints. Here is how i have modeled the problem:
Role - ProblemFact [Executive, Supervisor etc]
Person - ProblemFact [List of different people and each have a role assigned]
Book - ProblemFact and Planning Variable. It has bookCode and bookStatus properties.
BookAssignment - Planing Entity. It has book and person object.
Each book has some logical status(new, used). Each book's status is initialized to new/used based on some history. The book assignment depends on the status of the book that I am handling in drools file. One of the requirement is that a new book should be assigned to certain role, after assignment the book status should be changed from new to used during planning.
For example the rule is: role = executive gets new book, all other roles gets used book
lets say I have 3 books: books1 = new, book2 = new, book3= used
During planning when planner assigns 'book1' to a person with role= 'executive', after this assignment the book1 status should be changed to "used". For the next assignment to another person with the executive role, book1 can not be used because its status is used.
I need to update the property(bookStatus) of planning variable (Book) during planning. How do i achieve this functionality using optaplanner?
I read about shadow variables but it does not fit the model that i have.
Your help is very much appreciated!

FWIW just closing the loop here. I hope it helps someone else who is also new to optaplanner and drools :)
I solved this issue in a different way details here
My use case requires to use 'book1' with new status only once so I implemented a hard constraint in drools file that uses accumulate function.
rule "Every new book is used once"
when
$total: Number(this > 1)
from accumulate (
BookAssignment(book != null , book.status == BookStatusEnum.NEW),
sum(1))
then
scoreHolder.addHardConstraintMatch(kcontext, -10);
end

Related

Is there a simple generic implementation of rule based access control?

I'm implementing the access control of an intranet site. Which would be easy, if the company didn't have 200+ employees and custom permissions for almost every one. It's madness, I know, but I can't change it.
So, I tried to find a generic implementation which would meet my needs, but couldn't find it, so I went to do it myself. In the end, I came up with a fairly generic solution which got me thinking: someone must have done it before!
I called it STOP (Subject Task Object Permission) Access Control. I have the following relation:
.-------. .-----------. .-------.
| users |1---*| STOPRules |*---1| tasks |
`-------' '-----------' '-------'
A STOP Rule has the following attributes
STOPRule {
Subject;
Task;
ObjectType;
Permission;
Relation;
}
The object relation can be: owner, creator, revisor, etc. This field isn't required, to support generic tasks. When it's there, the relation between the current user and the object instance is calculated by a delegate. The current relation is then compared with the required relation on the rule to allow or deny the access.
Let me know if I wasn't clear enough.
Two questions arise:
Is there an open source implementation like this one?
Do you see any problems I would encounter following this path?
EDIT: I went ahead and actually started to implement this model. The first problem was I needed the relation between the subject and the object to support any use case. Now, I can store the following rule:
John (subject) can (permission) edit (task) an order (object) IF he is the creator (relation) of the order.
Please, can you guys provide a REALISTIC use case that couldn't be expressed using this model?
What about actually having one table with grouped permissions by certain roles and use another table for extended permissions that would override general ones. If it is the case of let only John access something, why also mention that each other person cannot? Like for the last example you provided in the comment above: do there is a table with permissions. A record looks like: 1645 edit_some_field. Then group_permissions looks like: 1645 everyone false and the final exception table would be 1645 (Jane Doe's ID) true.
If, let's say there are 50 people who have access to edit this field, then you just add another group in the group table like: 89 editors_of_field_X, put the people's IDs into a table group_members like 89 (John Smith's ID) true. And then on the final step you can override those with single person's permissions as I mentioned above. So in conclusion you would have 3-layer scheme. Everyone-group-person. And the deeper you go the higher importance that role has. For example if everyone is not allowed, but the group you are in is allowed, then you can edit something.
Moreover if you aren't permitted with an access on the third - person - level, then again, you became an exception in the group. This way you will be able to reuse groups for later, only adding minor changes.
John created an order and wants to let Bob view it.

How do I update an Entity Reference using a SelectList in edit form?

This is a follow-up to the discussion in this post. I am not sure how to ask the follow-up question in a 2-month-old thread; so I apologize if there is a better way.
Anyway, to reiterate I have an ASP.NET MVC Edit form, and one of the fields is a select list. I get the values fine, but I am having trouble to update the primary entity after Post. Obviously, I have the key to the lookup entity, but it seems crazy to have to load all lookups. So, the suggested solution is entity reference
For clarity, let's say I have a customer as main entity, and title (Mr / Mrs / Dr, etc.) as the lookup.
So, the link above suggests the following:
customer.TitleReference.EntityKey = new EntityKey("MyEntities.Titles", "Id",
Int32.Parse(formData["personTitle"]);
So far, so good. I assign the entity key (and I see in the debugger that is indeed what I expect). But I can't figure out how to get the new value saved along with other customer fields. I am doing the following:
var originalCustomer = (from c in MyEntities.Customers
where c.Id = customer.Id select c).first();
MyEntities.ApplyPropertyChanges(originalCustomer.EntityKey.EntitySetName,
customer);
This updates all customer fields, except for lookups. Intuitively, it is (somewhat) understandable, since if I specify originalCustomer.EntityKey.EntitySetName, ApplyPropertyChanges ignores originalCustomer.TitleReference.EntityKey.EntitySetName.
But if I do specify originalCustomer.TitleReference.EntityKey.EntitySetName, runtime complains that the entity is null (which is also understandable, since I didn't assign anything to the entity; only to entity reference.
As is probably obvious, I am going circles around what seems to be quite straightforward situation. However, I can't find any tutorials that cover it (which is strange in itself).
Furthermore, I have a more complex problem... the customer may have multiple addresses and the address has state... hopefully, once I figure out the titles - I can extrapolate.
By the way, the example (customer - title - address) is fictitious; but it models the problem quite well.
This should work:
var originalCustomer = (from c in MyEntities.Customers
where c.Id = customer.Id select c).First();
originalCustomer.TitleReference.EntityKey = new EntityKey("MyEntities.Titles", "Id",
Int32.Parse(formData["personTitle"]);
context.SaveChanges()

Behavior of aggregate roots in DDD should be as actor or not?

My english bad, so i will give two examples. Let's drop some even important things from DDD in this examples, the main thing is the essence of the matter.
How to do it right from the point of view of DDD?
We have two aggregate roots, the Seller and the Advert. The Seller can edit the Advert in these examples:
1.
If the models should reflect the real business logiс. Then it is the Seller who must change Adverts. I.e client layer invoke methods changeAdvertName() and changeAdvertCost() of aggregate Seller. By the way this gives such an advantage as access check. As we can see Seller can modify only own Adverts. This is the first option as possible.
//Client layer call seller.changeAdvertName(name)
//AR Seller
class Seller{
adverts
changeAdvertName(advertId, name){
adverts[advertId].changeName(name)
}
changeAdvertCost(advertId, cost){
adverts[advertId].changeCost(cost)
}
}
//AR Advert
class Advert{
name
cost
changeName(name){
this.name = name
}
changeCost(cost){
this.cost = cost
}
}
2.
Another variant, client layer can invoke directly methods changeName and changeCost from aggregate Advert. I saw this implementation many times.
//Client layer call advert.changeName(name)
//AR Advert
class Advert{
name
cost
changeName(name){
this.name = name
}
changeCost(cost){
this.cost = cost
}
}
What do you think about these options? Are they both valid for DDD
implementation? Which one is more correct and logical from the point of view of DDD?
Thank you!
Are they both valid for DDD implementation?
An important idea in domain driven design is the notion of a consistency boundary - an aggregate is a boundary around state that can be modified in isolation - without looking at any state outside of the aggregate.
The main benefit is that the client code doesn't need to worry about managing the consistency rules; that responsibility lives in the aggregate.
An additional benefit is that modifications to one aggregate don't need to block on modifications to another.
Nesting aggregate roots, by having one aggregate hold a reference to another, makes something of a mess of that idea; a thread that is trying to modify the Advert may interfere with a different thread that is trying to modify the Seller of the Advert.
There's fundamentally nothing wrong with having multiple entities within a single aggregate. For example, you could reasonably combine the Seller entity and the Advert entity into a single Seller aggregate, and enforce your consistency guarantees by making all changes to an Advert go through the Seller. It's important, however, to recognize that in this design the Advert is not, itself, an aggregate root.
There's also nothing wrong with having the Advert be its own aggregate root, handling its own consistency rules, while the Seller lives in a different aggregate.
In this simple example, where the seller is just deferring changes to the advert, it makes sense to keep them separate from one another, so that different Adverts of the same seller can be modified concurrently.
If there was some critical domain invariant that spanned multiple adverts, then you might need to pull them all into a single collection, which might live within the seller aggregate.
My idea was that, in the real business process specifically the Seller create Advert and change Advert. But not an abstract client layer create and change Advert. So, could you please help to understand?
It turns out that, in the real business world Seller can create(),drop(),modify()... -> Advert. But in DDD aggregate Seller can only implement create(Advert) behavior?
This really isn't specific to DDD; it's more a reflection of "object oriented" programming (as understood by Java, etc). Behavior - which is to say, changes of state - occur by sending a message to the entity that manages that state.
The object oriented idiom is not actually a good match with English grammar. We normally write "Seller modifies advert" -- a subject-verb-object form. But in the grammar of object oriented programming, objects change their own state in response to imperative tense messages (commands).
List.addItem(...) - we aren't modifying the list, we are sending the list a command that says: "modify your own state".
Similarly, the seller isn't modifying the state of the advert; she is sending a message describing the way the advert should change, and it's up to the advert to do that.
And that's deliberate: it means that the Seller can collaborate with the Advert without needed to know anything about the Advert's implementation, which means that we can replace that implementation any time we want without breaking Seller.
Aggregate roots are consistency boundary to ensure the domain model is kept in a reliable state.
From many DDD Practitioners we know that.
Transactions should, not cross aggregate boundaries. To Update another aggregate use domain events in a separate transaction. more
from this perspective Second option would be more valid, since you have 2 aggregate root.

Optaplanner to have assignment Criteria

If we take an example of task assignment to employee where we assign a list of tasks to list of employees based on employee's availability and skills(hard constraints) required to perform an individual task.
Now, if there is a task and no employee has skill to do that, Optaplanner will still assign that task to an employee and will break a Hard constraint. This result tells me that there is there is a hard constraint broken but still that task is assigned and that effects the chain of task an employee is supposed to do ie rather than assigning an irrelevant(out of skills) task, shouldn't system(Optaplanner) provide an assigment criteria that wont allow assigning of a task to an employee which is out of his/her skills.
Is there a way to achieve such criteria?
P.S. I'm just beginning to understand Optoplanner, please feel free to correct question if needed.
This is called overconstrained planning. Look for it in the docs.
There are basically 3 options for you to choose from:
Break hard constraints (default behaviour)
Assign to null (nullable=true and extra medium constraint)
Assign to virtuals (extra medium constraint and maybe even adjustments to soft constraints)
See docs.

How would model a vote/like system in a DDD/CQRS/EventSourced project?

Here a brief explanation of my domain:
I've Article which are basically like any article (title, summary, and a body).
I need to allow votes on my articles, votes will be casted by anonymous users (no registration required, but a session will store votes, please don't focus on this).
In this domain, Article is my aggregate root.
I can't find a way to model my votes with the following requirements:
a Vote can be either I like or I don't like, it should be mutable (it can be changed over time or even canceled)
A guest user with associated session can only cast one vote per article.
So, should Vote be aggregate on its own?
something like
Class Vote {
public function cast(ArticleId id, GuestSessionToken token, VoteValue value);
}
But in this case how should I check for unicity? Using Eventual Consistency (it seems ok because I don't having some duplicate as far as they are rare).
Because if I add vote method to my Article aggregate, I'll have to replay history for each votes which will be casted which sounds fairly slow (given the fact I can have 100k votes per articles).
I know that performance and optimization should not be taken in account when designing the DDD way but here it is a specific problem I need to solve before to implement anything.
Any of you has done something similar before?
Vote is an aggregate root on its own. If we think about associations "an article has many votes" then we are applying a relational approach and this make us incline towards the so criticized big aggregate approach consensual by the DDD community. Instead we want to focus on behaviour. We know already that an Article will not hold a collection of votes. Since a Vote will need its own lifecycle it will have its own global identity and so its own repository. An article is voted by users, it is a nice approach to give semantics to our domain model so playing with domain experts semantics we could say "an article is voted by the user"
anArticle.votedBy(aReader);
Remember that the user plays the role of a reader in this bounded context. The votedBy method is a factory method that is in a position of creating a Vote. Its implementation would be:
Article.votedBy(aReader) {
return new Vote(this, aReader);
}
Always remembering that at the end a Vote will have the conceptual identifiers of an article and a reader, promoting the disconnected model instead of holding actual references to other aggregate roots. So the domain service would be the reader itself. Suppose that you model a rest interface
RestInterface.voteArticle(articleId) {
reader = new Reader(articleRepository);
reader.vote(articleId);
}
Reader.vote(anArticleId) {
article = articleRepository.get(anArticleId);
vote = article.votedBy(this);
voteRepository.add(vote);
}
You should check for unique (making sure a user votes an article only once) by placing a composed unique constraint at the database level. This is the least intrusive way to check it, otherwise you should add another domain model that moderates votes. Maybe this new object makes more sense when different voting business rules are created, but for making sure a reader votes only once an article is enough and I think the most simplistic solution (that is to place the DB constraint).
DDD is a learning process and as we learn new things about the domain we realize the user can hit Like or Dislike button on an article so we think about re-factoring what we did so far a little bit:
Article.likedBy(aReader) {
return Vote.positiveByOn(aReader, this);
}
Article.dislikedBy(aReader) {
return Vote.negativeByOn(aReader, this);
}
where both implementations are:
class Vote {
readerId
articleId
typeId
Vote(aReaderId, anArticleId, aType) {
readerId = aReaderId
articleId = anArticleId
type = aType
}
public Enum VoteType { POSITIVE, NEGATIVE }
Vote static positiveByOn(aReader, anArticle) {
return new Vote(aReader.id, anArticle.id, POSITIVE);
}
Vote static negativeByOn(aReader, anArticle) {
return new Vote(aReader.id, anArticle.id, NEGATIVE);
}
}
Also, since the likedBy/dislikedBy factory method on the Article AR is creating Votes you could place a constraint saying an article cannot be voted more than N time or any other business scenario.
Hope it helps,
Sebastian.
I would separate the Vote object from a VoteCast object.
VoteCast is the event, it could have a value of Up, Down, or Cancel. There is also a Vote object which gets updated from VoteCasts.
When calculating votes, you don't need to replay the casts, just count the votes. You could put the Votes into collections on the Article (Up, Down), and just return the collection count. A VoteCast would modify which collection the Votes are part of.

Resources