Showing posts with label Monitor. Show all posts
Showing posts with label Monitor. Show all posts

Friday, October 18, 2013

Zen Style: Semantics Oriented, Contextual Programming

The title of this blog is suggestive.
Like a monk in Zen temple, a programmer should not work hard for low level thing, but just try hard to identify the essence of the problem, then the rest will follow magically with no effort.

Declarative programming style is something common to this style. we don't care some procedural steps, which are very low level, but just concentrate on the relationship.
But declarative style itself are still not powerful enough. We must be able to extend the declarative constraint enforcing mechanism in the programming. It is sort of reflective approach, the goal of this approach is to create autonomous intelligent program driven by knowledge and semantics, context, rules etc. Essentially the output is not cumming just from the written code, but the as a synthesis of machine intelligence and the directive programming which will be short in size.

Normally such kind of programming were not easy. But these days, reflection library can be used to assist such programming style. Annotation is actually very under evaluated naming, but it has big potential. we can change ordinarily programming behavior outside of written code using such annotation information and specific library using reflection.

The code I developed for GUI is such an example.
Essentially the goal of the approach is to support declarative GUI development.
Some structural/layout related coding are defined with no procedural codes.

And procedural code which are associated with how the GUI will respond to user input etc are cleanly separated from these GUI code.

In normal program, we cannot change the timing of setting some property values etc, but using reflection library, it can implicitly set these values based on annotation, field type, context class type etc.
So we may think of this as semantics driven program, or contextual program. We can improve programming productivity by delegating certain annoying patterns to such library.
This is quite close to changing our language itself. So that is the essence of reflectivity.

These things could have been done in Java, but Java's generics were poor at runtime compared to Dart, Dart has more potential utilizing generic's type information. This is important difference. Java could not know itself at runtime, but Dart can. One interesting example was the CouchDB json parser which will use provided applied generic type information to determine sub json's type information as posted before.
Another reason may come from just the basic verboseness of Java language. There are so many restrictions, like anonymous class, even something can be done better, in the faces of such a bloated code, the gain would have reduced a lot.
That would have been discouraging some effort. AOP activities were something to be mentioned, but I have never seen such AOP application for GUI library in Java.
The cascading syntax is very small syntactic addition, but it has a big potential to eliminate all html  based development. Also many future, higher order functional make code very short.
Only in such an environment, these new approach will shine.

Here is a new revised version of sample code I posted before.
in the first part of code are dedicated to GUI presentation. Also the idea of this approach is to assist component style web development which combine the behavioral logic in the component, so such sub components are also declared as final field property with annotations.
From this annotation information and the declaring class, ie, CRUDView as subclass of Component class, when the object is instantiated, the super class Component will start analysing the annotation
 through reflection library, and setting corresponding property in the subcomponents(like label value in the annotation).

class CRUDView extends Component {
  static const String CRUD = "g_cud_view";
  DivElement _content;
  DivElement _actions;

  @UI_Table()
  final Table<Expense> table = new Table<Expense>();
  
  @UI_Form()
  final Form<Expense> form = new Form<Expense>();
 
  @UI_Button(label: "Load")
  final ButtonComp loadButtom = new ButtonComp();
  
  @UI_Button(label: "New")
  final ButtonComp newButtom = new ButtonComp();
  
  @UI_Button(label: "Save")
  final ButtonComp saveButtom = new ButtonComp();
  
  @UI_Button(label: "Delete")
  final ButtonComp deleteButtom = new ButtonComp();
  
  Element _updateElement(Element elm) => 
      elm
      ..classes.add("section")
      ..nodes.add(new Element.html("<header class='section'>${table.modelType} Table</header>"))
      ..nodes.add(_content = new Element.tag("div")
        ..classes.add("g_crud_view_table")
        ..nodes.add(table.element))
      ..nodes.add(_actions = new Element.tag("div")
        ..id = "actions"
        ..classes.add("section")
        ..nodes.add(loadButtom.element)
        ..nodes.add(newButtom.element)
        ..nodes.add(saveButtom.element)
        ..nodes.add(deleteButtom.element))
      ..nodes.add(form.element)
      ..nodes.add(new Element.html("<footer class='section' id='footer'></footer>"));
 
This part defines more behavioral aspect of program.It defines how application respond to the user input etc. these are nothing to do with GUI. We may still reduce direct association of the action with each GUI components if we introduce Monitored fields as I have done in namebudge application.

