Vehicle Routing With Staff - drools

I am working on a solution where we need to route our vehicle to locations of Tasks asked by our Customers. Here is how my domain looks like:
interface TaskOrVehicle{
#InverseShadowVarible Task nextTask;
getLocation();
}
Task:
#PlanningEntity
Class Task implements TaskOrVehicle{
#ChainedPlanningVariable TaskOrVehicle taskOrVehicle;
#PlanningVariable Staff staff;
#AnchorShadowVariable Vehicle vehicle;
}
So, I've got Staff and Vehicle as facts while Task is a planning entity. So with optaplanner, it schedules task in a chain but it assigns different employee to different tasks in same chain.
So, if A, B, C ,D and E are tasks and Staff st1,st2,st3 and Vechcle V1,V2 are there.
Ideal solution looks like:
V1->A(st1)->B(st1)->C(st1)
V2->D(st2)->E(st2)
But my solution looks like:
V1->A(st1)->B(st3)->C(st2)
V2->D(st3)->E(st2)
This is because I don't have employees chained and using employee as a planning variable. Now, I can fix it using rules that nextTask should have same employee as current task but that's a overkill.
What are the best practices I can do here so that every task chain has same employee?
Note:I don't want to keep employee in Vehicle as if Vehicle gets free it can be assigned to different employee for new task chain.

Related

Single table design for no-SQL - Use case with no design pattern

I'm building a model in DynamoDB following the principles of single table design by Rick Houlihan.
The process shows how to model a 1:M and M:M relationship by using composite keys in primary key and sort keys.
For exemple:
Let's say we have a model for training classes.
We have STUDENTS and CLASSES which are basic entities. And we have a REGISTRATION entity which connect a student to a class. So far no issue and the table to hold this data is below.
If I want to get all the classes that student2 is registered I will query by PK=Student#002 and SK begins with 'Class#'.
PartitionKey SortKey EntityType
--------------- ---------- ----------
Student#001 Student#001 STUDENT
Student#002 Student#002 STUDENT
Student#003 Student#003 STUDENT
Class#001 Class#001 CLASS
Class#002 Class#002 CLASS
Class#003 Class#003 CLASS
Student#001 Class#001 REGISTRATION
Student#002 Class#001 REGISTRATION
Student#002 Class#002 REGISTRATION
Student#003 Class#002 REGISTRATION
Now consider that in my model I have an status attribute on classes which could be OPEN,CLOSED,CANCELED. The table will be like below.
Similar to previous query I want to get all the classes that student2 is registered with status OPEN.
Repeating the query with PK=Student#002 and SK begins with 'Class#' is not enough.
PartitionKey SortKey EntityType Status
--------------- ---------- ---------- ----------
Student#001 Student#001 STUDENT
Student#002 Student#002 STUDENT
Student#003 Student#003 STUDENT
Class#001 Class#001 CLASS OPEN
Class#002 Class#002 CLASS CANCELLED
Class#003 Class#003 CLASS OPEN
Student#001 Class#001 REGISTRATION
Student#002 Class#001 REGISTRATION
Student#002 Class#002 REGISTRATION
Student#003 Class#002 REGISTRATION
One solution could be prefixing the status in the sort key like below.
However this does not appear a good solution as the status is a transitory information.
Anytime a class changes the status all the registration records need to be updated to keep consistency. Not to mention the cost of this operation considering that a class can have 10k students registered.
PartitionKey SortKey EntityType Status
--------------- ---------- ---------- ----------
Student#001 Student#001 STUDENT
Student#002 Student#002 STUDENT
Student#003 Student#003 STUDENT
Class#001 Class#001 CLASS OPEN
Class#002 Class#002 CLASS CANCELLED
Class#003 Class#003 CLASS OPEN
Student#001 OPEN#Class#001 REGISTRATION
Student#002 OPEN#Class#001 REGISTRATION
Student#002 CANCELLED#Class#002 REGISTRATION
Student#003 CANCELLED#Class#002 REGISTRATION
Is there any way to solve this scenario properly in noSQL ?
Single table design with DynamoDB is cool but it is limited in some cases.
If I have 10k students, and I need to query all the OPEN registered classes for a student, and classes can be opened and canceled, then I would probably have Elasticsearch synced with the dynamodb table like:
DynamoDB - Dynamodb Stream - Lambda - Elasticsearch
refer https://github.com/vladhoncharenko/aws-dynamodb-to-elasticsearch/blob/master/scripts/dynamodb-to-es.py for the lambda syncing DDB to ES
I would be able to query all the open classes for the student2.
I see at least two options here.
Get the list of classes for a student (this would include all classes regardless of status) and then do a batchGet to get each of the classes, to filter the list down by status in your code. As long as the number of classes a single student is enrolled in isn't large this is a reasonable approach. Even if the number gets large you can add DAX to reduce the number of requests to the table and increase the performance.
Take the approach you mentioned in the last part; update each of the student records. The easiest way to accomplish this would be to use a Stream to capture the change and update the records as needed. This makes the process asynchronous. If your process to change the status of a class is already asynchronous then you can do the work there. You mentioned the cost of this, but I don't think the cost is going to be that high. Even in a case where there are 10K students in a class the update would cost $.0025, or 1/4 of a penny if the records are small enough (this is not accounting for the cost of a lambda running on a stream trigger, just the update cost to the table). You can do quite a few updates at that cost before really seeing a cost issue, and compared to the cost of alternatives it will still be a lot cheaper.
There are other options. As another person suggested, you can add ElasticSearch. You could also push the data to S3 and use Athena. I assume you want to stay in DynamoDB, in which case the above two options are the best I can think of (perhaps someone else has another idea).
I found more problematic scenarios like the one described in this post, so I realized that no-SQL wasn't the right DB choice for this project.
I have changed to Aurora RDS.

