-1

Working on a platform that currently has a CLI, but later will have a GUI.

Java.

Basically, currently has a Platform class that orchestrates the interaction of pluggable elements. Platform is a singleton.

There is a CLI class, which has Commands that can use the Platform and its plugins.

Sometimes the Commands employ Platform components (plugins) that require further user interaction (input and output). I am thinking of making a UI interface that Platform is configured with, and the components then make calls out to this to display and obtain input. An event driven solution.

Is that a valid design?

Is there something better?

I am trying to make an MVC style approach work in my head, but the problem is it seems to imply a lot of fore-knowledge in the CLI Commands (ie, the controllers), about the Platform components. That makes them tightly coupled, and I'd like to keep the commands as general as possible. That makes them easier for extenders to work on them, and makes fewer of them for the coming GUI development.

mtyson
  • 8,196
  • 16
  • 66
  • 106

1 Answers1

1

MVC pattern is useful to build the UI (be it CLI, GUI, web page, REST API or something totally different). For integration purposes, you'll want to use other patterns, for instance Facade.

Let's say you're building an ice cream machine. You have a platform interface:

package com.plaform.icecream;

public interface IceCreamMachine {
  public void measureCream(int milliLiters);
  public void measureCondensedMilk(int milliLiters);
  public void measureVanillaExtract(int tableSpoons);
  public void measureCacaoPowder(int tableSpoons);
  public void mixIngredients();
  public void freezeConcoction();
  public Object handOverExperimentResults();
}

Then you have your model class of MVC:

package com.cli.icecream.model;

public class Icecream {
  private int amount;
  private Flavour flavour;

  // getters, setters, toString, etc.
}

Flavours as enum:

package com.cli.icecream.model.values;

public enum Flavour {
  VANILLA, CHOCOLATE;
}

Controller:

package com.cli.icecream.controller;

public class IceCreamController {
  private IceCreamFacade serviceFacade;

  public IceCreamController(IceCreamFacade serviceFacade) {
    this.serviceFacade = serviceFacade;
  }

  public void handleShowingFlavours() {
    // ...
  }

  public IceCream handleOrderingIcecream(int balls, Flavour flavour) {
    // validations, etc.

    return serviceFacade.getIceCream(balls, flavour);
  }
}

Now the way to hide the actual details behind the product from the MVC, you can create a Facade that will integrate the two:

package com.cli.icecream.integration;

public interface IceCreamFacade {
  public IceCream getIceCream(int balls, Flavour flavour);
}

and:

package com.cli.icecream.integration;

public class IceCreamFacadeImpl {
   private IceCreamMachine iceCreamMachine;

   public IceCreaFacadeImpl(IceCreamMachine iceCreamMachine) {
     this.iceCreamMachine = iceCreamMachine;
   }

   public IceCream getIceCream(int balls, Flavour flavour) {
     int creamMl = ConversionUtil.calculateAmountOfCream(balls);
     int condensedMilkMl = ConversionUtil.calculateAmountOfCondensedMilk(balls);
     int flavourSubstanceTbsp = ConversionUtil.calculateAmountOfFlavourSubstance(balls);

     iceCreamMachine.measureCream(creamMl);
     iceCreamMachine.measureCondensedMilk(condensedMilkMl);

     switch (flavour) {
     case VANILLA:
       iceCreamMachine.measureVanillaExtract(flavourSubstanceTbsp);
       break;
     case CHOCOLATE:
       iceCreamMachine.measureCacaoPowder(flavourSubstanceTbsp);
       break;
     }

     mixIngredients();
     freezeConcoction();

     Object results = iceCreamMachine.handOverExperimentResults();

     return ConversionUtil.convertResultsToIceCream(results);
   }
}

This way the UI (MVC) consist of classes that are blissfully unaware of how the integrated platform works and vice versa, i.e. decoupled. As an added benefit, if either component changes its behaviour, all your logic to integrate the two are in one place, instead of splattered all over either application.

Community
  • 1
  • 1
t0mppa
  • 3,983
  • 5
  • 37
  • 48