  // this should be injected by AOP approach from out side..
  ICouchDbClientDAO<Expense> dao = new CouchDbClientDAO<Expense>(Expense, sampleJsonMapper);
  
  CRUDView() {
    this.classes.add(CRUD);
    Type _Expense = Expense;
    table
      ..modelType = _Expense
      ..formatFunctionMap[ExpenseType] = ExpenseTypeComp.format;
    
    form
      ..modelType = _Expense
      ..inputFactoryCache.specialInputCompMap[ExpenseType] = ExpenseTypeComp.inputCompFactory
      ..inputFactoryCache.adhocCompMap['detail'] = 'textarea'; // should be moved to annottaion!
    
    loadButtom.onClick((_) {
      dao.fetchAll().then((List<Expense> es){
        table.load(es);
        //print('loaded data from db; ${es}');
      });
    });
    
    newButtom.onClick((_) {
      Expense e = form.create();
      _changeButtonState(true, false, true);
      //print('new in db');
    });
    
    saveButtom.onClick((_) {
      if (form.e != null) {
        Expense e = form.save();
        if (e == null) {
          //print('form is empty, click New, or select arow before Save.');
          return;
        }
        // this part is tricky..
        // since e is fill from InputText, when it is empty text, it will assign "" instead of null..
        if (e.id == "") e.id = null;
        if (e.rev == "") e.rev = null;
        ((e.id == null)?dao.insert(e):dao.update(e)).then((Expense e0){
          e.id = e0.id;
          e.rev = e0.rev;
          table.addOrUpdate(e);
          _changeButtonState(false, true, true);
          //print('updated in db e0: ${sampleJsonMapper.toJson(e0)}, e: ${sampleJsonMapper.toJson(e)}');
        });
      }
    });
    
    deleteButtom.onClick((_) {
      Expense e = form.e;
      if (e != null) {
        dao.delete(e).then((ok){
          if (ok) {
            form.delete();
            table.delete(e);
            _changeButtonState(false, true, true);
            //print('deleted in db');
          }
        });
      }
    });
    _changeButtonState(false, true, true);
    
    table.row_listeners.add((ev, row){
      Expense e = row.e;
      form.load(e);
      _changeButtonState(false, false, false);
    });
  }
  
  void _changeButtonState(bool new_disable, bool save_disable, bool delete_disable) {
    newButtom.node.disabled = new_disable;
    saveButtom.node.disabled = save_disable;
    deleteButtom.node.disabled = delete_disable; 
  }
  
  Element createElement() => addSubComponents0(newElem("div"));
  
  Element update() => addSubComponents0(initElem());
      
  Element addSubComponents0(Element elm) => addListeners(_updateElement(elm));
}

This is one application of annotation and reflection, the other application I introduced was Monitor. Monitor is useful to separate GUI interaction and actual semantics.It may be considered as more efficient version of Event driven code.
Monitor is achieving similar goal as Observable does in Ploymer, but it is general purpose class, which may be used for OR mapped entity classes to support lazy loading etc.

Anyway, I will need to describe them in more detail later.

Several Dart bugs I encountered

I refactored the codes so that new implicit delayed UI component initialization can be used.
And I found a few restriction and bugs of Dart.

  1. I needed to define default constructor without taking optional values. this is required to create UI component object without taking any parameters, in particular, parent value can not be passed at the property declaration time.
    So I first tried to use optional parameter '{}', but when I combined with Monitor suing Mixen, I found it does not allow to use mixin with a class in which the default constructor has optional parameters.
  2. So I first try to avoid changing existing constructors(although it was not bad idea to change so, but it needed more changes), I moved Monitor class to be used as super class of the top level Component class. Then what I saw during execution was very strange problem. There was annotation class called Monitored, and reflection will get the instance through metadata, and in order to identify proper annotation class, it uses 'is" operator.
    What happened was that 'obj is Monitored' was not true even obj's runtimeType is Monitored!
    This kind of things happen in Java when different class loaders are used to instantiate an object, but in Dart, we will not manipulate class loading, so quite strange. So I basically abandoned this approach, and took the mixin approach again.(this was OK, since this approach would be more narrowly scoped, and appropriate for the purpose).
  3. after all required changes are finished, and could run properly with DartVM mode, I tested this app with static mirror library which are to be used for javascript mode.
    If I run this with Dart VM, it run properly, but if we use javascript mode, the dart2js compiler crashed.
    Actually the message of the compiler problem was the same as a bug I reported before, and it was quickly fixed(but  I did not verify it for myself.) So I thought this would be fixed if I update the dart sdk(r28355) since the fixed version was older that that revision.
    But I found it was not fixed. Actually there were some workaround to fix previous problem using variable instead of direct type value, but this issue was not fixed by this workaround. So this may indeed be another bug.
  4. Another problem I faced was the getting ClasssMirror of generic type. In order to provide javascript mode, portal mirror need to provide basic reflection features from concrete classes.
    For instance it need to use generic type's type(Type). right now, in order to have right type value, namely the type where parameters are substituted is only to go through instantiating the object.
    but new implicit delayed UI component initialization will call reflection library when  the default constructor is called. So this introduced infinite loop. Actually these kind of problems were I anticipated when I knew the current  way to get Type. Essentially this is very dirty trick. Also some case, this will case unnecessary resource usage as well. I avoided this problem using dirty trick to use static variable not to call the sub component initialization(although the global variable is defined as private, so it is not so bad way..).
  5. This issue also made clear the current constructor has a lot of restriction, lack of flexibility. The simple way to avoid this in Java was to define another constructor to take such flag to disable calling sub component initialization. But in Dart, if we define one constructor, there is no other way to define another.   So I was forced to use global variable.