The relation between Class name and its method name at UML Class Diagram

In UML Class Diagram , what is the relation between the name of class and the name of its methods? in specifically are there any consistency between their names ?
for example:
I have three classes " Patient" , " Appointment" , and "Receptionist"
where the "Patient" should do this task: " request appointment",
And the "Receptionist" do this task: "make appointment"
Where should I put these tasks as class methods? Should I make it all inside one class "Appointment" ? Or put each method in the Class that has responsibility to do it ?
Base on the previous BPMN model , here is a part of My Class Digram for the same process
This is basic design. Take request appointment for example:
Who is the actor and what will he do?
The actor is Patient and there should be a pool with appointments, so we model that as Appointment
How is the relation between both?
Patient needs to get a new Appointment on request.
Place a method makeAppointment in Patient
Where do the new appointments come from?
There's likely a schedule that keeps all appointments and finds times for new ones.
Create a class Schedule that aggregates Appointments and has a method nextFreeAppointment
etc.

How to set optimal and correct relationships between three collections

I have a problem with correct relationship setup.
I have three objects in my application:
projects
sectors
employees
And I need to design relations for it:
a) each sector has it's own employees
b) each sector could be responsible for any project
b) not every employee is responsible in every project, in which participate the employee's sector and there is requirement to filter employees "by project"
So at this moment i get something like this:
sector has field project (ref: project._id)
employee has field sector (ref: sector._id)
employee has field project (ref: project._id)
Is that approach correct?
I think the correct approach is:
sector should have employee id and project id
employee should have project id

DDD Repo - repo.findByChildId(id) AND repo.transferChild(to, from, child)

