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

"Ahmet Murati" <[email protected]> Sun, 24 Nov 2019 08:59:30 +0000
Newsgroups gmane.comp.programming.test-driven-development
Message-ID <CH2PR14MB37075A1292F5D26BE9113166EE4B0@CH2PR14MB3707.namprd14.prod.outlook.com>
--_000_CH2PR14MB37075A1292F5D26BE9113166EE4B0CH2PR14MB3707namp_
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

When developing web applications we should bear in mind that some people th=
at do not want to have I.e. any citizenship, this would lead to dirty data


Mit Freundlichem Gr=FC=DFen

Ahmet Murati

Software developer & Translator

E-mail: [email protected]
E-mail: [email protected]
Handy: +4915123015776

________________________________
From: [email protected] <[email protected]> on=
 behalf of J. B. Rainsberger <[email protected]>
Sent: Sunday, November 24, 2019 9:55:36 AM
To: [email protected] <[email protected]>
Subject: [testdrivendevelopment] "Find or Create" functions: a discussion

Hi, folks. An old issue came back to the surface this month in consultatio=
n with clients and I'd like your opinion. It regards the old "find or creat=
e" pattern. It seems to violate Command/Query Separation (as I understand i=
t), but it seems handy and harmless, so I'd like to find out more about wha=
t 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 much a=
s 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 we a=
llow the user to enter some basic identifying information. This information=
 suffices to either find an existing patient or create a new one if our dat=
abase doesn't know that patient. The result is something like

Patient registeredPatient =3D patientRepository.findOrCreate(patientIdenti=
fyingInformation);

The identifying information might have basics like name, date of birth, it=
 doesn'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.

This appears to violate CQS, but it seems like a good thing to have. Some =
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 the=
m something and they can't see what they're meant to learn. I haven't thoug=
ht about this in depth in years, so I feel the same way right now. Drawback=
s? Alternatives?

I was also thinking about how to design this, and it seems to me like a sp=
ecial case of getOrAbsent(), so that I could implement the generic findOrCr=
eate() algorithm with something like

repository.find(identifyingInformation).orElse(T::createFromIdentifyingInf=
ormation)

where find() returns Maybe TIdentifyingInformation and T has a named const=
ructor for creating a T from a TIdentifyingInformation. I'm assuming here t=
hat TIdentifyingInformation is enough to provide all the mandatory properti=
es 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 well e=
nough.

Thoughts? I'm happy to see the discussion meander. Is this a totally-solve=
d issue and there's one clear good way to proceed? or is it more a matter o=
f context or preference?
--
J. B. (Joe) Rainsberger :: https://tdd.training<https://eur02.safelinks.pr=
otection.outlook.com/?url=3Dhttps%3A%2F%2Ftdd.training&data=3D02%7C01%7C%7C=
3d347c93073d490e49b908d770bc1ebc%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0=
%7C637101825578440108&sdata=3DPrF8bFTpB%2FldS1BqWrhY8yjvnzIRCBye0HR8hMy2W5Q=
%3D&reserved=3D0> :: http://www.jbrains.ca<https://eur02.safelinks.protecti=
on.outlook.com/?url=3Dhttp%3A%2F%2Fwww.jbrains.ca&data=3D02%7C01%7C%7C3d347=
c93073d490e49b908d770bc1ebc%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C63=
7101825578450119&sdata=3DPoxbqrXKmUWEmr%2FB2anjLMzBDzN3JQ5nW9ZG1OficJs%3D&r=
eserved=3D0> :: http://www.thecodewhisperer.com<https://eur02.safelinks.pro=
tection.outlook.com/?url=3Dhttp%3A%2F%2Fwww.thecodewhisperer.com&data=3D02%=
7C01%7C%7C3d347c93073d490e49b908d770bc1ebc%7C84df9e7fe9f640afb435aaaaaaaaaa=
aa%7C1%7C0%7C637101825578460124&sdata=3DKuaRplAiCAXg12r1CbPxdOudcmQTmte2mq4=
069dG%2B5M%3D&reserved=3D0>



