TheProlog / prolog-use_cases

Use-case layer for Meldd/Prolog application.
0 stars 0 forks source link

Use-case class and support for proposing an Edit Contribution. #19

Closed jdickey closed 8 years ago

jdickey commented 8 years ago

Overview

Class ProposeEditContribution is the next in our continuing series of use cases, which allows for the submission of a request that the author of an Article approve a change to its content.

Its inputs are (in no particular order or separation here):

That's a total of _s_even inputs, which just feels like a lot. They're all needed, as far as we can tell, because this "use case" is a high-level "supervisor" for several actions:

  1. The Article Repository is queried for an Article with a specific title by a specific Author. If found, the code proceeds to the next step; if not found, an error notification is set and the use case is aborted;
  2. In future, the "Authoriser" object may be queried for actual permissions; initially, it is used simply to query the name of the Member proposing the Contribution;
  3. The selected Article is inspected, and the supplied endpoints validated as being within its body. If they are, the code proceeds to the next step; otherwise, an error notification is set and the use case is aborted;
  4. The Contribution Repository is queried for the ID number of the last Contribution to this Article. If none are found, that number is returned as zero;
  5. The Markdown-to-HTML Service is used to convert the proposed replacement content for the selection to HTML. If it reports errors, those are captured as the use case's own, and the use case aborts;
  6. The Selection Service is used to create an updated Article body string based on the existing body, the proposed replacement content (as HTML), and the last Contribution ID. If it reports errors, those are captured as the use case's own, and the use case aborts; if successful, it provides a (new) contribution-ID sequence number as an attribute;
  7. A new record is added to the Contribution Repository, which includes
    1. the state of the contribution ("proposed")
    2. the identification of the Article in question;
    3. the name of the Member proposing the Contribution;
    4. the updated body content from the Selection Service;
    5. the contribution-ID sequence number from the Selection Service;
    6. the justification string (as unconverted Markdown content).

      Problems

Are there problems with this? Of course! The obvious one is a race condition; in high-use environments for popular articles, there's a virtual certainty that two proposals can attempt to select the same (or overlapping) content and be assigned the same contribution ID. We could add a locked-by/unlocked state to the Article and immediately persist a locked-by-proposer entity to the Article Repository on entry, and an unlocked one on completion, but that simply adds two persistence calls to the workflow, which are prime opportunities for race conditions themselves. At some point well before 1.0, we're going to have to rethink this.

And One More Thing…

Remember that edit-contribution proposals by the author of an Article are always immediately accepted; we need to think up the least hackish yet sufficiently rapid-to-implement way to accomplish this.

jdickey commented 8 years ago

Another interesting bit of our current design is that the decision on what type of Contribution object to create (and therefore later save) is made by the repository. Look at Prolog::UseCases::ProposeEditContribution#updated_contribution:

      def updated_contribution
        @contribution ||= contribution_repo.create form_object.to_h
      end

We dump the form object's attributes as a Hash, shovel them to the Contribution repository's #create method, and let it figure out what to do.

Is that the best, purest approach? Likely not; better might be some intermediate object that exists because it knows the difference between a Proposed and Accepted Contribution in this context and just Does The Right Thing. The argument for the current approach, however, is that the repository class, and very possibly only that class' #create method, knows what an EditContribution::Proposed, EditContribution::Accepted, or EditContribution::WhateverElse is. That sort of conceptual containment can be a Very Good Thing, rescuing us from too much haphazard knowledge scattered about the system.

tl;dr There's no "second happy path" for successful creation of a Contribution by the Article Author; all the create-proposal logic is exactly the same as for an arbitrary other Member. If anyone can point out cases where that's not the case, we're certainly willing to be corrected — but we seriously doubt that we will be.

jdickey commented 8 years ago

Now that we've cleared that up (see Commit 42ce558), all that's left is handling the known possible failure modes and, oh yeah, considering the known issues with the current implementation.

mitpaladin commented 8 years ago

Once we take Markdown out of the picture, does the cross-block Edit Contribution constraint still apply?

jdickey commented 8 years ago

Taking "Markdown out of the picture" says that we trust the user to produce valid, well-formed HTML as a result of her proposed contribution. If the markup produced by replacing the selection with the proposed replacement yields invalid HTML, the proposal will be rejected (preferably at the edit stage, where it'll simply redisplay the UI with errors reported). Definitely not 1.0-quality work; HTML and casual users coexist as peacefully as petrol under pressure and a roaring fire.

mitpaladin commented 8 years ago

Actually, the question above was meant to confirm that the decision to defer Rule 6 above "Contributions affecting multiple sequential paragraphs will be disallowed, requiring individual Proposals for each paragraph" was not based on Markdown or interpretation of blank line separation as different paragraphs.

jdickey commented 8 years ago

No; that should better be phrased as

If the contribution as entered by the Member, when replacing the selected original content, produces invalid HTML markup, then entry of the proposal will not be accepted. In an interactive UI such as a Web environment, the Member will be prompted to enter a corrected, valid proposal.

Does that cover it?