Tuesday, October 15, 2013

Reflective Interceptor, Monitor in Dart (Part 2)

Here is a sample code using Monitor. This sample was created from dart-tutorials-samples-Master/web/namebadge so that we can compare the differences.

In order to have getter/setter interception, we need to use Mixin with Monitor or extend Monitor.
We need to define monitored private fields, and public getter/setter corresponding to these private annotated fields.
The public getter/setter will call inherited methods get/set defined in Monitor.
This part is sort of mechanical, and may be a bit annoying to repeat, but it is better than using  code generator.
Also we need to define actions to be triggered when setter/getter are called using addSetListener, addGetListner.

When we use setter for private variables, like '_male = true;', then no actions are triggered. but if we use public setter, like 'male = true; ' then, it will trigger the registered actions.

Compared the both code size, Polymer looks better. But this approach is simpler and flexible. we don't have to rely on some convention between Polymer html and dart class bound to the polymer element.
Also there is no need to maintain two files system closely associated with each others. That will become maintenance night mare.

Since this is normal dart code, much more complicated things can be done without struggling with the restriction posed by Polymer.

I don't like ugly JSP style mixing of control in html file.
If we use cascading style to build html Element, the size of code is comparable(may be smaller?) to HTML. And we can do much more flexible thing in dart.

One advantage of using HTML is it uses less dart code. the code size can be smaller than program based one.
but if we develop dynamic web site, such a difference may be ignorable.

And we want to take generic web component approach like Form, Table, Polymer style approach does not work.

This is using my portable_mirror lib,  it works using both dart VM using dart:mirrors lib, and javascript mode with static stubs.

import 'dart:html';
import 'dart:math';

import "../../gui_component/lib/monitor_lib.dart";
import "package:gui_component/gui_component_lib.dart";

class NameBadge extends Component with Monitor {
  static const String APP = "g_namebage";
  TextInputComp textInput;
  ButtonComp button;
  RadioComp maleRadio;
  RadioComp femaleRadio;
  
  Element _div0;
  Element _initDiv0(Element e) => _div0 = e;

  @Monitored()
  String _badgename = 'Bob';
  @Monitored()
  bool _male = false;
  @Monitored()
  bool _female = true;

  String get badgename => get(const Symbol('badgename'));
  void set badgename(String v) => set(const Symbol('badgename'), v);
  
  bool get male => get(const Symbol('male'));
  void set male(bool v) => set(const Symbol('male'), v);
  
  bool get female => get(const Symbol('female'));
  void set female(bool v) => set(const Symbol('female'), v);
  
  NameBadge(Component parent): super(parent, const[APP]) {
    this.textInput = new TextInputComp(this, "Enter New Name:", String);
    this.button = new ButtonComp(this, "Generate pirate name", (e) { badgename = pirateName(); });
    this.maleRadio = new RadioComp(this, "Male", "male", _male, name:"maleOrFemale")..onClick((_, comp){ male = true; });
    this.femaleRadio = new RadioComp(this, "Female", "female", _female, name:"maleOrFemale")..onClick((_, comp){ female = true; });
    
    addSetListener(const Symbol("badgename"), (NameBadge target, String old_value, String new_value){
      textInput.value = new_value;
      _div0.text = new_value;
    });
    addSetListener(const Symbol("male"), (NameBadge target, bool old_value, bool new_value){
      if (old_value == new_value) return;
      if (_male && _female) female = false;
    });
    addSetListener(const Symbol("female"), (NameBadge target, bool old_value, bool new_value){
      if (old_value == new_value) return;
      if (_female && _male) male = false;
    });
  }