-=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 (#35754): https://groups.io/g/testdrivendevelopment/mess=
age/35754
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-


--_000_CH2PR14MB37075A1292F5D26BE9113166EE4B0CH2PR14MB3707namp_
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Diso-8859=
-1">
</head>
<body>
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
When developing web applications we should bear in mind that some people t=
hat do not want to have I.e. any citizenship, this would lead to dirty data
<br>
<br>
</div>
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
<span id=3D"OutlookSignature">
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
<br>
</div>
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
Mit Freundlichem Gr=FC=DFen&nbsp;<br>
<br>
</div>
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
Ahmet Murati<br>
<br>
</div>
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
Software developer &amp; Translator<br>
<br>
</div>
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
E-mail:&nbsp;[email protected]<br>
</div>
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
E-mail:&nbsp;[email protected]<br>
</div>
<div dir=3D"auto" style=3D"direction: ltr; margin: 0; padding: 0; font-fam=
ily: sans-serif; font-size: 11pt; color: black; ">
Handy:&nbsp;&#43;4915123015776<br>
</div>
</span><br>
</div>
<hr style=3D"display:inline-block;width:98%" tabindex=3D"-1">
<div id=3D"divRplyFwdMsg" dir=3D"ltr"><font face=3D"Calibri, sans-serif" s=
tyle=3D"font-size:11pt" color=3D"#000000"><b>From:</b> testdrivendevelopmen=
[email protected] &lt;[email protected]&gt; on behalf of J. B. Rain=
sberger &lt;[email protected]&gt;<br>
<b>Sent:</b> Sunday, November 24, 2019 9:55:36 AM<br>
<b>To:</b> [email protected] &lt;testdrivendevelopment@group=
s.io&gt;<br>
<b>Subject:</b> [testdrivendevelopment] &quot;Find or Create&quot; functio=
ns: a discussion</font>
<div>&nbsp;</div>
</div>
<div>
<div dir=3D"ltr">
<div>Hi, folks. An old issue came back to the surface this month in consul=
tation with clients and I'd like your opinion. It regards the old &quot;fin=
d or create&quot; pattern. It seems to violate Command/Query Separation (as=
 I understand it), but it seems handy and harmless,
 so I'd like to find out more about what you folks think about it. Benign?=
 Problematic?</div>
<div><br>
</div>
<div>I imagine using this with the Repository pattern. Let's say we regist=
er a patient in a medical environment and so we need a UI that reduces as m=
uch as possible the number of steps. We don't want to force the user to loo=
k up a patient just to discover that
 the hospital has no record of them, so we allow the user to enter some ba=
sic identifying information. This information suffices to either find an ex=
isting patient or create a new one if our database doesn't know that patien=
t. The result is something like</div>
<div><br>
</div>
<div>Patient registeredPatient =3D patientRepository.findOrCreate(patientI=
dentifyingInformation);</div>
<div><br>
</div>
<div>The identifying information might have basics like name, date of birt=
h, it doesn't matter. We can guarantee that registeredPatient now represent=
s an Entity in our system, either because we found someone that matched the=
 identifying information or because
 we created one.</div>
<div><br>
</div>
<div>This appears to violate CQS, but it seems like a good thing to have. =
Some individuals struggle with this, because they don't know whether this i=
s an area where CQS &quot;doesn't matter&quot; or an area where CQS is tryi=
ng to teach them something and they can't see
 what they're meant to learn. I haven't thought about this in depth in yea=
rs, so I feel the same way right now. Drawbacks? Alternatives?</div>
<div><br>
</div>
<div>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 fin=
dOrCreate() algorithm with something like</div>
<div><br>
</div>
<div>repository.find(identifyingInformation).orElse(T::createFromIdentifyi=
ngInformation)</div>
<div><br>
</div>
<div>where find() returns Maybe TIdentifyingInformation and T has a named =
constructor for creating a T from a TIdentifyingInformation. I'm assuming h=
ere that TIdentifyingInformation is enough to provide all the mandatory pro=
perties of T.</div>
<div><br>
</div>
<div>With this design, I don't need a single findOrCreate() function any m=
ore, because the pieces find() and orElse(T::create) communicate the idea w=
ell enough.</div>
<div><br>
</div>
<div>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 mat=
ter of context or preference?<br>
-- <br>
<div dir=3D"ltr" class=3D"x_gmail_signature">
<div dir=3D"ltr">
<div>J. B. (Joe) Rainsberger :: <a href=3D"https://eur02.safelinks.protect=
ion.outlook.com/?url=3Dhttps%3A%2F%2Ftdd.training&amp;data=3D02%7C01%7C%7C3=
d347c93073d490e49b908d770bc1ebc%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%=
7C637101825578440108&amp;sdata=3DPrF8bFTpB%2FldS1BqWrhY8yjvnzIRCBye0HR8hMy2=
W5Q%3D&amp;reserved=3D0" originalsrc=3D"https://tdd.training" shash=3D"LWf7=
sNi6sBxcNTPMo7s7kxAlm5XDsGBesok/cHPJiHqL8xadnRLULubdw/NLvcuHi9ik9Xeg18C/HRO=
UQRvALS9XdBaDJn9okutPTFqsJ8&#43;y2sIsWymEW&#43;JnD5FgxcRUrnPc7G6WskBoW2Bnug=
hdmAk&#43;1SXMg5dHlUdDH1giQmw=3D" target=3D"_blank">
https://tdd.training</a> :: <span><a href=3D"https://eur02.safelinks.prote=
ction.outlook.com/?url=3Dhttp%3A%2F%2Fwww.jbrains.ca&amp;data=3D02%7C01%7C%=
7C3d347c93073d490e49b908d770bc1ebc%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7=
C0%7C637101825578450119&amp;sdata=3DPoxbqrXKmUWEmr%2FB2anjLMzBDzN3JQ5nW9ZG1=
OficJs%3D&amp;reserved=3D0" originalsrc=3D"http://www.jbrains.ca" shash=3D"=
IBFIHF6wuG/u9vyUbyHDYrtucf/J2tNwdmUBAhAKnurIgZRuBYjyhXYILjofLgfQ9bcP7jDlKVp=
tsq8DXx7SjKeXCkaNZ4E4/yVCdeSEJNHETKzcDEyBZlIEyoGZORpG0Wc/OR/t/ntOz7cqmigD4V=
JT/at0cvj84XAkjtU/acE=3D" target=3D"_blank">http://www.jbrains.ca</a>
 :: <a href=3D"https://eur02.safelinks.protection.outlook.com/?url=3Dhttp%=
3A%2F%2Fwww.thecodewhisperer.com&amp;data=3D02%7C01%7C%7C3d347c93073d490e49=
b908d770bc1ebc%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637101825578460=
124&amp;sdata=3DKuaRplAiCAXg12r1CbPxdOudcmQTmte2mq4069dG%2B5M%3D&amp;reserv=
ed=3D0" originalsrc=3D"http://www.thecodewhisperer.com" shash=3D"li3a5Oe8v5=
OjKYhrlLidpcD4zo88xNm/qYSMVtWZqs4/HoSNRY7yMUqno2/q5soZ7dDpSmj4NZiYfCP&#43;1=
tXWeo7zLLJ&#43;gDX7sdxafaqUIz37UIQ96e41i14M9z4xPmnWp&#43;lKll6GpuxphcmcIeyN=
ZMKSs1b4kgM9n&#43;dk5ep5Aww=3D" target=3D"_blank">
http://www.thecodewhisperer.com</a></span></div>
<div><br>
</div>
</div>
</div>
</div>
</div>

</div>
</body>
</html>

<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/35754">View/Reply Online (#35754)</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=3D=
Private:%20Re:%20Re%3A%20%5Btestdrivendevelopment%5D%20%22Find%20or%20Creat=
e%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>


--_000_CH2PR14MB37075A1292F5D26BE9113166EE4B0CH2PR14MB3707namp_--