Re: How do you handle free-text associations with DDD
Denis Biondic <[email protected]>
| Newsgroups | gmane.comp.programming.domain-driven-design |
|---|---|
| Message-ID | <CAJQG4FX0FGA3qDYa7vBy9GQC1bkyxoJ93zhQj+xbxwqgOShb3A@mail.gmail.com> |
Thanks for your replies ;) Well, you are right about this Invoice - Customer being just a toy sample; and I think that having Invoice hierarchy won't really cut it as well... Maybe I took a wrong example. Let me try to try again: Imagine having Customer and CustomerType. Lets assume that this type can be free-typed on Customer edit screen, but can also be choosen in that same screen via some combobox or some extra dialog. The question remains, do you provide a text property (field) on Customer for this type, or do you do an association? Of course, there is still a possibility that you define CustomerTypes via some other screen and these types would be reusable in this Customer screen. Some business constraints I can think of: - free-typed CustomerType should not be possible to be reused by other Customers. Many of these types with same name can coexist. - "real" CustomerTypes must have unique name among other CustomerTypes. - each "real" CustomerType can have some additional data attached to it, which is shown on Customer screen (if real type is choosen from the dropdown for example). - changing the Name of "real" CustomerType changes the name of the type for all Customers that use this "real" type. What I have extracted from little bit more analysis is that now I call this process "linking". I would introduce the real association here (between Customer and CustomerType), and each CustomerType would have a field on it to mark is it "linked" or not. The workflow would be that free-text Types are "unlinked" and their names can be duplicated among other "unlinked" CustomerTypes. Any of the types entered through dedicated CustomerTypes dialog would be "linked". If the user edits some Customer and chooses a "linked" type over an "unlinked" type, it would swap the associations, and delete the "unlinked" type from the CustomerTypes table. There would be some more tracking and work around this, but I think I find this the cleanest approach, because to state it one more time --- each of these Types can have "linked" data with it. Maybe the term "linking" isn't the best here, but since this is another fictional example ... :=) Another major benefit from this approach would be the querying from database side, because all CustomerType names would be in the same table (no split of data). What do you think about this idea? Any other toughts? Denis. On Wed, Mar 13, 2013 at 9:06 PM, Simon Fox <[email protected]> wrote: > ** > > > Going back to the original question, are you possibly missing a concept > here something like Sale or Transaction that links the invoice to the sales > information. Sale could be a CustomerSale or a CashSale where a cash sale > would track "free" customer information. > > /* > Email: [email protected] > Twitter: @simonmfox > Phone: +64 21 079 2900 > */ > > > On Thu, Mar 14, 2013 at 6:22 AM, Yevhen Bobrov <[email protected]>wrote: > >> ** >> >> >> I don't do reporting on OLTP databases ;) >> >> 13 марта 2013, в 19:05, Giacomo Tesio <[email protected]> написал(а): >> >> It's just as hard as doing any meaningful reporting out of a db schema >> designed to persist an object model. :-) >> >> And indeed we handle reporting with dedicated schemas in the database >> (and often a schema serves only one report). Indeed you don't need to track >> the customer's address to build many of reports. Such strategy enable to >> build reports really fast, with lower load on reporting's machines. >> >> Obviously it's not good for data mining. >> Again schemas for data mining are different, but this looks a bit >> off-topic here. >> >> >> Giacomo >> >> >> On Wed, Mar 13, 2013 at 4:47 PM, Yevhen Bobrov <[email protected]>wrote: >> >>> ** >>> >>> >>> Well, if you don't do anything interesting with invoice data then you >>> can store only PDFs, for sure. >>> >>> But unfortunately doing any meaningful reporting out of PDFs is quite >>> hard :) >>> >>> Yevhen >>> >>> 13 марта 2013, в 15:35, Giacomo Tesio <[email protected]> написал(а): >>> >>> Exactly. Our customers do so. >>> Would you store a contract that you sign with a bank, or not? >>> PDF/A is a format designed to be stored this way, as you would do with >>> paper. >>> >>> And BTW, why not? What's wrong with files? >>> File storage is far cheaper than databases, and you can set up >>> customized archive policy if you need them. >>> >>> Moreover, PDF files don't change, while databases evolve and >>> applications too: can you really grant that you can reproduce the invoice >>> exactly in the same way that you printed 5 years ago, if you need to? >>> >>> >>> Giacomo >>> >>> On Wed, Mar 13, 2013 at 12:37 PM, Yevhen Bobrov <[email protected] >>> > wrote: >>> >>>> ** >>>> >>>> >>>> PDF is just a paper representation of invoice. >>>> What if I want to print it again? Perhaps customer is asking for a copy. >>>> Should I store PDF forever? >>>> >>>> 13 марта 2013, в 13:05, Giacomo Tesio <[email protected]> написал(а): >>>> >>>> Sure, you are right. >>>> >>>> However in such situation we simply use the PDF/A that was printed (in >>>> our domain they are reports, financial advices, contracts and so on...) as >>>> the autoritative source of true. We fill them with searchable metadata and >>>> we register in a dbms their relations with our entities. But we try to >>>> minimize the informative duplication between db and formal documents (when >>>> possible). >>>> >>>> BTW, I thought he was using invoicing just as a toy example. >>>> >>>> >>>> Giacomo >>>> >>>> On Wed, Mar 13, 2013 at 11:27 AM, Yevhen Bobrov < >>>> [email protected]> wrote: >>>> >>>>> ** >>>>> >>>>> >>>>> I think it is better to get a deeper understanding of domain. >>>>> >>>>> Once published (finalized) an invoice becomes immutable. It's simply a >>>>> historical record then. That means that any information which is the part >>>>> of an invoice cannot be changed. >>>>> >>>>> So if customer information (say an address) changes afterwards and >>>>> you're only storing live reference to a customer entity (by means of >>>>> customer id) on an invoice, next time you open it, instead of showing >>>>> customer information that was actual at the moment it was published, it >>>>> will show an updated customer information. Which is wrong and illegal amost >>>>> everywhere. >>>>> >>>>> Armed with this knowledge the solution is obvious - you need to copy >>>>> all information referenced by invoice into invoice aggregate itself. >>>>> Capture it. >>>>> >>>>> Then when you select customer from the list of existing customers (in >>>>> GUI) you will just copy all of the relevant properties. Same with the >>>>> free-form input - user can just fill out all of the relevant properties >>>>> in-place, without bothering creating permanent customer data. This is >>>>> especially useful, because usually there is no point to create permanent >>>>> customer entity for one-time sales. But it depends on you business >>>>> requirements. >>>>> >>>>> So that means that you customer list is nothing more than a glorious >>>>> autocomplete, which just prefills fields on an invoice with permanently >>>>> stored customer information. >>>>> >>>>> BTW, exactly the same situation is with invoice items. >>>>> >>>>> Yevhen. >>>>> >>>>> P.S. If you don't copy referenced information you will end up with >>>>> silly things like multiversioning of referenced entities and all that jazz. >>>>> >>>>> >>>>> 13 марта 2013, в 11:35, Giacomo Tesio <[email protected]> написал(а): >>>>> >>>>> What do you think about a hierarchy of Invoice (the abstract one, >>>>> derived by the others), CustomerInvoice and FreeInvoice? >>>>> CustomerInvoice would derive Invoice and use a CustomerIdentifier to >>>>> relate to the customer and the FreeInvoice would simple use a string. >>>>> >>>>> >>>>> Giacomo >>>>> >>>>> On Tue, Mar 12, 2013 at 11:16 AM, codewithcoffee < >>>>> [email protected]> wrote: >>>>> >>>>>> ** >>>>>> >>>>>> >>>>>> >>>>>> Hello All, >>>>>> >>>>>> I will first present a simple example which I know that I shouldn't >>>>>> talk >>>>>> about UI first, but it places the example in a context. >>>>>> >>>>>> So - imagine two agg. roots: Invoice and Customer. Invoice has an >>>>>> association to Customer, but there is also a possibility to define a >>>>>> customer for an invoice by simply typing the customer name into the >>>>>> "Customer" textbox. I would call this free-text. >>>>>> >>>>>> There are two possibilities here as I see them: >>>>>> >>>>>> - have a text property on Invoice in which the customer name is stored >>>>>> (I would not go for this at all), and then provide messy code that >>>>>> decides what to return when you ask for the Customer. >>>>>> - create a new Customer when saving the Invoice, by providing his >>>>>> newly >>>>>> typed name since this is the only dependency of the Customer root. >>>>>> >>>>>> I would always lean for second approach, but take into account that we >>>>>> don't want these "free" customers displayed in our "Customers view" >>>>>> for >>>>>> example. So, what could you do? Add a property on Customer that would >>>>>> distinguish these entries? >>>>>> >>>>>> I would also presume that since this "feature" is required in the >>>>>> domain, we would have requirements like: "User is able to define a >>>>>> Free >>>>>> Customer on an Invoice" and an UI requirement like "User should not >>>>>> see >>>>>> Free Customers in Customers View". >>>>>> >>>>>> One option that I see is having inheritence in place here, meaning >>>>>> specific entities Customer and FreeCustomer entities, but again I am >>>>>> little confused how to model this in DDD way. >>>>>> Would FreeCustomer inherit Customer which is agg. root? Would callers >>>>>> of >>>>>> interating over all Customers try to cast to FreeCustomer? I generally >>>>>> don't like inheritance that much. >>>>>> >>>>>> This example is completely made up, and I know what there are no >>>>>> "concrete" questions here; but I would appreciate any comments about >>>>>> the >>>>>> thoughts given here :=) >>>>>> >>>>>> Best regards, Denis >>>>>> >>>>>> >>>>> >>>> >>> >> > >