I've recently started looking into DDD and have been refactoring an old personal project to this pattern. I'm about halfway through Evans blue book, and can't seem to find the answer for this there or online anywhere.
Basically my application is an inventory tracker. Inventory would contain a collection of items, items are transferrable entities between inventories. Inventory would have methods like transferIn() transferOut() which would contain some validation logic, ie checking that the inventory is not already full or that the item is in a transferrable state. These constraints lead me to believe that inventory is the aggregate root and that item is an entity.
1) at some point if a user requests a specific item entity for their inventory I would like to have a inventoryRepo.findByItemId(id) which would return the inventory that currently has that item. So that I can:
2) through a service do something like:
boolean requestItemTransfer(destInvId, itemId){
Inv from = invRepo.findByItemId(itemId);
Inv to = invRepo.findById(destInvId);
from.transferOut(itemId);
to.transferIn(from.getItem(itemId));
return invRepo.transferChild(to, item); //Edited
}
Basically writing my validation logic in the inventory class (rich domain model) and if there are no exceptions then I use the repo.transfer() method to persist the changes.
Would I be violating DDD? Are there better alternatives?
From what I've read and understood this seems valid if only unconventional. Every example that I've found shows entities that can only exist within 1 root instance. There's also the bank account transfer examples but those deal with amounts that are value objects, and have a transfer repository because transfers are to be recorded in that particular scenario, just not in mine.
EDIT:
The use cases are as follow:
1) User requests a list of their inventories and their items.
2) User selects 1 or more items from 1 inventory and requests for them to be sent to another inventory. This is where my TransferService would come in and coordinate the txIn and txOut from the specified inventories, and persist those changes through the repo. Maybe that should be an infrastructure services? That's one thing I'm not clear on.
3) User predefines a set of items he would like to be able to transfer to an inventory regardles of what inventory those items are currently in. TransferService would find where those items currently are and coordinate the rest as use case 2 does.
EDIT2: About the repo.transfer
This is actually a constraint/optimization? from the data side, from what I've been told all it does is lookup the item and change the inventory id that it points to. This is because items cannot be in 2 inventories at once. So instead of repo.update(fromInvInNewState) and repo.update(toInvInNewState) there is repo.moveChild(toInv, child) because we don't want to rewrite the entire state of the inventory (all its items that haven't moved, and because the rest of its state is derived from the items that it has at any point), just move some items around.
You are missing at least one aggregate and trying to replace it with your persistence. Talk to your domain expert, find out who or what is doing this transfer. I bet you will not hear that this is done by "a repository" or "a database". This something will be your aggregate and it will probably have this Transfer method. This call would also encapsulate the login from transferIn and transferOut since this seems to be a transactional process and you are doing it in three different places. Remember that your transaction boundaries is your aggregate. Not your repository.
First of all I would like to recap the domain model defined by your scenario.
You said that you are building an Inventory Tracker with the next spec:
An User has Inventories.
An Iventory consists of Items.
An User can transfer Items from one Inventory to another. I guess that both inventories belong to the User as you said that:
"User requests a list of their inventories and their items. User selects 1 or more items from 1 inventory and requests for them to be sent to another inventory..."
On the other hand, an invariant you pointed out are:
An Item can be transferred from the Inventory where it already is (InventoryA) to another Inventory (InventoryB) only if InventoryB is not already full. I guess that in case that the Item cannot be transferred it should be kept in the InventoryA.
If I understood well, an User transfers his Items between his Repositories.
Something like:
class TransferItemService {
public function execute(TransferItemRequest request)
{
user = userRepository.findOfId(request.userId());
user.transferItem(request.itemId(), request.fromInventoryId(), request.toInventoryId()); //Checks invariant -> the given Item is in one of his Inventories, the destination Inventory is owned by him, the destination Inventory is not full and finally transfers the Item
userRepository.save(user);
}
}
Now, in order to define the Aggregate Root/s I would need to know if my business can deal with eventual consistency. That is, if moving an Item must be done atomically (just one request) or it can take some time (more than one request).
No Eventual Consistency
In case business says that Eventual Consistency is not allowed here, if you want to ensure that your domain remains consistent and aligned to the invariant, the User would be the unique AggregateRoot as he is the nexus between his Inventories. In this case, you can face performance problems due to loading all the Inventories along with their Items.
Eventual Consistency
In case that you can go with eventual consitency, you can have the next Aggregate Roots: User, Inventory, Item. So, using the previous code to model the use case of transferring an item:
class TransferItemService {
public function execute(TransferItemRequest request)
{
user = userRepository.findOfId(request.userId());
user.transferItem(request.itemId(), request.fromInventoryId(), request.toInventoryId()); //Checks invariant -> the given Item is in one of his Inventories, the destination Inventory is owned by him, the destination Inventory is not full and finally transfers the Item
userRepository.save(user);
}
}
In this case, the transferItem method would look like:
class User {
private string id;
private List<UserInventory> inventories;
public function transferItem(itemId, fromInventoryId, toInventoryId)
{
fromUserInventory = this.inventories.get(fromInventoryId);
if(!fromUserInventory) throw new InventoryNotBelongToUser(fromInventoryId, this.id);
toUserInventory = this.inventories.get(toInventoryId);
if(!toUserInventory) throw new InventoryNotBelongToUser(toInventoryId, this.id);
toUserInventory.addItem(itemId);
fromUserInventory.deletetItem(itemId);
}
}
class UserInventory {
private String identifier;
private int capacity;
public function deleteItem(userId, itemId)
{
this.capacity--;
DomainEventPublisher.publish(new ItemWasDeleted(this.identifier, itemId));
}
public function addItem(userId, itemId)
{
if(this.capacity >= MAX_CAPACITY) {
throw new InventoryCapacityAlreadyFull(this.identifier);
}
this.capacity++;
DomainEventPublisher.publish(new ItemWasAdded(this.identifier, itemId));
}
}
Notice that UserInventory is not the Inventory Aggregate Root, it is just a VO with an identifier reference and the current capacity of the actual Inventory.
Now, you can have a Listener that asynchonously updates each Inventory:
class ItemWasRemovedListener()
{
public function handleEvent(event)
{
removeItemFromInventoryService.execute(event.inventoryId(), event.itemId());
}
}
class ItemWasAddedListener()
{
public function handleEvent(event)
{
addItemToInventoryService.execute(event.inventoryId(), event.itemId());
}
}
Unless I have made a mistake I think we have satisfied all our invariant, we have just modified one Aggregate Root per Request and we don't need to load all our Items to perform an operation on an Inventory.
If you see something wrong please let me know :D.

A question about entities, roles and interfaces in Entity Framework 4

I am an experienced .NET developer but new to EF - so please bear with me. I will use an example of a college application to illustrate my problem. I have these user roles:
Lecturer, Student, Administrator.
In my code I envisage working with these entities as distinct classes so e.g. a Lecturer teaches a collection of Students. And work with 'is Student' 'TypeOf' etc.
Each of these entities share lots of common properties/methods e.g. they can all log onto the system and do stuff related to their role.
In EF designer I can create a base entity Person (or User...) and have Lecturer, Student and Administrator all inherit from that.
The difficulty I have is that a Lecturer can be an Administrator - and in fact on occasion a Student can be a Lecturer.
If I were to add other entities such as Employee and Warden then this gets even more of an issue.
I could presumably work with Interfaces so a person could implement ILecturer and IStudent, however I do not see how this fits within EF.
I would like to work within the EF designer if possible and I'm working model-first (coding in C#).
So any help and advice/samples would be very welcome and much appreciated.
Thanks
Don't make Student and Lecturer inherit from Person. As you say, what if "Bob" was both a student and a lecturer? This happens all the time in real colleges. You said it best yourself: These are roles, not types. A person can have many roles.
As a rule of thumb, avoid inheritance in O/R mapping when it's not strictly necessary (which is almost never). Just as when coding, favor composition over inheritance.
So you could give each Person a property Roles which is a 0..* collection of Roles. Then to get a list of students, you can do:
var students = from p in Context.People
where p.Roles.Any(r => r.Id = studentRoleId)
select p;
Or you could have a related Student type with a 0..1 relationship between Person and Student; this would allow you to add additional data for the student, e.g.:
var students = from p in Context.People
where p.StudentInfo != null
select new
{
Id = p.Id,
Name = p.Name,
Grades = p.Student.Grades
};