TheProlog / prolog-use_cases

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

[WIP] Feature strategy and planning. #1

Open jdickey opened 8 years ago

jdickey commented 8 years ago

As described in two Wiki pages in the prolog_core repo (Getting to 0.5 and Architectural Rabbit Hole Avoidance Attempt No. 769), this Gem sets out the basics of how we're going to get from here (for an arbitrary value of here) to April Fools' Day.

Gem Strategy

Paraphrasing ARAA 769:

  1. Use cases are developed as single (public) classes within individual modules within Prolog::UseCases, which is initially developed as a monolithic Gem (one Gem contains all use case implementations). As new use cases are implemented, the patch-level release number of the Gem (starting from 0.1.0, then 0.1.1, and so on) is incremented.
  2. When an existing use case is modified, its code is extracted from the main Gem into a new Gem; let's assume that we're talking about the "Propose No-Op Contribution" use case, so a logical Gem name might be prolog-use_cases-propose_noop. That new Gem would start its life (with the bug fix) as version 0.1.0, which would be listed as a dependency of the main prolog-use_cases Gem. This Gem would have its minor version number bumped (e.g., from 0.1.27 to 0.2.0 per SemVer.
  3. If a specific use case's Gem includes changes significant enough to warrant a minor or major (breaking change) version bump, then all Gems dependent on it should have their respective version numbers bumped to the same degree.
  4. Immediately prior to the public release of the first application built using these Gems (prolog_core, prolog-use_cases, et al), each of these Gems shall have their version numbers bumped to 1.0.0, so that the application may be linked against "production" dependencies.

    More Process Specifics

When starting development of a new use case, open a new issue for that use case, and tag it with the feature label. In the opening comment, mention this issue by number, so GitHub will auto-generate a link for it here. This might not completely eliminate the need for a ginormous checklist, but it will at least defer it.

User-Eye View

Reproducing that section of Getting to 0.5 for reference:

From a user perspective, it's going to take being able to:

  1. view the landing page, with existing articles, styling, and navigation links;
  2. sign up as a new member;
  3. log in, create a new article, and submit it for publication;
  4. see that new article in the newest-article list shown on the landing page while still logged in as the article's author;
  5. log out;
  6. see that new article in the newest-article list on the landing page, before having logged in;
  7. log in as a different member than the one who just published a new article;
  8. see that new article in the newest-article list in the landing page after logging in (as a second member);
  9. view the article page for the newest article;
  10. designate any single contiguous subset of the content of that article as the target of a Contribution proposal;
  11. view the UI for proposing a contribution, indicating the designated content as the target of the proposal;
  12. enter alternate content and an optional justification for an edit proposal;
  13. submit the new proposal after entering it validly;
  14. abort the proposal process before submitting it, removing the designation of the target content;
  15. view the article page for the target article, seeing that the content designated earlier is the target of an open proposal but is still presented in its original form;
  16. from that article page, viewing the content and metadata of the open proposal;
  17. repeat the previous two steps while logged in as a different member, and while not being logged in;
  18. log in as the author of an article to which a contribution has been proposed, and be notified of that proposal;
  19. while logged in as that author, viewing the article page and select a contribution proposal as the target of a response;
  20. after designating a proposed contribution, responding affirmatively to that proposal, optionally adding a free-form content response;
  21. after designating a proposed contribution, responding negatively to that proposal, optionally adding a free-form content response;
  22. view the article page for the subject article after accepting an edit contribution, and seeing the accepted content in place of the original selection;
  23. view the article page for the subject article, seeing that the designated or replaced content is the target of a proposal which has been responded to;
  24. log in as a proposer of a contribution which has not yet been responded to, and be notified that the proposal has not yet been responded to;
  25. log in as a proposer of a contribution which has been responded to, and be notified that the proposal has been responded to;
  26. view the article page for an article to which the logged-in user had previously proposed a contribution since responded to, and seeing the result of that response reflected in the article content;
  27. view the article page for an article to which the logged-in user had previously proposed a contribution since responded to, and seeing any content response entered by the article author, separately from or distinct from the (updated) article content;
  28. regardless of login state, view a summary list of registered members;
  29. regardless of login state, view a page describing a specific member, and see a summary list of contributions that member has proposed, including the response status of each (not yet responded to; affirmative response; negative response).

and, bringing up the rear,

  1. enter an explanation for a challenge proposal;
  2. enter a (free-text) query for a query proposal

which can be deferred to a post-0.5 release without undue pain/wasted effort, as they are simply variations on by-then-existing items.

Oh, By The Way...

When reading those "user-eye view" requirements, bear in mind that much, if not most, of the verbiage describes user interface and other delivery-system artefacts, that the use cases remain categorically unaware of. For instance, the very first use case from a non-UI-centric standpoint might have been phrased as

  1. Aggregate and return a collection of all the Article entities in the system which the current user is permitted to read.

This includes some concepts that either haven't been defined yet (permissions?) or which identify parameters that must be passed into the use case's command function. What's a "current user" when the person viewing the page hasn't yet authenticated to the system? We've just identified the need for a Guest User.

jdickey commented 8 years ago

Rethinking From the Underground Up

We just got back from reimplementing prolog_core to its new-and-for-now-shiny 0.2.0 release, making extensive use of Wisper rather than injecting dependencies directly. That seems a good and useful strategy to apply here.

Specifically, our approach to hexagonal architecture led us to envision a use-case class for a "landing page" to look something like

module Prolog
  module UseCases
    class CreateOverallSummary
      def initialize(current_user:, repo:)
        # ...
      end

      def call
        # ...
      end
    end # class Prolog::UseCases::CreateOberallSummary
  end
end

The "repo" being injected into #initialize would have been the Article repository, which would serve as a persistence interface to a set of Article instances, each of which would have an embedded User entity for its author, as was implemented in PrologCore::Article 0.1.0's Article entity.

Prolog::Core 0.2.0, in contrast, makes use of Wisper messages like :query_article_by_title to get information on a particular article. (We can see right now that we'll need an 0.2.1 release which adds query_all_articles to produce a collection of Article instances.)

Against prolog_core 0.2.x, we'd probably want to use an even simpler public interface for our first use-case class:

module Prolog
  module UseCases
    class CreateOverallSummary
      def call
        # ...
      end
    end # class Prolog::UseCases::CreateOberallSummary
  end
end

No explicit initialiser is needed to pass in the "current user" and "repo" parameters; when they're needed, they'll be queried for by Wisper messages. The key is going to be keeping the Wisper interface small, efficient and well-documented as it grows.

Future use cases similarly would "ask the world" for their outside collaborators rather than injecting them explicitly. We gain most of the benefit of the original, clean, hexagonal architecture without relying on concrete interface classes that must then be mocked and nested clumsily during testing and in live code.

EDIT

Actually, even better; there's no need yet for an 0.2.1 release because we're simply adding a new requirement to the persistent-storage interface _which isn't part of prolog_core directly_; it's just made use of (and should be documented as such somewhere). prolog_core no longer defines a "Repository" interface; it simply defines its interactions with *a persistent-storage provider.* That was easy :relieved:

jdickey commented 8 years ago

We've been tearing down the list of "User-Eye View"-listed features, until we're confronted with the absolute need to define how we're going to present and store Article content. See Issue #16.

jdickey commented 8 years ago

"User-Eye View" items 11, 12, and 14 are UI details wrapped around Item 13, "submit the new proposal after entering it validly". Whereas Meldd 1.0 will have at least three different types of proposal (for Edit, Challenge, and Inquiry Contributions), Meldd 0.5 will support only Edit Contributions. to be implemented in a new ProposeEditContribution use case that will first appear in Gem release 0.6.0.