Ensure by default in puppet provides "present" and "absent". Is there way in which we can have "present", "absent" and "modify" ?
Can you provide me with a link for an example.
Valid values for the ensure attribute are specific to the defined resource. Puppet is designed to ensure a defined state, and I don't see how you could ask Puppet to define a state that changes during every execution. I haven't given this too much thought, but if I understand your question correctly, this is either stateless or an undefined state. In either case, Puppet relies on idempotence, and a scenario that demands a modified state for each run is just not idempotent.
Related
In this question https://softwareengineering.stackexchange.com/questions/396151/which-layer-do-ddd-repositories-belong-to?newreg=f257b90b65e94f9ead5df5096267ef9a, I know that we should avoid talking with the repository.
But now we have one aggregate root and we need to get another aggregate root to check if the aggregate root we have is correct.
For example:
every resource has its scheme. So the resource will hold the name of its scheme.
If the resource wants to update with the new resource data, it wants to get the scheme entity and ask scheme check if the new resource data is matched by scheme validator or not.
To get the scheme entity, we need to ask the scheme repository. But they tell me we should avoid talking with the repository. If we really need to avoid, how can we get the scheme entity by its name?
Two ideas that you should keep in mind:
these are patterns; the patterns aren't expressed exactly the same way everywhere, but are adapted to each context where we use tham.
we choose designs that make our lives easier -- if the pattern is getting in the way, we don't use it.
To get the scheme entity, we need to ask the scheme repository. But they tell me we should avoid talking with the repository. If we really need to avoid, how can we get the scheme entity by its name?
Basic idea: entities can be found via traversal (you start from some aggregate root, then keep asking for things until you get where you want), root entities can be reached via the repository.
In the "blue book", Evans assumed that you could reach one aggregate root from another; people tend not to do that as much (when you can no longer assume that all aggregates will be stored in the same database, you suddenly need to be careful about which aggregates can change at the same time, and this in turn suggests additional constraints on your design).
In the present day, we would notice that if we aren't intending to change the scheme, that we don't need its aggregate root at all - we just need a validator, which we can create from a copy of the information.
So we treat the scheme information as reference data (see Helland, 2005).
Great - so how do we get "reference data" to the resource aggregate?
Typically in one of two ways - the simplest by far is to just pass it as an argument. The application code (usually the same place that we are pulling the resource aggregate out of its repository) is also responsible for looking up the resource data.
resource = resourceRepository.get(id)
validator = validatorRepository.get(resource.scheme)
resource.update(validator, ....)
Alternatively, we can pass the capability to lookup the validator to the resource. Naively, that might look like:
resource = resourceRepository.get(id)
resource.update(validatorRepository::get, ....)
But that violates our "rule" about where we use the repository. So now what? Two possible answers: we decide the rule doesn't apply here, OR we use a similar pattern to get what we need: a "domain service")
resource = resourceRepository.get(id)
resource.update(domainService, ....)
Domain service is a pattern that can be used for all sorts of things; here, we are using it as a convenient mechanism to access the reference data that we need.
Superficially, it looks like a repository - the significant difference here is that this domain services doesn't have affordances to change the scheme entities; it can only read them. The information is the same, but the expression of that information as an object is different (because this object only has read methods).
It's "just" design; the machine really doesn't care how we tell it what work to do. We're merely trying to arrange the code so that it clearly communicates intent to the next programmer who comes along.
I'm modelling a domain where entities are packages of business services and can be made of other packages - tree structure. I have some issues with designing domain logic for avoid cycles.
Let's say we have entity (object of class "Package") PackageA and it has children (PackageB and PackageC). We also have PackageD with child PackageB.
Now we want add PackageA to PackageB as its child - we're doing this by getting PackageB from PackageRepostiory and using PackageB::addChildPackage() method. But before that we need to make sure that adding this package won't do any loops in other trees (in the example it will). The question is how to implement this in DDD?
I thought about moving adding packages to domain service, so I can get all packages that are currently related to the package I want to modify and make a check on them if there will be no cycles.
Do you think it's good idea?
I thought about moving adding packages to domain service, so I can get all packages that are currently related to the package I want to modify and make a check on them if there will be no cycles.
Do you think it's good idea?
Yes, you can do it. Adding a PackageServices class that provide validation for Package it make some sense for your description of Domain.
An aggregate root should not contain a reference to an instance of another aggregate root. You should indirectly reference the other aggregate using either an Id or a value object containing the Id and some extra interesting information.
Your case appears to be along the lines of a classification structure and you could event model that separately from your main aggregate. Either way you would need to get the entire hierarchy that your aggregate belongs to an check that there is no cycle. However, there is no guarantee that you are not creating a cycle along with another user at the same time if what you and the other user are doing would create a cycle.
More-or-less the same goes for some unique attribute such as an e-mail address. In that case it could be as simple as creating a unique constraint on your data store.
In the case of a cyclic dependency it isn't going to be as simple as creating a constraint and the same goes for a data store that does not support unique constraints.
In such a case you would need to use a bit of a process manager and perform a couple of steps. We would probably want to prevent the obvious cycles by checking for a cycle before creating the item in the hierarchy. After you have committed your unit of work (say, transaction) you could send a message to validate the new entry. That second step would then check for a cycle again since someone else may have created an invalid state along with you. If you have a cycle then the last entered item "loses" and is removed an a notification of sorts published in order to make that decision known.
Another way would be to attempt to prevent creating cycles using some locking strategy. This would have to have the correct grain depending on your design. If you have various independent hierarchies they could be locked on a root level. The root would be the Package that has no parent. After your commit you would release the lock. If you have a single hierarchy then you could probably still lock that and permit only a single change to the hierarchy at any one time.
Using a domain service for this seems to be the way to do it but that in itself does not quite solve your issue. It is more about what that service is going to do.
In the application I'm building there are a lot of scenarios where I need to select a group of aggregates on which to perform a specific operation. For instance, I may have to mark a bunch of Reminder aggregates as expired if they meet the expiration policy (there is only one).
I have a ReminderExpirationPolicy domain service that is always applied before delivering reminders. This policy does something like:
reminderRepository.findRemindersToExpire().forEach(function (reminder) {
reminder.expire(clockService.currentDateTime());
});
The expiration policy is currently duplicated as it exists as a SQL predicate within the SqlReminderRepository.findRemindersToExpire method and also within the Reminder.expire aggregate's method.
The answer to the question may be strongly opiniated (although there should definitely be pros and cons - and perhaps a widely adopted practice), but should I simply trust that the Reminder.expire method will only get called as part of the ReminderExpirationPolicy process and trust that the repository implementation will return the correct set of reminders to expire or should I also protect the invariant within the Reminder aggregate itself?
NOTE: I am aware that modifying multiple aggregates in a single transaction is sub-optimal and hinders scalability, but it's the most pragmatic solution in my case.
should I simply trust that the Reminder.expire method will only get called as part of the ReminderExpirationPolicy process and trust that the repository implementation will return the correct set of reminders to expire or should I also protect the invariant within the Reminder aggregate itself?
Short answer: you are backwards. You must protect the invariant within the Reminder aggregate; using the policy as a query specification is optional.
The key thing to realize is that, in your scenario, using the policy as a query specification is really is optional. Eliding persistence concerns, you should be able to do this
repo.getAll () { a -> a.expire(policy) ; }
with the aggregate declining to change state when doing so would violate the business invariant.
In general, the reason that this distinction is important is that any data that you could get by querying the repository is stale -- there could be another thread running coincident with yours that updates the aggregate after your query has run but before your expire command runs, and if that coincident work were to change the aggregate in a way that the policy would no longer be satisfied, then your expire command would come along later and threaten to violate the invariant.
Since the aggregate has to protect itself against this sort of race condition anyway, checking the policy in the query is optional.
It's still a good idea, of course -- in the course of normal operations, you shouldn't be sending commands that you expect to fail.
What's really happening, if you squint a little bit, is that the expire command and the query are using the same policy, but where the command execution path is evaluating whether the writeModel state satisfies the policy, the query is evaluating whether the readModel state satisfies the policy. So it isn't really duplicated logic - we're using different arguments in each case.
However, where my assumptions are different than yours is that from as far as I can see (assuming optimistic locking), even if the data become stale after aggregates are loaded and that I do not enforce the expiration rule within the aggregate, the operation would still fail because of a concurrency conflict.
Yes, if you have assurance that the version of the aggregate that processes the command is the same as the version that was used to test the policy, then the concurrent write will protect you.
An additional consideration is that you are losing one of the benefits of encapsulation. If the policy check happens in the aggregate, then you are guaranteed that every code path which can expire the aggregate must also evaluate the policy. You don't get that guarantee if the aggregate is relying on the caller to check the policy (a variant on the "anemic domain" model).
I want to represent a break in an iterative expansion version in UML 2.4.1.
I tries this:
With exit arrow to the region:
With no exit arrow:
With an end flow:
What is the correct convention ?
There is no convention for it. It depends simply on what you want to say.
The first diagram is incorrect as Add does not lead to any end. You need to connect it to wherever reasonable but not leave it stuck "in the air".
The second even more for twice the reason.
The third is the same as the first. You can use the Flow Final instead of transferring control to the expansion node. You would do that if you have complex flows with many of such interim exits. For the simple case here you will not need it.
Please note that there is also a possibility to use a Initial inside the region. You would use that if you have multiple inputs and want them to start at the same point inside.
P.S.: I overlooked your question while starring at the bugs in the diagram. The break condition can be shown by a guard in the transition which leads to a Flow Final or connects to the output pin.
Alternatively, to interrupt processing all collection elements you get passed you can do this:
This treats the preemptive loop as an exception.
I would also say that a simple note would suffice unless you want to generate code from your model.
A bit down in Superstructures I found this:
When the ExpansionRegion completes all expansion executions, it offers the output collections on its output ExpansionNodes on any ActivityEdges outgoing from those nodes (they are not offered during the execution of the ExpansionRegion). If the ExpansionRegion contains an ActivityFinalNode immediately within it, then, if the ActivityFinalNode accepts a token within any expansion execution, all currently ongoing expansion executions are terminated and the ExpansionRegion as a whole completes its execution. In this case, output collections are still offered from the output ExpansionNodes, though the collections may only be partially filled.
Which confirms my first statement from the P.S.
Looking at the OMG UML spec:
First & Second Diagram:
Please refer to section 14.3.5 Examples which shows as I understand it that a state with no exit state is a terminal state for the submachine/composite state that contains it.
Third Diagram:
You are saying aborted/terminate vs final state. Different things happen can happen. See page 338. I think you mean final state as expected, not in error, so avoid the circle with an X. Does not allow for normal execution to complete.
"terminate – Entering a terminate Pseudostate implies that the
execution of the StateMachine is terminated immediately. The
StateMachine does not exit any States nor does it perform any exit
Behaviors. Any executing doActivity Behaviors are automatically
aborted. Entering a terminate Pseudostate is equivalent to invoking a
DestroyObjectAction."
Summary: It is subjective, but lines matter as behavior can be attached and they can be named. If we take the ATM examples (336-340)pg in the spec, they have been there for many UML versions, then I would say leaving it, if needed connecting it to an edge/exit point, or final state circle with a filled inner circle within the composite state <<iterative>>. Now I am not sure what tool you are using, but that might be worth consideration. Not sure what the broader context is.
I've got an agent that takes in states and returns actions, while keeping an internal representation of the utility of state/action pairs. I've also got an environment that takes in actions and returns state/reward pairs.
I need to be able to set the agent up with a start state and then continuously go from agent -(action)-> environment -(state, reward)-> agent -(action)->...
However, the internal states (which need to be updated every iteration) need to stay private (that is, within the agent or the environment). This means that I can't simply call environment as a function within the agent using state and action as arguments.
I'm somewhat of a Haskell noobie, so I'm not even sure if this is possible.
Two questions:
If the agent must use a state to compute an action, then how do you expect to keep the representation of states secret from the agent?
If the environment expects to produce a state (and a reward) given an action, how do you expect to keep the representation of states secret from the environment?
Both of these are possible, but each must involve some sort of abstraction for querying states or creating states. I don't have a good feeling about this design.
It would help to clarify the question by
Providing type signatures for the functions of interest
Identifying to which functions you want the representation of states not to be exposed.
P.S. These difficulties are quite separable from Haskell and would be at issue regardless of the choice of implementation language (provided that the implementation language supports some form of privacy).
You'll need to decide which of the agent and the environment sits "on top" - let's suppose for the rest of this answer that it's the environment on top calling into the agent since that generally makes most sense.
You can keep data representations of the Agent private using the module system - just export the datatype name without any of its internals.
module Agent (AgentState, other_stuff) where
as opposd to
module Agent (AgentState(..), other_stuff) where
If the agent also needs to be passed the environment's state (though I can't see any reason this would be necessary as the environment can keep track of it for itself), then make the agent functions polymorphic so that they can be passed any state type - then the environment can pass whatever it likes in without its representation being exposed.
It should also be possible to use state monads to achieve more control over what happens to the state, for example preventing the environment from duplicating a state the agent gives it and calling the agent repeatedly with that same state, but if you're new to Haskell it's probably best to get a bit of experience without monads first. (Not that monads are particularly scary or anything, but they do hide detail from you so it's harder to see what's going on.)