  String pirateName() => (_female)?new PirateName.female().name:new PirateName.male().name;
  
  Element createElement() => addSubComponents0(newElem("div"));
  
  Element update() => addSubComponents0(initElem());
  
  Element addSubComponents0(Element elm) => addListeners(
      elm
        ..nodes.add(
            new Element.div()
              ..classes.add("entry")
              ..nodes.add(textInput.element)
              ..nodes.add(button.element)
              ..nodes.add(maleRadio.element)
              ..nodes.add(femaleRadio.element))
        ..nodes.add(
            new Element.div()
              ..classes.add("outer")
              ..nodes.add(new Element.div()..classes.add('boilerplate')..text = 'Hi! My name is')
              ..nodes.add(_initDiv0(new Element.div()..classes.add('name')..text = _badgename))));
}

Following codes are from original dart-tutorials-samples-Master/web/namebadge.
In polymer version, we need to write both dart program and corresponding polymer html files. So this dart part is short compared to my monitor based implementation, but if we compare with dart and html, the code size difference will become less.

import 'dart:html';
import 'dart:math';
import 'package:polymer/polymer.dart';

@CustomTag('name-badge')
class NameBadge extends PolymerElement with ObservableMixin {
  @observable String badgename = 'Bob';
  @observable bool female = true;
  @observable bool male = false;
    
  NameBadge() {
    bindProperty(this, const Symbol('female'), () {
        if (female) {
          male = false;
        }
        notifyProperty(this, const Symbol('name'));
      });
    bindProperty(this, const Symbol('male'), () {
        if (male) {
          female = false;
        }
        notifyProperty(this, const Symbol('name'));
      });
  }

  void pirateName(Event event, var detail, Node target) {
    if (female) {
      badgename = new PirateName.female().name;
    } else {
      badgename = new PirateName.male().name;
    }
  }
}

<polymer-element name="name-badge">
  <template>
    <style>
    .entry {
      padding-bottom: 20pt;
    }
    .outer {
      border: 2px solid brown;
      border-radius: 1em;
      background: red;
      font-size: 20pt;
      width: 12em;
      height: 7em;
      text-align: center;
    }
    .boilerplate {
      color: white;
      font-family: sans-serif;
      padding: 0.5em;
    }
    .name {
      color: black;
      background: white;
      font-family: "Marker Felt", cursive;
      font-size: 45pt;
      padding-top: 0.5em;
      padding-bottom: 0.3em;
    }
    </style>
    <div class="entry">
      <label for="newName">Enter New Name:</label>
      <input type="text" id="newName" value="{{badgename}}">
      <button on-click="pirateName">Generate pirate name</button>
      <input name="maleOrFemale" type="radio" value="male" checked={{male}}>Male
      <input name="maleOrFemale" type="radio" value="female" checked={{female}}>Female
    </div>
    <div class="outer">
      <div class="boilerplate">
        Hi! My name is
      </div>
      <div class="name">
        {{badgename}}
      </div>
    </div>
  </template>
  <script type="application/dart" src="name_badge_element.dart"></script>
</polymer-element>



Monday, October 14, 2013

Reflective Interceptor, Monitor in Dart (Part 1)

In GUI, persistent data programming, the interceptor for the field access is fundamental.
It can enhance the field access with additional behaviors.
It may trigger another action, or keep recording of some internal changes.
But these behaviors should be irrelevant for the caller of these getter/setter.

These things has been implemented as part of general AOP type injection mechanism like CGlib, asm etc, but these approach would not be possible in Dart,  and overkill for this limited range of interception (getter/setter).

Dart introduced @observable Observable mixin, but Observable class seems not general purpose class, but restricted to polymer html file.

So it is interesting to find an alternative way to support similar idea in more general setting,and apply it to my web-framework, gui-components library.

For this purpose, I created the Monitor class. for the name of the field annotation  to be monitored by Monitor class is 'Monitored'. This Monitor class can be used with mixin as well as subclassing, so any class can be changed to a Monitor class easily.