Re: [Snowdrift-dev] code feedback please!

2016-11-03 Thread Stephen Michel


On November 3, 2016 7:38:24 PM EDT, Aaron Wolf  wrote:
>On 10/27/2016 06:55 PM, Bryan Richter wrote:
>> 
>> -snip-
>
>I hope others will weigh in.

I'm planning on weighing in but I'm in the middle of a big crunch so it won't 
be until at least next Friday.
-- 
Sent from my phone; please excuse my brevity.
Email policy: http://smichel.me/email
___
Dev mailing list
Dev@lists.snowdrift.coop
https://lists.snowdrift.coop/mailman/listinfo/dev


Re: [Snowdrift-dev] code feedback please!

2016-11-03 Thread Aaron Wolf
On 10/27/2016 06:55 PM, Bryan Richter wrote:
> Hi everyone,
> 
> The crowdmatch mechanism code is still a work in progress, and I want
> to talk about what I've done so far to get some feedback. This email
> has become rather long! Feel free to skim it to find parts that sound
> interesting. This was written for my benefit as much as yours, and in
> the hope that I get some feedback. Anything at all, like "Well hurry up
> and do it already", is very welcome.
> 
> It is also written for posterity and for your amusement. :)
> 
> The new code is on a branch called split-mechanism. A giant comparison
> can be viewed, but it's longer than this email(!)[1] and I'm going to
> call out specific items instead. This will be a technical discussion,
> but not too nutty. I will talk about how I structured the crowdmatch
> mechanism code, how I've designed it to be used, how I've designed it
> to be testable, and how some quirks popped up during my headlong crash
> through coding it. Please reply with feedback ABOUT ANY PART OF THIS! :D
> 
> ### Table of Contents:
> 
> 1.   A separate module for the crowdmatch mechanism
> 2.   API for the library
> 2.a.   Client code requirements
> 2.b.   Usage example
> 2.c.   Exported actions
> 3.   Database management
> 3.a.   Migrations
> 3.b.   The test database
> 3.c.   run-persist library
> 4.   Implementation to allow property testing
> 5.   Implementation to allow more-than-one Stripe
> 6.   Difference between MechAction and StripeI
> 7.   What's left to do
> 
> Appendix A: Questions
> 
> ### 1. A separate module for the crowdmatch mechanism
> 
> Although there is only one foreseeable client to this code, namely the
> Snowdrift website, I went ahead and structured it as a standalone
> library. It is in a directory called 'crowdmatch'. I did this so it can
> be tested independently. It will be a lot more stable than the website
> eventually, too, which is a good decider for whether something should
> be independent or not.
> 
> ### 2. API for the library
> 
> The crowdmatch library puts certain constraints on client code because
> it requires a database. Then, it does what any API does: provides
> actions and data types.
> 
> ### 2.a. Client code requirements
> 
> A client of this library must be using Postgres via Persistent.
> The only way to be agnostic about databases would be to completely
> reimplement a database. That's nuts. The library will just use Postgres,
> and thus requires client code to use it as well.
> 
> The library also needs to do IO to talk to Stripe. Rather than rely
> on monad transformers or mtl-style classes to manage these different
> layers, I use plain old functions. Each API method needs to be passed
> a handler for running database actions. Will this be a pain in the
> ass? Probably not. It's also the easiest style to change FROM, should
> that become necessary.
> 
> The library maintains its own notion of what a "Patron" is. To
> interface with the website, I created ToMechPatron and FromMechPatron
> type classes. These are easy to define for the User type. Thus, it's
> easy to create a relationship between "website Users" and "crowdmatch
> Patrons".
> 
> ### 2.b. Usage example
> 
> Here's a usage example that covers these parts so far.
> 
> Given:
> 
> fetchPatron
> :: (ToMechPatron usr, MonadIO io, MonadIO env)
> => SqlRunner io env
> -> usr
> -> env Patron
> 
> You can run:
> 
> someHandler = do
> Entity uid user <- requireAuth
> patron <- Crowdmatch.fetchPatron runDB uid
> ...
> 
> See how 'runDB' is passed in as the database runner.
> 
> ### 2.c. Exported actions
> 
> There are about ten operations that will be exported, as well as a
> handful of data types. I am starting with fetching, storing, and
> deleting two items: payment-method tokens and pledges. The payment
> tokens are what Stripe gives us in lieu of credit card info. Pledges are
> what you think they are: the record of a donor pledged to a project.
> 
> Next in the API are two super important methods (prototyped but not
> implemented yet): 'runCrowdmatch' and 'processPayments'.
> 
> The first looks at all pledged patrons and calculates an outstanding
> donation balance. After a crowdmatch event, each pledged patron will
> then "owe" a certain amount to the project. That all happens in the
> database in a single transaction.
> 
> Later, at our leisure, we can run 'processPayments'. That method
> inspects outstanding balances and sends payment commands via
> Stripe. This is where fee limits take effect.
> 
> The website won't trigger the crowdmatch event or payment processing.
> Instead I'll have two simple utilities that do that stuff. I'll just
> run them manually at first.
> 
> This section was longer than I intended, but that's probably good.
> It's one of the more important. Feedback on the API is highly welcome.
> 
> API to date:
>