2sic / connect.koi

Koi enables .net CMS-components to work perfectly with different CSS-Frameworks determined by the layout / theme.
MIT License
6 stars 0 forks source link

RFC (Request for Comment): Polymorphism #12

Open iJungleboy opened 5 years ago

iJungleboy commented 5 years ago

1. The Problem I'm trying to solve

Imagine if your theme/app would exist in many shapes (morphs). And you could dynamically switch between them based on a simple factor like a cookie.

Example for Polymorph: Open-Heart-Surgery

Imagine if your theme (or app or template or whatever) had a default.ascx which was empty except for an if-else statement, checking what edition (Morph) the user should see (default would be live) and would then load that edition from a subfolder (usually from /live). Now the developer wants to make some changes on live, copies the full live to staging and starts to work. Thanks to a cookie only he sees that edition, everybody else still sees live. So even if something breaks as he's working, only he sees it. When he's done, he can let the customer check it (with a special url or cookie) and when everything is good, simply copy staging back to live.

Full list of Scenarios This should Cover

  1. Open-Heart-Surgery
    Often you have a running installation and you would like to make some changes and work in production, without hurting the live output. In such cases it would be awesome if the new and old theme (or app) would run side-by-side, and changes to the new one wouldn't affect the existing version. Only you would see the changed edition.

  2. Customer Preview Similar scenario: a new output (theme/app) is prepared and on production, but only your customer should see it, but she should see the full experience, so it shouldn't be a URL parameter, but something that stays as she browses the site.

  3. Live Staging
    Sometimes you want to test changes for a few days on an internal team, but on the real live environment.

  4. A/B Testing Imagine having multiple editions of the same theme/app, and based on some factor (random, targeting group, etc.) you want to do A/B testing.

2. Things that can vary

I believe there are different levels of detail at which we want to solve this.

  1. Full component/theme/app switch
    in this case, the configuration would make the entire theme/app run in a different mode.

  2. Fragment Switch
    In this case, the configuration would make parts of the theme/app run in a different mode - for example, a different logo, a different CSS or just a different JS include.

  3. API Switch
    In some cases - like JS applications, the JS will stay the same, but should use a different endpoint version (again for testing, dev, A/B).

  4. Configuration Switch
    In some cases the same code/template should run, but just using a different configuration.

3. Aspects of an Amazing, Full Solution

The following things should IMHO be solved to make this amazing.

  1. Configuration - Ideally using JSON
    Configuration will probably be possible through code, but in most cases a JSON will be the better solution, because otherwise modifying this configuration (to add another Morph/Edition) could already cause bugs/downtime on the live system. If we rely on a config file (and the runtime is very error-resistant) we'll avoid downtime.

  2. Simple Consumer API to use in C# webparts, razor
    Basically the user of Polymorph should have something like if(Polymorph.Edition == "staging") {...} and similar mechanisms, to easily use this. There's a lot more to this which I'll explain more below.

  3. Simple consumer API to use in JavaScript
    Similar to the C# some code-snippets or NPM modules for JS would increase productivity.

  4. Simple Edition-Detection Mechanisms
    I guess in many cases the edition-change will be configured through the cookie, but ideally there are a set of Detectors, like a CookieDetection, UserProfileDetection, TimeDetection etc. This would allow generic extension of "why should a user see a certain edition".

  5. Fully Automated Integration into DNN
    Ideally by convention, the system would pick up a koi.json containing such configuration fully automatically - similar to the css-framework detection mechanisms.

  6. Set-user-edition Helpers
    In certain cases (like cookie) it needs a bit of code to set this edition. This could be done by the developer on a case-by-case (like manually set the cookie) but ideally there would be some helpers. This is low priority though.

Current implementation (2018-11-17)

So far I (iJungleboy) created a set of code which does most of this (proof-of-concept), + unit-test-code to verify that the detections behave as expected. I'm still missing the JSON bits, more detectors (only Cookie is implemented ATM) and the fully automatic DNN integration. The code is in the branch Polymorph.

RFC

I need your feedback regarding "am I solving a real problem", "does it sound like a good idea" or "am I barking up the wrong tree" and "would you do something better".

Thx!

Some Code Examples for the "User"

Razor which chooses a sub-view depending on the auto-detected edition

@RenderPage(@Polymorph.Edition + "/_gallery.cshtml")

Razor which switches between colors based on auto-detected edition

<link href="@Polymorph.Part("design")/StyleSheet.css" rel="stylesheet" type="text/css">

JSON Config Simple Example

This example assumes the all default mechanisms, which is cookie detection using the default cookie name, based on portal and skin name:

{
  "polymorph": {
    "names": "live,staging"
  }
}

JSON Config More Control (Work in progress)

This example assumes the all default mechanisms, but different parts which have more different bits

{
  "polymorph": {
    "live": {
      "folder": "live/",
      "logo": "blue.jpg",
     }, 
    "staging": {
      "folder": "staging/",
      "logo": "red.jpg"
     }
  }
}

JSON Config Detection Type (Work in progress)

This example assumes that both a special cookie, or a user-property defines what should be shown.

{
  "polymorph": {
    "detection": {
      "cookie": "simulate-membership",
      "userprofile": {
        "field": "Member",
        "map": [
          "customer": "premium"
        ]
      }
    },
    "default": {
      "folder": "default/",
     }, 
    "premium": {
      "folder": "premium/",
     }
  }
}
Tychodewaard commented 5 years ago

Sounds like a great idea! And if it would cover 1 more scenario (and I think it could be) it would full the gap between DNN and commercial software. I mean personalization and/or marketing automation. I was triggered by the cookie-concept. First stage: if I know what cookie to look for, I can offer a different user experience (look&feel, order etc) than visitors without that cookie. Second stage: cookie management / rule management. An interface for marketeers that would allow to add/edit rule like 'Person who visited page A, should get module B on the homepage'

Not trying to slip in features which are monster projects in itself but confirming my enthusiasm :-)

iJungleboy commented 5 years ago

@Tychodewaard absolutely agree. That would be a separate project/product, but totally agree - that's a real use case. Could be triggered through cookie, or user-profile etc.