Larman's System Operation Contracts - CRUD example - oop

I have some confusion with applying Larman's system operation contracts (OO Analysis from book Applying UML and Patterns) on CRUD-like operations. More precisely, I'm confused with postcondition part.
For example, if I have CRUD system operations looking as follows:
createEmployee(employee:Employee),
readEmployee(employeeId:int),
updateEmployee(employee:Employee),
deleteEmployee(employeeId:int)
what would be postcondition on, for example, readEmployee system operation, or some other operation like searchEmployees etc?
For example: for read operation, system needs to read record from database, instantiate domain object, set attribute values on domain object (set relations also) and that's it. Does it means that postconditions are above mentioned - instance creation, changes on attributes, etc. Or, read operation does not have any postcondition. None of this does sound logical to me.
My confusion is about relation between domain model (state) and database (state). I just don't get implications which above operations will have on domain model. I always think in way that the database is a place that preserves the state of the system. After I create employee, its object's state will be persisted in database... But what happens with domain model state?

The post-condition defines what the state of your application (or object, depending on the level of abstraction) should be after the operation for it to be considered as successful. For the readEmployee operation, for example, the post-condition would be that:
a new Employee instance is created.
the Employee instance contains attributes matching the database values.
the database connection is closed.
I like to think of "pre-condition" and "post-condition" as the "state of mind" of your application before and after an operation has executed, respectively. As you can imagine, it's more a thought process than a coding exercise when you do DbC.
(If you do unit-testing, states make it clear what needs to be covered by your tests. Basically, you end up testing the "state of mind" of your application.)
Interestingly, if you consider the reverse of DbC, you realise that to identify what operations your application (or object) should expose, it is simply a matter of listing what states it can have and how it transitions between these states. The actions that you need to take to make these transitions then become your operations, and you do not have to bother with implementing operations that do not lead to any desired states. So, for example, you probably want the following states for your application.
Employee details added (S1)
Employee details loaded (S2)
Employee details updated (S3)
Employee details deleted (S4)
The following state transitions are possible.
S1 -> S3 (add new employee, update the details)
S1 -> S4 (add new employee, delete the employee)
S2 -> S3 (load employee details, update employee details)
S2 -> S4 (load employee details, delete employee)
S4 -> S1 (delete employee, add new employee)
S2 -> S1 (load employee details, add new employee)
S3 -> S1 (update employee details, add new employee)
S3 -> S2 (update employee details, load employee details)
Based on the above, you can write your operations in such a way that only valid transitions are allowed, with anything else giving rise to errors.
Impossible state transitions:
S4 -> S2 (cannot delete an employee, then load their details)
S4 -> S3 (cannot delete an employee, then update their details)
State modeling is probably the most important part of designing objects, so you're asking the right questions. If you want a good resource on state modeling, get Object Lifecycles Modeling the World in States from Sally Shlaer / Stephen Mellor. It is quite an old book and costs almost nothing on Amazon, but the principles it introduces form the basis of modern UML -- incidentally, the notation used in the book looks nothing like UML.
I realise I did not touch on database state, but at the conceptual level, the database layer is just another system of states and the same principles apply.
I hope this was useful.

My interpretation of Larman's contracts is always with respect to the domain model. Larman clearly states there are only 5 types of post conditions:
Instance creation
Instance deletion
Attribute change of value.
Associations formed.
Associations broken.
Therefore, a Read (or search) operation would have no post conditions, at least not on the elements that are being read or searched. For example, if 10,000 users performed reads/searches in one day, but never did any of the other operations (C, U, D), there would be no change to the objects in the domain.
There is an exception to this, however, in domains where searches/reads are remembered. For example, Google surely keeps track of searches. In this case, doing a search has the postcondition of creating a new object in their domain model, e.g., A Search instance s was created (instance creation).

The confusing comes form mentioning data model relation within the contract template that Larman provided as in :
Contract CO2: enterItem
Operation: enterItem(itemID : ItemID, quantity : integer)
...
sli was associated with a ProductSpecification, based on itemID match (association formed).
The detail referential properties of the database should not be mentioned in the operation contract. It is better to leave it as: "sli was associated with a ProductSpecification".
In fact, it is one of the things that Larman's operation contracts does not talk about in much detail. Think about a contract for an operation that calculates a total number of items and return the total ! seems that it cannot be written as an operation contract.

Related

How to express pagination in attribute based access control?

