Re: [testdrivendevelopment] "Find or Create" functions: a discussion

"Nat Pryce" <[email protected]> Sun, 24 Nov 2019 11:32:31 +0000
Newsgroups gmane.comp.programming.test-driven-development
Message-ID <CADGzuY8e9jdNUALz6TuBFyXnpk0E=3QLEWX+wpEjEUpYCOA0PQ@mail.gmail.com>
--0000000000004ebf130598160146
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Apologies for brevity. I=E2=80=99m on my phone.

I think it depends on how transactions are being managed. If called within
a transactional scope, I=E2=80=99d be happy with separate =E2=80=9CfindPat=
ient=E2=80=9D that
returns an optional patient, and a =E2=80=9CcreatePatient=E2=80=9D that ta=
kes the minimal
properties needed to record a new patient in the system.  That would allow
the properties used to find a patient and the properties used to create a
new patient to vary as the application  requires.

But if transactions & concurrency control are being managed behind the API=
,
they may _have_ to be combined into a single operation.


On Sun, 24 Nov 2019 at 08:55, J. B. Rainsberger <[email protected]>
wrote:

> Hi, folks. An old issue came back to the surface this month in
> consultation with clients and I'd like your opinion. It regards the old
> "find or create" pattern. It seems to violate Command/Query Separation (=
as
> I understand it), but it seems handy and harmless, so I'd like to find o=
ut
> more about what you folks think about it. Benign? Problematic?
>
> I imagine using this with the Repository pattern. Let's say we register =
a
> patient in a medical environment and so we need a UI that reduces as muc=
h
> as possible the number of steps. We don't want to force the user to look=
 up
> a patient just to discover that the hospital has no record of them, so w=
e
> allow the user to enter some basic identifying information. This
> information suffices to either find an existing patient or create a new =
one
> if our database doesn't know that patient. The result is something like
>
> Patient registeredPatient =3D
> patientRepository.findOrCreate(patientIdentifyingInformation);
>
> The identifying information might have basics like name, date of birth, =
it
> doesn't matter. We can guarantee that registeredPatient now represents a=
n
> Entity in our system, either because we found someone that matched the
> identifying information or because we created one.
>
> This appears to violate CQS, but it seems like a good thing to have. Som=
e
> individuals struggle with this, because they don't know whether this is =
an
> area where CQS "doesn't matter" or an area where CQS is trying to teach
> them something and they can't see what they're meant to learn. I haven't
> thought about this in depth in years, so I feel the same way right now.
> Drawbacks? Alternatives?
>
> I was also thinking about how to design this, and it seems to me like a
> special case of getOrAbsent(), so that I could implement the generic
> findOrCreate() algorithm with something like
>
>
> repository.find(identifyingInformation).orElse(T::createFromIdentifyingI=
nformation)
>
> where find() returns Maybe TIdentifyingInformation and T has a named
> constructor for creating a T from a TIdentifyingInformation. I'm assumin=
g
> here that TIdentifyingInformation is enough to provide all the mandatory
> properties of T.
>
> With this design, I don't need a single findOrCreate() function any more=
,
> because the pieces find() and orElse(T::create) communicate the idea wel=
l
> enough.
>
> Thoughts? I'm happy to see the discussion meander. Is this a
> totally-solved issue and there's one clear good way to proceed? or is it
> more a matter of context or preference?
> --
> J. B. (Joe) Rainsberger :: https://tdd.training :: http://www.jbrains.ca
> :: http://www.thecodewhisperer.com
>
>=20
>
> --
http://www.natpryce.com

-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#35743): https://groups.io/g/testdrivendevelopment/mess=
age/35743
Mute This Topic: https://groups.io/mt/61872506/3268755
Group Owner: [email protected]
Unsubscribe: https://groups.io/g/testdrivendevelopment/leave/6156322/74455=
6386/xyzzy  [[email protected]]
-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-


--0000000000004ebf130598160146
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div><div dir=3D"auto">Apologies for brevity. I=E2=80=99m on my phone.</div=
><div dir=3D"auto"><br></div><div dir=3D"auto">I think it depends on how tr=
ansactions are being managed. If called within a transactional scope, I=E2=
=80=99d be happy with separate =E2=80=9CfindPatient=E2=80=9D that returns =
an optional patient, and a =E2=80=9CcreatePatient=E2=80=9D that takes the m=
inimal properties needed to record a new patient in the system.=C2=A0 That =
would allow the properties used to find a patient and the properties used t=
o create a new patient to vary as the application =C2=A0requires.</div></di=
v><div dir=3D"auto"><br></div><div dir=3D"auto">But if transactions &amp; c=
oncurrency control are being managed behind the API, they may _have_ to be =
combined into a single operation.=C2=A0</div><div dir=3D"auto"><br></div><d=
iv dir=3D"auto"></div><div dir=3D"auto"><br></div><div dir=3D"auto">On Sun,=
 24 Nov 2019 at 08:55, J. B. Rainsberger &lt;<a href=3D"mailto:jbrains762@g=
mail.com">[email protected]</a>&gt; wrote:<br></div><div><div class=3D"g=
mail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Hi, folks.=
 An old issue came back to the surface this month in consultation with clie=
