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]

Reply via email to