Based on my coarse reading, ABAC, i.e. attribute based access control, boils down to attach attributes to subjects, resources and other related entities (such as actions to be performed on the resources), and then evaluate a set of boolean valued functions to grant or deny the access.
To be concrete, let's consider XACML.
This is fine when the resource to be accessed is known before it hits the decision engine (PDP, in the case of XACML), e.g. view the mobile number of some account, in which case the attributes of the resource to be accessed probability can be easily retrieved with a single select SQL.
However consider the function of listing one's bank account transaction history, 10 entries per page, let's assume that only the account owner can view this history, and the transaction is stored in the database in a table transaction like:
transaction_id, from_account_id, to_account_id, amount, time_of_transaction
This function, without access control, is usually written with a SQL like this:
select to_account_id, amount, time_of_transaction
from transaction
where from_account_id = $current_user_account_id
The question: How can one express this in XACML? Obviously, the following approach is not practical (due to performance reasons):
Attach each transaction in the transaction table with the from_account_id attribute
Attach the request (of listing transaction history) with the account_id attribute
The decision rule, R, is if from_account_id == account_id then grant else deny
The decision engine fetch loops the transaction table, evaluate each row according to R, if granted, then emit the row, util 10 rows are emitted.
I assume that there will be some preprocess step to fetch the transactions first, (without consulting the decision engine), and then consult the decision engine with the fetched transaction, to see if it has access?
What you are referring to is known as 'open-ended' or data-centric authorization i.e.access control on an unknown number (or a large number) of items such as a bank account's transaction history. Typically ABAC (and XACML or alfa) have a decision model that is transactional (i.e. Can Alice view record #123?)
It's worth noting the policy in XACML/ALFA doesn't change in either scenario. You'd still write something along the lines of:
A user can view a transaction history item if the owner is XXX and the date is less than YYY...
What you need to consider is how to ask the question (that goes from the PEP to the PDP). There are 2 ways to do this:
Use the Multiple Decision Profile to bundle your request e.g. Can Alice view items #1, #2, #3...
Use an open-ended request. This is known as partial evaluation or reverse querying. Axiomatics has a product (ARQ) that addresses this use case.
I actually wrote about a similar use case in this SO post.
HTH,
David

How to implement design in OOP

I have following structure
One organization can have many environments.
One environment can have many Applications.
One application can have many Policis.
I created class of each entities i.e.
class Organization,
class Environment,
class Application,
class Policy
Now I want to apply policies to Application.
One policy should have one Policy class object. All instances of Policy are different. Every policy have unique name and ID.
Inheritance will not work, Consider following hierarchy -
Organization
Environment(Organization)
API(Environment)
Policy(API)
because every policy, required to procide all details of API, Environment, Organization.
Can we do aggregation here? Need help on this
All instances of Policy are different.
Every policy have unique name and ID
You can indicate that with the constraint :
Policy.allInstances() -> forAll(p1, p2 |
p1 <> p2 implies (p1.name <> p2.name and p1.ID <> p2.ID))
A class diagram from the information you give can be :
I do not use bidirectional relations supposing Policy does not know the associated Application(s) whose does not know associated Environment(s) whose does not know associated Organization(s).
I use multiplicities * equivalent to 0..* because nothing in your question says the minimum multiplicity is 1 each time. I do not indicate the multiplicity in the opposite direction of the relations because your question does not indicate something about them.
Inheritance will not work
A inherits B implies A is a B, among the classes your give none of them satisfy that, so there is no possible inheritance between them.
Can we do aggregation here
may be between Environment and Application because we can say an environment is composed by applications, but else where no.

Optaplanner - continuous planning with changing constraints, that do not set prior assignments invalid

we are using Optaplanner 7.0 beta + Graphhopper for a calculation of shortest paths in a warehouse, where goods have to be collected into boxes by workers (vrptw). Since the business is about collecting online-ordered goods approx. 70% of the items to collect are added to the problem during the day. We use ProblemFactChange to add the incoming order items and already completed order items in the chain are set to immovable (these 'restarts' are performed each full hour). So far everything works.
The question now is about changing restrictions/conditions, that can occur due to unbalanced workload over warehouse-zones. The warehouse is logically divided into areas, to avoid that all workers have to serve all areas (I know your opinion about segmentation of planning problems, but this is, how the work currently is organised). The limited assignment of items to available workers within one zone is currently defined by a hard-constraint.
The new requirement that we are confronted with is, that a worker should be temporary assigned to a different zone, if the workload there is higher compared to his actual zone. Afterwards he can switch back to his original zone. To my understanding an update of the constraint condition would result in hard constraint violations for the previous assigned, locked items, which should be avoided. Are there mechanisms to support temporary changing restrictions or would a SelectionFilter for items help ? (btw: we are using drools).
Hints are welcome, Thank you
Michael
If there are 2 different tenants, each with their own set of employees, tasks, etc and each in their own Solver, then the Borrow Pattern can be used, especially if the employee borrowing involves some human interaction (usually paperwork or a phone call between managers):
Suppose tenant A has an employee called John and tenant B wants to borrow him. Then assign one or more entities from B to John and make them immovable (usually a boolean borrowLocked). Then add the same entities to tenant A. Neither the solver of A nor B will be able to move them (so they won't change), but both of them will take them into account: tenant A won't give John work when he's working for tenant B and tenant B will agree that those entities are assigned (and it won't try to assign John to other entities as it's no in it's value range).