nts and I&#39;d like your opinion. It regards the old &quot;find or create&=
quot; pattern. It seems to violate Command/Query Separation (as I understan=
d it), but it seems handy and harmless, so I&#39;d like to find out more ab=
out what you folks think about it. Benign? Problematic?</div><div><br></div=
><div>I imagine using this with the Repository pattern. Let&#39;s say we re=
gister a patient in a medical environment and so we need a UI that reduces =
as much as possible the number of steps. We don&#39;t want to force the use=
r to look up a patient just to discover that the hospital has no record of =
them, so we allow the user to enter some basic identifying information. Thi=
s information suffices to either find an existing patient or create a new o=
ne if our database doesn&#39;t know that patient. The result is something l=
ike</div><div><br></div><div>Patient registeredPatient =3D patientRepositor=
y.findOrCreate(patientIdentifyingInformation);</div><div><br></div><div>The=
 identifying information might have basics like name, date of birth, it doe=
sn&#39;t matter. We can guarantee that registeredPatient now represents an =
Entity in our system, either because we found someone that matched the iden=
tifying information or because we created one.</div><div><br></div><div>Thi=
s appears to violate CQS, but it seems like a good thing to have. Some indi=
viduals struggle with this, because they don&#39;t know whether this is an =
area where CQS &quot;doesn&#39;t matter&quot; or an area where CQS is tryin=
g to teach them something and they can&#39;t see what they&#39;re meant to =
learn. I haven&#39;t thought about this in depth in years, so I feel the sa=
me way right now. Drawbacks? Alternatives?</div><div><br></div><div>I was a=
lso thinking about how to design this, and it seems to me like a special ca=
se of getOrAbsent(), so that I could implement the generic findOrCreate() a=
lgorithm with something like</div><div><br></div><div>repository.find(ident=
ifyingInformation).orElse(T::createFromIdentifyingInformation)</div><div><b=
r></div><div>where find() returns Maybe TIdentifyingInformation and T has a=
 named constructor for creating a T from a TIdentifyingInformation. I&#39;m=
 assuming here that TIdentifyingInformation is enough to provide all the ma=
ndatory properties of T.</div><div><br></div><div>With this design, I don&#=
39;t need a single findOrCreate() function any more, because the pieces fin=
d() and orElse(T::create) communicate the idea well enough.</div><div><br><=
/div><div>Thoughts? I&#39;m happy to see the discussion meander. Is this a =
totally-solved issue and there&#39;s one clear good way to proceed? or is i=
t more a matter of context or preference?<br>-- <br><div dir=3D"ltr" data-s=
martmail=3D"gmail_signature"><div dir=3D"ltr"><div>J. B. (Joe) Rainsberger =
:: <a href=3D"https://tdd.training" target=3D"_blank">https://tdd.training<=
/a> :: <span><a href=3D"http://www.jbrains.ca" target=3D"_blank">http://www=
.jbrains.ca</a> :: <a href=3D"http://www.thecodewhisperer.com" target=3D"_b=
lank">http://www.thecodewhisperer.com</a></span></div><div><br></div></div>=
</div></div></div>



<p></p><p></p></blockquote></div></div>-- <br><div dir=3D"ltr" class=3D"gm=
ail_signature" data-smartmail=3D"gmail_signature"><a href=3D"http://www.nat=
pryce.com" target=3D"_blank">http://www.natpryce.com</a></div>

<div width=3D"1" style=3D"color:white;clear:both">_._,_._,_</div>
<hr>
Groups.io Links:<p>

You receive all messages sent to this group.


<p>

<a target=3D"_blank" href=3D"https://groups.io/g/testdrivendevelopment/mes=
sage/35743">View/Reply Online (#35743)</a> |


  <a target=3D"_blank" href=3D"mailto:[email protected]?subj=
ect=3DRe:%20Re%3A%20%5Btestdrivendevelopment%5D%20%22Find%20or%20Create%22%=
20functions%3A%20a%20discussion">Reply To Group</a>
  
    | <a target=3D"_blank" href=3D"mailto:[email protected]?subject=3DPr=
ivate:%20Re:%20Re%3A%20%5Btestdrivendevelopment%5D%20%22Find%20or%20Create%=
22%20functions%3A%20a%20discussion">Reply To Sender</a>
  


|


  
    <a target=3D"_blank" href=3D"https://groups.io/mt/61872506/3268755">Mu=
te This Topic</a>
  

| <a href=3D"https://groups.io/g/testdrivendevelopment/post">New Topic</a>=
<br>



<br>

<a href=3D"https://groups.io/g/testdrivendevelopment/editsub/3268755">Your=
 Subscription</a> |
<a href=3D"mailto:[email protected]">Contact Group Own=
er</a> |

<a href=3D"https://groups.io/g/testdrivendevelopment/leave/6156322/7445563=
86/xyzzy">Unsubscribe</a>

 [[email protected]]<br>
<div width=3D"1" style=3D"color:white;clear:both">_._,_._,_</div>


--0000000000004ebf130598160146--