I think we are talking at cross purposes - I thought you were talking
about delaying the mutation until the 'main' logic has finished, whereby
the main logic would push the mutation into a queue which were then
executed later. Something like queueing up a bunch of commands to be
executed later.

If you are simply talking about isolating/abstracting database logic
(but not the _timeliness_ of when that logic is executed) from the
mainline code. The Repository pattern, DataAccess pattern then yes, of
course, I think we are all on the same page.

The original point was do you/don't you pass in the DB as an explicit
arg. I still haven't seen a recommendation for handling protocols whose
implementation is persistence agnostic.

I also think you might be making a few unwarranted assumptions ;-) - who
mentioned building up SQL in raw strings?! for example.

James Gatannah writes:

> On Monday, August 3, 2015 at 5:19:34 AM UTC-5, Colin Yates wrote:
>>
>> I have heard this approach before, but I have never seen how it works in
>> real life.
>
>
> Interesting. I don't think I've ever worked anywhere that didn't take this
> kind of approach. Even if we weren't doing it formally.
>
>
>
>> For example, what about 'selects' - where do they happen?
>>
>
> They're just part of the overall transaction description.
>
> It's [thankfully] been a long time since I worked on a project that worked
> in raw strings
> to build SQL. Even working at that level, the SELECT pieces were just
> a subquery in the main query we were building.
>
> The web server(s) would pre-process the incoming request, hand that
> to the middle-tier layers that did this sort of business logic, those would
> pass
> the data description (in this case raw SQL, in others something like
> XML-RPC)
> off to the servers that actually have pools of database connections.
>
> Even in companies that only needed one virtual host for their tiny little
> web
> server and couldn't be bothered to break it into multiple processes, we
> split
> this out into multiple logical layers.
>
>
>> What about if my updates are not independent (e.g. if the first
>> update works then do the second update otherwise do this completely
>> different thing?).
>>
>
> We're working in lisp. This sort of thing is far easier than it is for the
> poor schmucks who are doing exactly this sort of thing in, say, C# with
> LINQ or building/parsing/translating XML using python.
>
>
> For simple workflows I can see the elegance. For non-trivial workflows
>> the problem is that _accessing_ the DB and _switching_ on the DB logic
>> tends to be all through the workflow.
>>
>
> I'll argue that this sort of isolation gets more important when your system
> gets more complex. You don't build a modern automatic transmission with
> sloppier tolerances that were used for a manual 50 years ago. You spend
> more time engineering the Eiffel Tower than you would a back-yard shed.
> You don't skimp on O-rings when you're building a space shuttle.
>
>
>
>> I am genuinely interested in the answers to this as yes, the described
>> approach has some great benefits.
>>
>
> Let's see. Specific example...
>
> This comes from a startup that was bought for IP around 2001. I think it's
> safe to describe what I remember of their general architecture, since it
> seems
> to be extinct.
>
> Big picture was warehouses where workers are loading up pallets of goods to
> be shipped to retail stores.
>
> End users wore computers that had headsets and mics. Input was by
> speech recognition, output through text-to-speech. The wearables didn't have
> enough horse-power to actually do the speech recognition, so compressed .wav
> files were transmitted to the server over wifi.
>
> We probably should have been using a web interface, but most web apps were
> written in perl. This was a serious technology shop using <s>C++</s>MFC.
>
> We had a ton of different modules/classes that covered different
> possibilities for
> any given scenario at various customer sites. They got initialized and wired
> together by rules defined in an .ini file. (That should have come from a
> database,
> but that's a different topic).
>
> Most of our database interaction happened when a worker logged in: we cached
> the various phrases that would be used throughout her shift.
>
> And we'd select a list of work. As each work item was completed, the
> front-end
> code would notify our database layer. I don't have any idea how that
> notification
> worked. It went through some library routine that had a database connection
> buried far away from any front-end code.
>
> "Our" database was really just a cache for interaction phrases in various
> languages
> and the work queues.
>
> Periodically, some job would upload our work status reports and download new
> pending work queues to/from the "real" database. IIRC, this interaction
> happened
> over FTP. We absolutely did not have (or want!) handles to work directly
> with
> whatever ancient server that was their authoritative source of all
> knowledge.
>
> Our portion of the system was ~70-80 KLOC. Since it was C++ (and most of
> that was boilerplate), it was *far* simpler (in terms of business logic)
> than the 200 KLOC of clojure that we're talking about. Although the big iron
> side may have pushed it into that realm.
>
> You obviously aren't going to be able to predict every possible interaction
> in
> the next few minutes. Much less the next 4 hours. But you should be able to
> predict
> most of what might happen for any given web request.
>
> Life changes when you're working on a highly interactive app like, say, an
> IDE
> or a photo editor. At my job today we have issues with multiple users adding
> and removing the same artifact to a document at something resembling the
> same
> time.
>
> That problem has a lot to do with the fact that it's a distributed system
> with at
> least (I haven't dug into the tier beneath the web server) 4 layers between
> the
> end-users and the actual database connections. I'm not sure it would be
> possible
> to get rid of more than one of those layers to get us closer to the
> database.
>
> I'm absolutely positive that it would not be desirable.
>
> My "database connection" consists of data structures that I put onto and
> read
> from a message queue.
>
> This system is about as far from functional purity as you can possibly get.
>
> It's quite possible that the database guys at the very bottom of the stack
> are
> using exactly the kind of global connections that were originally suggested.
>
> The difference is that, even if they are (and I certainly hope not!), I
> can't touch
> them. When (and it's never "if") a hacker gets control over the front-end
> web
> server, that's just the first layer of defense.
>
> Regards,
> James
>
>
>
>>
>> James Gatannah writes:
>>
>> > On Thursday, July 30, 2015 at 7:44:31 PM UTC-5, J. Pablo Fernández
>> wrote:
>> >>
>> >> Hello Clojurians,
>> >>
>> >> I found passing around the database connection to each function that
>> uses
>> >> it very error prone when you are using transactions as passing the
>> wrong
>> >> one could mean a query runs outside the transaction when in the source
>> code
>> >> it is inside the with-db-transaction function.
>> >>
>> >
>> > I'll go ahead and make the point that it's error-prone for different
>> > reasons.
>> >
>> > Pretty much by definition, that database connection is a system
>> boundary.
>> > It's all about something that's *way* more complex than random global
>> state
>> > changes inside your program. This is a thing that interacts with the
>> > outside world, with all the nastiness that implies.
>> >
>> > Everything that everyone else has already written about this approach is
>> > true, but I don't think they've gone far enough.
>> >
>> > Even if you pass that database connection around as a parameter
>> everywhere,
>> > you're talking about throwing away a huge part of the benefit of using a
>> > functional language.
>> >
>> > Isolate your side-effects.
>> >
>> > Think of a castle. You have a moat surrounding it, and a few gates that
>> you
>> > use to allow your peasants to enter/exit. This particular gate opens up
>> to
>> > a swamp full of alligators.
>> >
>> > Your approach amounts to letting the gators wander around loose.
>> >
>> > Passing the connection around to each function in the call chain is like
>> > tying a ribbon around the gator's neck and hoping you can use that as a
>> > leash.
>> >
>> > You can use either approach to great effect. If you're really, really
>> good.
>> > And so is everyone else on your team (you did mention a 200 KLOC
>> project).
>> >
>> > One of the main benefits to functional programming is that admitting you
>> > aren't really, really good is incredibly liberating. I don't have the
>> > time/energy to dedicate to trying to maintain this sort of code. (Yes, I
>> > spent lots of time recently thinking about how java was designed for
>> very
>> > average programmers, but it really takes much better programmers than a
>> > functional language to actually write correct programs). Even if I were
>> > that good...I'd rather be focused on the problems that make my customers
>> > happy.
>> >
>> > I'm going to appeal to authority here for the right
>> > answer: http://prog21.dadgum.com/23.html (in my defense, it's a great
>> > blog). Have your web response handler (which is another system
>> > boundary...this one is next to an active volcano populated by
>> > fire-breathing dragons) build up a list of all the nasty side-effects
>> that
>> > will eventually have to happen.
>> >
>> > Don't just isolate your side-effects. Quarantine those suckers as if
>> each
>> > and every one means you're dealing with the most diabolical hacker you
>> can
>> > imagine.
>>
>> --
>> Sent with my mu4e
>>

--
Sent with my mu4e

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to