Correct Delete Rule for Core Data Many-to-Many Relationship?

In my Core Data model I have a Profile entity with a couple of Many-to-Many relationships. One of them is 'Looking For'. Many profiles can be looking for many different things.
The relationships in Core Data have their Delete Rule set to Nullify. What I want to happen is, when a Profile is deleted, all the Looking For entries remain unaffected, and when a Looking For entry is deleted, it should be removed from everyone's Profiles.
This seems like I should be doing No Action for both directions of the relationship between Profile and Looking For, but from googling around and reading docs, I'm not sure this is correct, and in fact No Action seems to be something you would almost never want to use unless you were heavily optimizing. Here's the documentation:
No Action
Do nothing to the object at the destination of the
relationship. For example, if you delete a department, leave all the
employees as they are, even if they still believe they belong to that
department.
It is less obvious why the No Action rule might be of use, since if
you use it you have the possibility of leaving the object graph in an
inconsistent state (employees having a relationship to a deleted
department).
If you use the No Action rule, it is up to you to ensure that the consistency of the object graph
is maintained. You are responsible for setting any inverse relationship to a meaningful value.
This may be of benefit in a situation where you have a to-many relationship and there may be a
large number of objects at the destination.
So I feel like I should be using Nullify instead (which I am currently using), but the documentation for Nullify says:
Nullify
Set the inverse relationship for objects at the destination to
null. For example, if you delete a department, set the department for
all the current members to null. This only makes sense if the
department relationship for an employee is optional, or if you ensure
that you set a new department for each of the employees before the
next save operation.
Now, as written, this seems to imply that if you delete a Profile, every Looking For that was associated with that Profile will have its relationship with Profile emptied, i.e. be removed from all Profiles.
What is the correct thing to do in this case?
"Nullify" is correct. Assume that the Profile p1 is related to the Looking Fors l1, l2, l3. If p1 is deleted and the relationship is set to Nullify, then only
p1 will be removed from the inverse relationships in l1, l2, l3.
With "No Action", the inverse relationships in l1, l2, l3 would remain unchanged,
and therefore point to a non-existing element p1. You would have to remove p1
"manually" from those objects.
In other words, "Nullify" is the simplest rule that keeps the object graph consistent: If a is related to b, and b is deleted, then b is not related to a anymore.

Is it acceptable to have multiple aggregation that can theoretically be inconsistent?

I have a question about the modelling of classes and the underlying database design.
Simply put, the situation is as follows: at the moment we have Positions and Accounts objects and tables and the relationship between them is that a Position 'has an' Account (an Account can have multiple Positions). This is simple aggregation and is handled in the DB by the Position table holding an Account ID as a foreign key.
We now need to extend this 'downwards' with Trades and Portfolios. One or more Trades make up a Position (but a Trade is not a Position in itself) and one or more Portfolios make up an Account (but a Portfolio is not an Account in itself). Trades are associated with Portfolios just like Positions are associated with Accounts ('has a'). Note that it is still possible to have a Position without Trades and an Account without Portfolios (i.e. it is not mandatory to have all the existing objects broken down in subcomponents).
My first idea was to go simply for the following (the first two classes already exist):
class Account;
class Position {
Account account;
}
class Portfolio {
Account account;
}
class Trade {
Position position;
Portfolio portfolio;
}
I think the (potential) problem is clear: starting from Trade, you might end up in different Accounts depending if you take the Position route or the Portfolio route. Of course this is never supposed to happen and the code that creates and stores the objects should never be able create such an inconsistency. I wonder though whether the fact that it is theoretically possible to have an inconsistent database implies a flawed design?
Looking forward to your feedback.
The design is not flawed just because there are two ways to get from class A to class D, one way over B and one over C. Such "squares" will appear often in OOP class models, sometimes not so obvious, especially if more classes lie in the paths. But as Dan mentioned, always the business semantics determine if such a square must commute or not (in the mathematic sense).
Personally I draw a = sign inside such a square in the UML diagram to indicate that it must commute. Also I note the precise formula in an UML comment, in my example it would be
For every object a of class A: a.B.D = a.C.D
If such a predicate holds, then you have basically two options:
Trust all programmers to not break the rule in any code, since it is very well documented
Implement some error handling (like Dan and algirdas mentioned) or, if you don't want to have such code in your model, create a Checker controller, which checks all conditions in a given model instance.