Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tobias: Begin Issuing a Payout #2162

Closed

Conversation

zspencer
Copy link
Member

Open Question

  • What happens when Payout#issue runs twice with the same Payout#amount and Payout#trust#beneficiaries?
  • What happens when the set of Payout#trust#beneficiaries is changed between calls to Payout#issue?
  • What happens when the Payout#amount doesn't divide evenly between Payout#beneficiaries?

* 📝 `TOBIAS`: Sprout README as Contributor-Facing Product Marketing

- zinc-collective#709
- #1

This is an attempt at using a README as a form of product-design
documentation.

It follows the Pain-Dream-Fix recipe for marketing copy, with an
emphasis on the code's *purpose*. By exposing the purpose of the code;
new contributors (or contributors that have been away for a bit)
have a way of grounding themselves in the product-thinking behind the
project itself.

That said, good README's have additional context beyond the purpose, such as:

- A Data Model, which exposes a high-level view of the interactions between
  entities within the system we are building.
- Setup instructions, such as guidance for how to populate an initial
  database or a reference to additional software to install.

But for now we don't have either of those things; and I wanted to do
some Product-based House Keeping, such as creating Fauxsonas and Use
Cases before diving into Engineering.
- #11

I'm starting out by coding by wishful thinking, putting together the
pieces of the pie that I can eat bite by bite.

In this test, I'm using imagining there will be a Model called
`Tobias::Payout`, which will be our computational entrance point into
the [Issuing a Payout](#11)
feature.

I considered starting with a system test, which would have gone through
the User Interface and tied together a bunch of different concepts; but
I figured I would start with a `model` spec; so that I can stay focused
on drawing the computer-facing side of the feature out before worrying
too much about the human-facing bits; which I always find require a lot
more thought for me.

That said, a system test will be useful here at some point.

The computational bits, on the other hand, feel pretty accesible. We
want to create Payments for every Beneficiary of the appropriate amount,
and store records of these Payments so we know who is supposed to get
paid what.

Here's a line-by-line play-by-play of this change:

I'm using the `spec` folder to store executable examples
of a feature.

Because `Issuing Payout` is a feature for the [`TOBIAS`
project](#1), I am storing it
under `spec/tobias`. My choice of what to call the file
(`payout_spec.rb` indicates that this spec will be for the `Payout`
model.

The `require "rails_helper"` line tells our testing framework to load
all the code necessary to run a spec.

The `describe Tobias::Payout do` line groups the examples nested within
it as relating to the `Payout` model.

The `describe "#issue"` line tells me that the `Payout` model will have a
method named `issue`, and also creates a group of examples that describe
how the `Payout#issue` method works.

The `it "issues a Payment..." do` line describes one of the examples we
we plan to use to confirm that the `Payout#issue` method works the way
we hope it will.

The test itself lives on the lines between `it "issues a Payment..." do`
and the `end` that is aligned with the `it`

The `payout = create(:tobias_payout, payout_amount_cents: 150_00) line
says "create a database record of a `Tobias::Payout, and populate it's
`payout_amount_cents` field with $150.00, and store a reference to it in
the `payout` variable.

The `beneficiaries = create_list(10, :tobias_beneficiary, trust:
payout.trust)` line says create 10 `Tobias::Beneficiary` records in the
database, and make sure their `trust` field is pointed at the same
`Tobias::Trust` that our `payout` is pointing to. Store references to
those in the `beneficiaries variable.`

The `payout.issue` line executes the `Payout#issue` method that we are
describing.

The `beneficiaries.each do |beneficiary|` goes over every one of the
newly created `Tobias::Beneficiary` records stored in the
`beneficiaries` variable, expose each one as a variable named
`beneficiary`, and execute the code between it and the next `end`.

The `expect(beneficiaries.payments).to exist(amount_cents)` tells our
example to let us know if there are no `Tobias::Payment` records in the
database for one of the `beneficiaries`.
This sketches in the `Payout#issue` method's line-of-action, which is to
iterate through the `Payout#trust#beneficiaries` and add a `Payment` to the set
of `Payout#payments` for the per-beneficiary amount.

That said, there's a few outstanding questions we'll probably want to
add some tests to interrogate, especially around:

1. What happens if the method is ran twice with the same data?
2. What about if the set of `Payout#trust#beneficiaries` is changed
   between calls to `Payout#issue`?
3. What happens when the `Payout#payout_amount` doesn't divide evenly
   between the `Payout#beneficiaries?
There was a number of things I didn't love about my implementation of
`Payout#issue`:

- I had added a `Tobias::Record` far earlier than necessary
- There were linter errors
- `Payout#payout_amount` felt redundant

This remediates those nose-wrinkles, and sets us up nicely for the next
test.
@zspencer zspencer closed this Jan 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant