FYI – I posted Mike's nice summary to this page<https://wiki.openmrs.org/x/G4GxAQ>on the wiki and added a comment to cover some outstanding issues, including those brought up by Win & Steve. Anyone interested can watch that page (I've already added a few watchers). If you think of any additional issues/questions that need to be addressed in coming up with a "final" lit of requirements for logic 2.0, please add your comment(s) to the bottom of the page <https://wiki.openmrs.org/x/G4GxAQ>.
We'll discuss logic again on a design call in a couple weeks. Cheers, -Burke On Thu, Nov 17, 2011 at 8:34 AM, Nyoman Ribeka <[email protected]> wrote: > To chip in: > > I would rather us to have something like: > > - EvaluationParameter instead of Map<String, Object> as the rule > evaluation parameter. > - EvaluationResult instead Map<Integer, Result>. > > Definitely need to do another design call. > > On Wed, Nov 16, 2011 at 5:47 PM, Darius Jazayeri > <[email protected]> wrote: > > Perhaps we should revisit this on the design call in 2 weeks? > > -Darius > > > > On Wed, Nov 16, 2011 at 2:14 PM, Michael Seaton <[email protected]> wrote: > >> > >> Hi all, > >> > >> Thanks to everyone who participated in this call today - I think we > made a > >> lot of progress. Here is a summary of what we were able to produce > (full > >> etherpad notes here): > >> > >> Requirements/Goals > >> > >> Existing logic engine can be implemented as an optional module without > too > >> much trouble. > >> A shared Rule interface > >> > >> Rules provide a method to evaluate within a context + parameters > >> > >> A shared Result interface > >> > >> Result declares it's type explicitly > >> Provides a mechanism for consumers to easily distinguish between & use > >> lists vs. single values > >> > >> Provides an easy way to coerce results between different types and > between > >> lists vs. single value > >> A shared LogicContext interface within which rules are evaluated > >> Centralized token registration by providing token, rule ID, provider, > and > >> configuration (unique across providers) > >> Support for parameters. > >> Caching is deferred to rule evaluators for now > >> > >> Skeleton Interfaces / Implementations > >> > >> Rule: > >> > >> interface Rule { > >> public Set<RuleParameterInfo> getParameterList(); // TODO: We didn't > >> discuss this interface, but we did agree that rules need to support > >> parameters > >> } > >> > >> interface RuleEvaluator { > >> boolean canEvaluate(Rule rule); // TODO: This might be better > >> implemented through annotations. Needs further discussion > >> Map<Integer, Result> evaluate(Cohort, Rule, Map<String, Object>, > >> RuleContext); // TODO: We probably want to wrap Map<Integer, Result> in > a > >> proper class > >> } > >> > >> interface RuleProvider { > >> Rule getRuleInstance(String ruleName, String extraConfig); // ruleName > >> could be anything the provider wants. might typically be a classname. > >> } > >> > >> interface / implementation RuleService/RuleServiceImpl { > >> RuleContext createContext(); // Ensures that RuleContext can be > >> overridden as needed > >> void registerToken(String token, RuleProvider provider, String > ruleName, > >> String extraConfig); > >> void unregisterToken(String token, RuleProvider provider); // provider > >> for safety > >> > >> (the below methods might also have implementations without RuleContext > >> and/or without params for convenience) > >> Result evaluate(Integer ptId, String token, Map<String, Object> > params, > >> RuleContext context) { > >> // create a cohort with a single patient, call the evaluate method > on > >> the cohort, return the result for that patient > >> } > >> Map<Integer, Result> evaluate(Cohort c, String token, Map<String, > >> Object> params, RuleContext context) { > >> // find the appropriate RuleProvider, ruleName, extraConfig for the > >> given token; get the Rule from the RuleProvider passing in the ruleName > and > >> extraConfig; call evaluate method on the Rule > >> } > >> Result evaluate(Integer ptId, Rule rule, Map<String, Object> params, > >> RuleContext context) { > >> // construct a cohort of one; get the evaluator for the passed rule; > >> call evaluate passing in the cohort, params and the context; return the > >> result for the patient > >> } > >> Map<Integer, Result> evaluate(Cohort c, Rule rule, Map<String, Object> > >> params, RuleContext context) { > >> // get the evaluator for the passed rule; call evaluate passing in > the > >> cohort, params and the context; return the result > >> } > >> } > >> > >> interface RuleContext { > >> // TODO: Figure out whether this has indexDate, any caching, etc. > >> } > >> > >> Result: > >> > >> interface Result { > >> public Object getValue(); > >> public Date getDatetime(); // Needs more discussion if this is > >> appropriate on the base interface (eg. what to do for Lists) > >> public String formatAsString(); > >> } > >> > >> class NumericResult { > >> private Double result; > >> private Date datetime; > >> public Object getValue() { return result; } > >> public Date getDatetime() { return datetime; } > >> } > >> > >> class ListResult { > >> private List<Result> results; > >> public Object getValue() { return results; } > >> public Date getDatetime() { // Not sure what to do here. Get the > >> datetime of the first result? Maybe this method doesn't belong > >> } > >> > >> class ObsResult { > >> private Obs obs; > >> public getValue() { return obs; } > >> public Date getDatetime() { return obs.getObsDatetime(); } > >> } > >> > >> Use of Result: > >> > >> For coercing / converting Results to scalars for use in comparisons etc, > >> for example: > >> if (eval("BMI") > 23) { ... }, we discussed a few possible approaches: > >> (TODO: Decide on one) > >> > >> 1. adding methods like "asDouble()", "asDate()", "asString()", > >> "asBoolean()" to the Result interface (as we have now) > >> 2. Add single method to Result like: eval("BMI").coerce(Double.class) > > >> 23 > >> 3. Add utility method like: LogicUtil.toDouble(eval("BMI")) > 23 > >> 4. Add utility method like: LogicUtil.coerce(eval("BMI"), > Double.class) > > >> 23 > >> 5. Add a variety of converters like: new > >> DoubleConverter().convert(eval("BMI")) > 23 > >> > >> Benefit of #5 is that it is cleaner than a massive utility method with > >> lots of conditional logic, and that it allows modules to plug new > converters > >> into the framework as needed. It might look something like this: > >> > >> interface ResultConverter<T> { > >> public T convert(Result); > >> } > >> > >> class DoubleConverter<Double> { > >> public Double convert(Result result) { return > >> Double.valueOf(result.toString()); } > >> } > >> > >> > >> We ran out of time before we could really discuss next steps on all of > >> this. Should we carve out time in another design forum in December? > >> > >> Thanks, > >> Mike > >> > >> > >> > >> > >> On 11/16/2011 03:23 AM, Ben Wolfe wrote: > >> > >> Lets plan on having a discussion today about this on the design call at > >> 2pm. We can write up the solutions (and new questions) for Tammy to > read > >> offline. > >> > >> Ben > >> > >> On Tue, Nov 15, 2011 at 2:21 PM, Dugan, Tammy Marie <[email protected]> > >> wrote: > >>> > >>> I am on maternity leave and have my hands pretty full with a two week > old > >>> and a two year old. If you have any specific questions, please feel > free to > >>> email me. Email is a lot easier for me right now than phone. > >>> > >>> Thanks, > >>> > >>> Tammy Dugan > >>> > >>> Quoting Michael Seaton <[email protected]>: > >>> > >>>> Yes, I will be there and looking forward to talking about this. > >>>> > >>>> Mike > >>>> > >>>> From: [email protected] [mailto:[email protected]] On Behalf Of Ben Wolfe > >>>> Sent: Tuesday, November 15, 2011 3:14 AM > >>>> To: [email protected] > >>>> Subject: Re: [OPENMRS-DEV] The future of Logic > >>>> > >>>> Would it be possible for folks to join tomorrow the 16th at 2pm EST? > >>>> I fear that some people will be missing next Wednesday due to the US > >>>> holiday on Thursday the 24th. > >>>> > >>>> Tammy? Dave? Mike? Darius? Burke? Roger? Win? Beuller? > >>>> > >>>> https://wiki.openmrs.org/display/RES/Design+Forum > >>>> > >>>> Ben > >>>> On Mon, Nov 14, 2011 at 8:55 PM, Burke Mamlin > >>>> <[email protected]<mailto:[email protected]>> wrote: > >>>> Can we enumerate what we want from the simplified logic service? > >>>> > >>>> * Existing logic engine can be implemented as an optional module > >>>> without too much trouble. > >>>> * Strongly instead of loosely typed results. > >>>> * Support for parameters. > >>>> * ... > >>>> Do we want to support an index date (i.e., avoid assuming today's > date)? > >>>> > >>>> Don't we want to forego tokens? Or are we assuming that consumers of > >>>> logic know which rule provider to consult (which may or may not use > >>>> tokens)? If the consumer needs to know which provider to consult and > >>>> that provider will presumably be handling the evaluation, then what > >>>> purpose does the logic service serve? Alternatively, rule providers > >>>> could be registered with the logic service and then consumers could > >>>> come to the logic service with a token (i.e., not need to know the > >>>> provider). > >>>> > >>>> I'm assuming that we'll defer caching & criteria implementations to > >>>> the various forms of logic (at least for now). > >>>> > >>>> What's the purpose of LogicContext now? In the original design, > >>>> LogicContext served a few purposes: (1) proxy for all data requests > >>>> by rules, (2) provide a context for evaluations ? index date & > >>>> parameters ? that could be stacked for recursion, (3) context for > >>>> caching results, and (4) an abstraction so that the same rule could > >>>> be run against a patient or cohort. If we aren't using logic context > >>>> for any of these, do we need to maintain LogicContext at this stage? > >>>> > >>>> Looking forward to the design call. > >>>> > >>>> Cheers, > >>>> > >>>> -Burke > >>>> > >>>> On Wed, Nov 9, 2011 at 10:23 PM, Michael Seaton > >>>> <[email protected]<mailto:[email protected]>> wrote: > >>>> Hi all, > >>>> > >>>> I wanted to pick up a thread on the future of Logic that we spent > >>>> some time discussing during the Developers Forum on October > >>>> 27<https://wiki.openmrs.org/x/5oamAQ>. > >>>> > >>>> The overall consensus on the call was that "Logic is too complicated. > >>>> We wish there were a simpler implementation, that were easier to > >>>> adapt to individual needs. We wish it were more rigorously tested, > >>>> including performance testing". > >>>> > >>>> Anyone that cares about preserving Logic as it currently exists, or > >>>> wants to see it change in a specific way, please read further > >>>> > >>>> Specific users of Logic have communicated the following needs: > >>>> > >>>> * Tammy and her team require more control over the current Logic > >>>> implementation, and better testing around it, so that future upgrades > >>>> do not cause serious bugs and performance degradation > >>>> * Win and Tammy need implementations of Logic that are optimized > >>>> for running lots of rules for individual patients at a time > >>>> * Mike needs an implementation of Logic that is optimized for > >>>> running a single rule for lots of patients at a time as well > >>>> * Mike wants to be able to choose to not use the existing Logic > >>>> implementation in favor of an implementation provided by the > >>>> Reporting module > >>>> To accomplish this, the following high-level refactoring steps are > >>>> being considered: > >>>> > >>>> * Reduce and simplify the number of interfaces and interface > >>>> methods that Logic exposes in OpenMRS core > >>>> * De-couple the existing Logic Module in such a way that it is one > >>>> of many possible "Rule Providers" that can plug into this > >>>> lighter-weight core framework > >>>> * Remove, if possible and practical, the need to have a "required" > >>>> Logic module installed > >>>> Specifically, we are considering an approach that would reduce the > >>>> core Logic interfaces to something like: > >>>> interface LogicContext; > >>>> > >>>> interface Result; (classes DateResult, NumberResult, ListResult...) > >>>> > >>>> interface Rule { > >>>> Set<RuleParameterInfo> getParameterInfo(); > >>>> Class<? extends Result> getReturnType(); > >>>> Result evaluate(Integer patientId, Map<String, Object> parameters, > >>>> LogicContext context); > >>>> } > >>>> > >>>> interface LogicService { > >>>> public Result evaluate(Rule rule, Patient patient, Map<String, > >>>> Object> parameters, LogicContext context); > >>>> public Map<Integer, Result> evaluate(Rule rule, Cohort cohort, > >>>> Map<String, Object> parameters, LogicContext context); > >>>> } > >>>> I would like for this to spur the following potential activities: > >>>> > >>>> * Give anyone who has not yet been aware of these discussions, or > >>>> who does not agree with this approach, an opportunity to weigh in and > >>>> get involved in the process > >>>> * Make a plan to put this topic onto one or more future Design > >>>> Forum calls, in order to agree upon the revised design, make tickets, > >>>> and establish an owner for moving it forward. > >>>> * Publicize when this Design Forum will occur so that interested > >>>> parties can be involved as desired > >>>> Thanks! > >>>> Mike > >>>> > >>>> > >>>> ________________________________ > >>>> Click here to > >>>> > >>>> unsubscribe<mailto:[email protected] > ?body=SIGNOFF%20openmrs-devel-l> > >>>> from OpenMRS Developers' mailing > >>>> list > >>>> > >>>> ________________________________ > >>>> Click here to > >>>> > >>>> unsubscribe<mailto:[email protected] > ?body=SIGNOFF%20openmrs-devel-l> > >>>> from OpenMRS Developers' mailing > >>>> list > >>>> > >>>> ________________________________ > >>>> Click here to > >>>> > >>>> unsubscribe<mailto:[email protected] > ?body=SIGNOFF%20openmrs-devel-l> > >>>> from OpenMRS Developers' mailing > >>>> list > >>>> > >>>> _________________________________________ > >>>> > >>>> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail > >>>> to [email protected] with "SIGNOFF openmrs-devel-l" in the > >>>> body (not the subject) of your e-mail. > >>>> > >>>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l] > >>>> > >>> > >>> _________________________________________ > >>> > >>> To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to > >>> [email protected] with "SIGNOFF openmrs-devel-l" in the > body (not > >>> the subject) of your e-mail. > >>> > >>> [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l] > >> > >> ________________________________ > >> Click here to unsubscribe from OpenMRS Developers' mailing list > >> > >> ________________________________ > >> Click here to unsubscribe from OpenMRS Developers' mailing list > > > > ________________________________ > > Click here to unsubscribe from OpenMRS Developers' mailing list > > > > -- > Thanks, > > Nyoman Ribeka > > _________________________________________ > > To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to > [email protected] with "SIGNOFF openmrs-devel-l" in the body > (not the subject) of your e-mail. > > [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l] > > _________________________________________ To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to [email protected] with "SIGNOFF openmrs-devel-l" in the body (not the subject) of your e-mail. [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

