last day (17 days later) » 

13:04
0
A: Can a Domain Object always be "completely ignorant of persistence" and yet still possible to persist?

FlaterThe core conflict in your question is the consideration of who drives the design. it should not be designed at all with persistence in mind What this means is that the domain model's design does not entail any persistence considerations. I'm aware that you probably already know this, I'm mentio...

"[the persistence layer] should assume that the domain model's structure is set in stone and non-negotiable" versus "One of these has to give. Either you design your domain in a way that an outside observer can persist it, or you allow your domain to involve itself with calling the shots on persistence"? It's not clear whether you are advising that the model design can be done without regard to persistence, or whether it must be designed in the first place to accommodate persistence. You acknowledge latterly that some model designs can be accidentally unpersistable.
@Steve : Yes, that's my point. If you are building interfaces into the domain to control what gets persisted, you are explicitly involving persistence in the domain design. The question is basically "how strictly do you take 'ignorant' (i.e. 'absent')" in the statement of this design pattern?
@Flater - Your "I disagree. The persistence layer should only be interested in persisting that which you give it." seems to miss the point of what I'm saying. It is logically impossible for the persistence layer to persist something without accessing the bits (as in 1/0 of data) that make it up. So whatever you give it, it better have all the relevant bits totally laid bare and public. Computer objects are made of data; you have to tell the computer to take that data and write it down on the hard drive (or whatever).
So some kind of code has to be present to tell it to take all that "private" stuff and write it down in a fully recoverable form, somehow, somewhere. That means either you break the encapsulation using reflection (etc.), or else you design explicitly into the domain layer code to feed the persistence layer "bits and pieces" of objects, e.g. DTOs or something that are pure data with no methods, in some encapsulation-preserving way.
But, then, each domain object is being designed to produce/map into those DTOs, or so to say in less literal language, it "has knowledge" of the fact it can be turned into DTOs. And since those DTOs are a persistence concern, that means it "has knowledge" of persistence. Or else, there is a different interpretation of "has knowledge" intended here than this one, and if that is so, then what is that? What is the "correct" interpretation of "does not know at all about persistence" if it doesn't mean "domain is designed as though persistence did not exist"?
@The_Sympathizer, well I think "ignorant of" is a clear word, meaning "a total absence of regard for". But other contributors here - usually very sensible ones - seem to think it means "anything less than total responsibility for". So an object that is designed to yield a memento for persistence, or whatever, is apparently "ignorant" of persistence. Personally I think we're seeing utter doublespeak.
@Steve: You bet. Seems there's no "perfect" design; you either trade off whether encapsulation or "ignorance" is more important (or get lucky that the DO's natural design just happens to be fully persistible), and that would be the most honest/"correct" possible answer. The tradeoff really is there, and you then choose the balance that maximizes the design goals of the particular application in question.
@The_Sympathizer (a) It is impossible to at the same time expect that domain implementations (down to the state of any subaggregates) is 100% private, and that the logic to persist it is 100% disconnected from the domain. You've found a new way into the "unstoppable force vs immovable object" discussion. (b) The duck analogy stands. To an outside observer, a domain model is defined by how it can be publicly observed (if it looks like a duck...). A persistence layer stores state, and is inherently able to access the domain model's publicly observable state. [..]
[..] How to restore that persisted state back into the domain model when fetching something from the data store, is the domain's responsibility. This is only difficult in cases where the domain has chosen to represent its internal state significantly different from its externally observable state. This inherently means the domain has signed itself up for translating one to the other. Therefore, if you now find yourself in a situation where you have a snapshot of the external state and you wish to recreate the internal state, the domain has to implement a way for you to do that. [..]
[..] And to pre-empt the subsequent question: but what about the state that's not externally visible? Well that state doesn't matter. Because if it cannot be observed externally in any way (neither directly nor indirectly), then it has no purpose of existing. Simply put, something that is private and never impacts anything that is not private has no functional purpose. Something that is hidden to such a degree is inherently not part of the contract, and therefore it is impossible to expect an external layer such as persistence to be able to know about it or do anything with it.
@Steve: The doublespeak you're referring to is not between what is said but between how it is (wrongly and excessively extremely) interpreted. There is no contradiction here, there is only leeway given for different scenarios as there is no one-size-fits-all answer here. You're taking that leeway and pointing at it as if it proves an inconsistency. It doesn't. Also, your backhanded comment about "usually sensible" contributors is nothing short of an ad hominem and I'm not interested in conversing in this manner.
13:04
@Flater: I think something in the vein of Steve's point could still be made that the way that this has been written and talked about, though, does not easily give a clue as to what leeway actually can or cannot be assumed. As it seems you've obviously pretty much said what I've thought - the domain layer does (likely) need to "know" about persistence in any case where you want both a) encapsulation and b) there is any state that cannot be both arbitrarily accessed and mutated from public methods (i.e. get/set method or via constructor).
But the point is you keep this to the minimum, and in particular you do not include any details of how the persistence operates or that persistence will be done. But you still do have to "inform" that it can be done, and that's not (or shouldn't be) a "no no".
@The_Sympathizer: The domain doesn't need to "know about persistence". What you mean by that is not what that phrase is commonly understood as by software engineers, you have to be really careful about that if you don't want to be misunderstood. The domain doesn't need to do anything other than design its contract in the way that it wishes to be used by external parties. What you're trying to point at as "special extra work for persistence" just isn't that. It's nothing more than clear contract design, which should happen regardless of persistence or not.
@The_Sympathizer: If after the previous comment you still believe that there is some secret encapsulation-breaking required to make the domain persistable, I think it's time for you to post a concrete example of the kind of internals that you think are (a) necessary in the Domain layer in order for it to work (b) should not be exposed via the Domain contract (c) are used or indirectly relied upon by (non-persistence) consumers of the domain and (d) cannot be accessed by persistence in order to either persist or restore the state. I cannot see any example to which all of the above apply.
@Flater : One possibility - you have a configurable factory object where the configuration settings are passed in via constructor and then its only other method is one (say "produce()") to churn out many copies of some other objects. If you want to save the state on this object, you will need to explicitly add another method to dig that out or else somehow try to reconstruct/guess at it from the returned objects, which may or may not be possible - or maybe it is possible, but the "produce()" is very compute intensive or else not something you just wanna do "for fluff".
@The_Sympathizer: What hidden state are you thinking about? Be concrete about your example.
@Flater: Ah I also see you posted two comments in succession. What then does "know about persistence" actually mean in this context? If what I describe (adding a method to reveal more state because persistence is possible ) is not "knowing about persistence" then I don't need to argue further because I misunderstood what was being advocated for and would much rather use the proper understanding so long as I can be confident it is the proper understanding.
@The_Sympathizer: Let's say I hire Bob to write my domain logic, and I might potentially hire Frank to write my persistence logic. Bob should be able to do his work without ever needing to know whether I'll hire Frank or not. If Bob tells me that he is blocked until he knows definitively if Frank will be hired or not, or how Frank will do his job when hired; then Bob is doing his work incorrectly. That's what it means that the domain should "have no knowledge of" persistence.
13:04
@Flater: So then, as described ,this would not preclude, say, going back at a later time to add additional state getting methods in the event the persistence is required, right? That is, "not knowledge of persistence" simply means you don't need to know about persistence to write a functioning MyObject.
@The_Sympathizer: No, that is precisely what is meant. Even if I hire Frank, I shouldn't then go back to Bob and say "hey now you need to change [X] because Frank is here". In effect, the scenario you describe is what I referred to when "Bob tells me that he is blocked until he knows definitively if Frank will be hired or not", except in your scenario Bob assumed Frank would not be hired - and now Frank has been hired Bob needs to redo or expand his work. That's not correct. Bob should be able to finish his job without ever thinking about Frank.
@The_Sympathizer: Based on how you structure your examples of the issue you're asking about, I get the feeling that you're working in more abstract terms than you're comfortable, and you're constructing an argument by using several points, each of which is using a different concrete use case. I need you to come up with a concrete example, and I'll show you how to approach it. There is a lot of nuance here and different scenarios resolve differently - I think you're trying to mistakenly think of these scenarios as a single universal truth, which is probably the cause of the confusion.
@Flater: Yes, you're right, and I don't have that example on hand at this very moment, but I've encountered such a situation before. Thus, I can't discuss further at this time.
@Flater : I just came up with an explicit example and now edited it right into the original post.
@The_Sympathizer: (a) Factories don't tend to get persisted , they are behavior, not state (b) Whatever initially set the max radius (usually a config file when dealing with factory settings) is already your source of truth, why are you trying to persist it a second time? (c) If instead the user provided this data, then they need the ability to know what value they've set it to - thus meaning your setting needs to be public (at least readable), thus opening you up to having the persistence layer read its value in order to persist it.
@Flater, the "usually sensible" remark was not directed at you specifically (the thought occurred to me outside your answer, it's only coincidental that it was finally expressed here in an exchange with the OP). To me, the difficulty seems to be that many here cannot accept that "ignorance" is a strong word, and the answer to the OPs question is "no, the design cannot be ignorant of persistence concerns". The writer contributing to the original Wiki probably went too far in saying an object needn't know "if it will be persisted", and your own answer is ambiguous per my original comment.
@Flater, on the Bob and Frank scenario, one way Bob can make progress is to design things to accommodate Frank if he is hired. But to do so, Bob needs tacit knowledge of Frank's job and how persistence works. I can assure you, if Bob is allowed to proceed independent of Frank and without knowledge of what Frank might later do, then Bob's work may well end up being revisited. There's no reason to think Frank will be able to complete his job, if Bob's code is not written pre-emptively to accomodate Frank, and Bob's code cannot be altered later under Frank's direction.
 
10 hours later…
23:28
@Steve: Your claim as to what the answer allegedly is, is not what my answer to the question is. Disagree all you like, I'm not changing my answer because you think differently. Secondly, Bob should never think about Frank. That is the point I'm trying to get across. "Bob's work may well end up being revisited" is precisely the bad way of doing things - I don't understand why you phrase it in a way that makes it seem an inevitable truth.
@Steve What you claim to be inevitable truth is bad practice and goes against domain-first design principle.
Coming from someone who has successfully adopted domain-first design in the last several years (and other designs in the further past), your claim that Bob must inherently account for Frank and implying it cannot be any other way sounds a lot like an oldschool doctor sticking to his claim that trepanning works and not doing so when a patient is ill would be an act of reckless medicine.
Your claim is not wholly untrue (there were cases where trepanning works; there are designs which are persistence-first such as N-tier architecture), but the assertion that it must invariably be this way is decidedly untrue (trepanning is not the best solution to every problem it claimed to solve; domain-first design inherently means that the domain is designed without needing to consider other layers)

  last day (17 days later) »