<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 13 August 2014 08:17, Peter Inglesby <span dir="ltr"><<a href="mailto:peter.inglesby@gmail.com" target="_blank">peter.inglesby@gmail.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class=""><div>> <span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px">I'm starting my week-long exercise on trying it out on a slice of our existing Django monster. I'll report back.</span></div>


<div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px"><br></span></div></div><div><span style="color:rgb(0,0,0);font-family:arial,sans-serif;font-size:13px">Echoes of Captain Oates here?</span></div>

<div>
<br></div><div>Anyway, reviving an old thread: Brandon Rhodes talks provides a straightforward and accessible summary of "The Clean Architecture" in a recent talk[0] and it's the least wanky discussion of this kind that I've come across.  His main point is that things with side effects (particularly calling external services) should be isolated in "procedural glue" code, while the processing of data -- the business logic -- should happen in pure functional code.  This leads to a better focus on the structure of the data you're dealing with, which in turn leads to more comprehensible and maintainable code.</div>


<div><br></div><div>Thoughts?</div><div><br></div>[0] <a href="http://www.pyvideo.org/video/2840/the-clean-architecture-in-python" target="_blank">http://www.pyvideo.org/video/2840/the-clean-architecture-in-python</a></div>

</blockquote><div><br></div><div>I'm always reminded of that Rimmer quote about Oates... <br></div><div><br></div><div>I've been doing this recently with Twisted -- separating out async code that deals with deferred chains from synchronous logic handling the results of the deferreds. <br>

I'm finding that it's leading to clear, easily tested code -- simple synchronous tests on real data for the business logic, and stubbed success/failures to test the various code-paths in the deferred logic. <br>I came to this variously by tangling too much with mixes of deferred-flows and business logic while trying to write simple tests and seeing this DAS talk on Boundaries [1]<br>

<br></div><div>d = defer.succeed(foo)<br></div><div>d.addCallback(handle_foo)<br>d.addCallback(make_request)<br>d.addErrback(retry, make_request, foo)<br></div><div>d.addCallback(parse_body)<br></div><div>return d<br></div>

<div>^ code like this is easily tested by stubbing all the callbacks, with the stubs either succeeding or raising synchronous exceptions. <br><br></div><div>def parse_body(body):<br></div><div>  content = json.parse(body.read())<br>

</div><div>  if not 'username' in content:<br></div><div>    raise HttpError(401)<br></div><div>  return Response(content)<br></div><div>^ again, really easy to test. No deep nested logic, no need to mock or stub. <br>

</div><div><br>[1] <a href="https://www.destroyallsoftware.com/talks/boundaries">https://www.destroyallsoftware.com/talks/boundaries</a><br><br><br></div><div> </div></div></div></div>