Tuesday, November 19, 2013

Dart 1.0

Dart released 1.0, but it looks like some political gesture, it seems having nothing to do with the quality of the system.
There are still many basic unresolved problems, like mirror, await etc.
Essentially certain power user cannot use Dart at this level of quality.
Also editor sometimes causing suppressing internal error, and showing bad error messages.
Anyway, they would have needed to show some progress for public, that would be the only the reason for they have released 1.0.

Also the last minutes announcement of deprecation web-component and replacing it by unproven polymer is also nonsenses move.
If it is experimental nature, it is better to avoid pushing such technology. This also would have come from political decision to provide some sort of solution to support component based web development which dart supposed to address. But like JavaScript does not provide such framework, Dart actually does not have to provide such 'solution'. It doesn't have to be a part of Dart release at all.

Since Dart is new language, it may take sometime to understand the best way to utilize new language features for component based web developments.
These thing may be delegated to communities, and wait to see emerging new solutions.

Also in general, if we develop with JavaScript, we don't see any fragment of HTML. So such focus on HTML file on Polymer looks very much old fashioned approach.
It will be an obstacle for utilizing full language capabilities to design component based library.

So I feel a lot of questionable thing for Dart right now.
But if I wait Dart 2.0, it may be something I expected as 1.0.
So just I may need to wait another year to mature.

At least, if Dart does not provide proper synchronization feature for server side application, it seems a waste of time to develop something on server side right now.

Thursday, November 7, 2013

bad choice for Server side Dart?

I investigated the isolate to see if it can support waiting another isolate to finish, then continue the rest of job.
But Dart's concurrency is really restrictive, there seems no way to achieve this.
Considering many poor design of asynchronity of current Dart, server side Dart seems not good option right now.

Maybe I may try 'Go' as well..
Rob pike and Thompson who are behind Go had been working on this area.

http://doc.cat-v.org/plan_9/4th_edition/papers/sleep

Of cause Java is still OK..
If we define some mapping tool from Dart annotation to JPA annotation, it is still not so bad option.But even we use java in server side, lazy evaluation on Dart client is still not possible. As long as the expected job in client side is low, this may not be a big problem though..

Tuesday, November 5, 2013

video:Dart Today and Beyond with Google's Gilad Bracha

Dart Today and Beyond with Google's Gilad Bracha 

This video was taken a year ago, just after m1 release. It explains some of the idea behind Dart , so it is worth watching.  

in that video, he was telling he want to reduce asynchronity. in fact, mirror dropped future from the api, but io lib added much more async api. so totally dart increased a lot of asynchronity.

Anyway, he looks kind of language proper guy, it would be better to couple with  another guy with broader application development experiences for leading language design so that it won't go to romanticist's dream world.

 

Monday, November 4, 2013

Dart's Future evaluation order

Dart's future evaluation order is not so clear from source code, so I tested using sample code.
Also this test when stream evaluation happen. listen method also started after the end of main code line and after running all futures. this means listen may create future, but not at the time listen is invoked.

import "dart:async";

main() {
    Stream stream = new Stream.periodic(const Duration(milliseconds: 1), (x) => x);
    int receivedCount = 0;
    var subscription;
    print("<1>");
    int a = 0;
    new Future.value(1).then((v) {
      print(">> 1 v: ${v}");
      new Future.value(10).then((v) {
        print(">> 10 v: ${v}");
        
      });
    });
    
    bool finished = false;
    subscription = stream.listen((data) {
      //expect(data, receivedCount);
      receivedCount++;
      print("receivedCount: ${receivedCount}");
      finished = true;
      new Future.value(30).then((v) {
        print(">> 30 v: ${v}");
        
      });
      if (receivedCount == 5) subscription.cancel();
      
    });
    new Future.value(2).then((v) {
      print(">> 2 v: ${v}");
      new Future.value(20).then((v) {
        print(">> 20 v: ${v}");
        
      });
    });
    /*
    while (!finished) {
      
    }
    */
    print("<2>");
}


<1>
<2>
>> 1 v: 1
>> 2 v: 2
>> 10 v: 10
>> 20 v: 20
receivedCount: 1
receivedCount: 2
>> 30 v: 30
>> 30 v: 30
receivedCount: 3
receivedCount: 4
>> 30 v: 30
>> 30 v: 30
receivedCount: 5
>> 30 v: 30

If we add while loop:

import "dart:async";

main() {
    Stream stream = new Stream.periodic(const Duration(milliseconds: 1), (x) => x);
    int receivedCount = 0;
    var subscription;
    print("<1>");
    int a = 0;
    new Future.value(1).then((v) {
      print(">> 1 v: ${v}");
      new Future.value(10).then((v) {
        print(">> 10 v: ${v}");
        
      });
    });
    
    bool finished = false;
    subscription = stream.listen((data) {
      //expect(data, receivedCount);
      receivedCount++;
      print("receivedCount: ${receivedCount}");
      finished = true;
      new Future.value(30).then((v) {
        print(">> 30 v: ${v}");
        
      });
      if (receivedCount == 5) subscription.cancel();
      
    });
    new Future.value(2).then((v) {
      print(">> 2 v: ${v}");
      new Future.value(20).then((v) {
        print(">> 20 v: ${v}");
        
      });
    });

    while (!finished) {
      
    }

    print("<2>");
}

The output will be just <1>.
<1>


These things means future evaluation will happen only main code line was ended.
And the order of future evaluation is the order it was created.

Friday, November 1, 2013

Big restriction: Dart's Stream does not support synchronous mode

When I tried to support getter property of another referenced entity, I came to recognize that it is NOT possible in current Dart.

This is ridiculous restriction.
And it was supported until M3 deprecated the previous synchronous Stream classes.
I think this is pretty much nutty stupid decision.
It must have been done by young limited experienced people who can believe such single bullet approach can solve every thing. Probably it may solve every thing they knew.
That is the problem of the lack of experience.

Whole Dart development somehow has resemblance to early stage of Java around 1995. Probably many of developer of Dart does not remember.

Java has been introduced as a language for Applet. And marketed as such, then it was mainly used for server side. The main reason for the adaption can be contributed several reasons. one aspect is it was free, and it provided a lot of library. Compared to C/C++, these are big difference. Also from language point of view, Java supported class, object oriented features and garbage collection.(and lack of pointer). So compared to C/C++, it was significantly high level language, it was good enough for the most of server side application.

(but it was really backward step compared to other advanced moduler languages, like Mesa/Cedar, Ada, Modula-2, etc. but they never became known to wider audiences, that may have helped Java to proliferated also..)

For Dart,  the current marketing Buz is for browser side language(to replace JavaScript (eventually..)), but as a language, it has also unique feature integrating object/functional idioms in a single language.
Although there are many of such languages(Like Scala), there are no other language which can support both browser and server side.

I think  these two aspects are quite important. Although current marketing focus is in browser side, like polymer, dart:io etc, but it will be used more on server side.
Since the combination of object/functional style is very powerful, once people realized how it is productive, they will never want to write huge amount of equivalent codes in Java. Also sharing the same class from both sides is big plus.

Bottom line is  Dart should target such server side development in much higher priority. Right now, many people seems not developing significant application, they will not complain, but eventually, more people start using Dart, this kind of biased API design will bring a lot of complaints.

Thursday, October 31, 2013

ORMapping in Dart (Part2)

I started the implementation of Object Relational Mapping tool like JPA in Dart.
The approach follows the outline I posted before.
But there were several differences.

One is basically I decided to go with minimalist approach.
Always it creates more problem in the end if we rely on many outer resources.
In this case, I just went with my own Postgres scheme generation, sql generation etc.
In fact, it is not so complicated.
And for this kind of tool, we don't need much feature of SQL.

The reason I chose Postgres was the Dart lib for Postgres had BSD license.
MySQL driver in Dart was GPL. But Postgres may be better choice than MySQL technically.

Right now, it can generate DB scheme from annotated class definition, and it support CRUD*create/read(query) /update/delete operations.
persistence object has several level of state.

remaining things are:
  1.  how to support reference and relation. These are actually subtle issue inherent for many ORM system.
    Since if we fetch all associated objects, it may need to copy whole db content.
    So it is important to minimize fetching data.
  2.  how to support relationship. Even though we define relationship as List or reference, but, in particular, the List representation are sort of useless.
    Conceptually, relationship don't have to be represented as entity properties.
    In JPA, it also supports separate query, so it is better not to use List attribute.
 For reference, if we uses strict evaluation, it may end up fetching all data, so we must use lazy evaluation for fetching reference.
There is  some interesting issue for this, since most of postgres API is using Future, how can we avoid asynchronous operation for getting referenced object?
We may need to introduce some operator to change Future to synchronous call by  monitoring the asynchronous call was finished or not.

Also in order to support lazy evaluation, some fieldstate object associated to the filed may need to keep entity id in it, and if the filed is accessed,  it need to fetch from db and assign to the actual object field.
These are a bit complicated, but relatively straightforward.

But the relationship, List field is quite bad.
Essentially if there are large number of associated entities, such whole set is useless. If it cannot be used in general situation, it is better not to use it.

Actually, I created this binding scheme, so I can also change the type to represent relationship.
So instead of List<B>, I may use Rel<A, B>, Ref<A>. and Rel<A, B> class will provide query methods. and it will not maintains fetched objects. In fact, query and managing entity objects for transactional scoped are contradicting requirement.
Often fetched object may not have to be managed(read only).
So it will be useful to provide separate fetching mode so that it will reduce managed fetched objects.

For creating one/many to many relationship, it may be better to reflect such change immediately in database, and do not keep such info in memory unless corresponding object is managed in memory(such case, it need to reflect both sides). this simplify fetching data from database consistently.

class A {
  @OneToMany(mappegBy:"a")
  Rel<A, B> bs;

}
class B {
  @ManyToOne
  Ref<A> a;
}

Following is the test program.

@Table(name: "A")
class A extends Persistence {
    @Id()
    @Basic(optional: false)
    @Column(name: "id")
    String _id;

    @Basic(optional: false)
    @Column(name: "i")
    int _i;
    
    @ManyToOne()
    B _b;

    @OneToMany(mappedBy: "a")
    List<C> _cs;
    
    String get id => get(const Symbol("id"));
    void set id(String v)=>set(const Symbol("id"), v);

    int get i => get(const Symbol("i"));
    void set i(int v)=>set(const Symbol("i"), v);

    B get b => get(const Symbol("b"));
    void set b(B v)=>set(const Symbol("b"), v);

    List<C> get cs => get(const Symbol("cs"));
    void set cs(List<C> v)=>set(const Symbol("cs"), v);
    
    String toString() => "A(id: ${id}, i: ${i}, b: ${b}, cs: ${cs})";
}

@Table(name: "B")
class B extends Persistence {
  @Id()
  @Basic(optional: false)
  @Column(name: "id")
  String _id;

  @Basic(optional: false)
  @Column(name: "s")
  String _s;
  
  @ManyToOne()
  A _a;

  @OneToMany(mappedBy: "a")
  List<C> _cs;
  
  String get id => get(const Symbol("id"));
  void set id(String v)=>set(const Symbol("id"), v);

  String get s => get(const Symbol("s"));
  void set s(String v)=>set(const Symbol("s"), v);

  A get a => get(const Symbol("a"));
  void set a(A v)=>set(const Symbol("a"), v);

  List<C> get cs => get(const Symbol("cs"));
  void set cs(List<C> v)=>set(const Symbol("cs"), v);
  
  String toString() => "B(id: ${id}, s: ${s})";
}

@Table(name: "C")
class C extends Persistence {
  @Id()
  @Basic(optional: false)
  @Column(name: "id")
  String _id;

  @Basic(optional: false)
  @Column(name: "i")
  int _i;
  
  @ManyToOne()
  B _b;

  @OneToMany(mappedBy: "a")
  List<C> _cs;
  
  String get id => get(const Symbol("id"));
  void set id(String v)=>set(const Symbol("id"), v);

  int get i => get(const Symbol("i"));
  void set i(int v)=>set(const Symbol("i"), v);

  B get b => get(const Symbol("b"));
  void set b(B v)=>set(const Symbol("b"), v);

  List<C> get cs => get(const Symbol("cs"));
  void set cs(List<C> v)=>set(const Symbol("cs"), v);
  
  String toString() => "C(id: ${id}, s: ${i})";
}

Future<int> test0(_) =>
    persistenceMgr.deleteTables([A, B, C]).then((int n) {
      print("deleteTables done. ${n}");
    });

Future<int> test1(_) => persistenceMgr.createTables([B, C, A]);

Future<bool> test2(_) {
  A a1 = new A()
    ..managed = true
    ..id = "a1"
    ..i = 10;
  
  A a2 = new A()
    ..managed = true
        ..id = "a2"
        ..i = 20;
 
  return persistenceMgr.commit();
}

Future<bool> test3(_) {
  IClassMirror cmirror = ClassMirrorFactory.reflectClass(A);
  Selector<A> selector = new Selector<A>(cmirror);
  return selector.query(where: "id = 'a1'")
    .then((A a){
      print("==>> a: ${a}");
      a.i = 100;
      return persistenceMgr.commit();
    })
    .then((_)=>selector.queryAll())
    .then((List<A> as){
      print("==>> as: ${as}");
      return true;
    });
}

Future test4a(_) {
  IClassMirror cmirror = ClassMirrorFactory.reflectClass(A);
  Selector<A> selector = new Selector<A>(cmirror);
  return selector.query(where: "id = 'a2'")
    .then((A a){
      print("1a==>> a: ${a}");
      if (a == null) {
        return false;
      }
      print("1b==>> a: ${a}");
      return a.delete();
    })
    .then((ok) {
      if (!ok) {
        return false;
      }
      return selector.query(where: "id = 'a1'")
      .then((A a){
        print("2==>> a: ${a}");
      });    
    });
}

Future test4b(_) {
  IClassMirror cmirror = ClassMirrorFactory.reflectClass(A);
  Selector<A> selector = new Selector<A>(cmirror);
  return selector.queryAll()
  .then((List<A> as)=>Future.forEach(as, (A a)=>a.delete()))
  .then((ok) => selector.query(where: "id = 'a1'"))
  .then((A a){
      print("2==>> a: ${a}");
      //a.delete();
   });
}

void main() {
  
  // register reflection factory
  initClassMirrorFactory();
  
  setDBAdaptor(new PostgresDBAdaptor());
  
  test1(null).then(test2).then(test3).then(test4b).then(test0).then((_) { print(">>> completed."); });
}
And this is the output.

==>createTables: CREATE TABLE B (
id varchar(256) primary key,
s varchar(256),
a varchar(256));

CREATE TABLE C (
id varchar(256) primary key,
i int,
b varchar(256));

CREATE TABLE A (
id varchar(256) primary key,
i int,
b varchar(256));

ALTER TABLE B ADD CONSTRAINT b_a_fkey FOREIGN KEY (a) REFERENCES A(id);
ALTER TABLE C ADD CONSTRAINT c_b_fkey FOREIGN KEY (b) REFERENCES B(id);
ALTER TABLE A ADD CONSTRAINT a_b_fkey FOREIGN KEY (b) REFERENCES B(id);

>> createInsert: INSERT INTO A (id, i, b) VALUES
( E'a1' , 10, null);
>> createInsert: INSERT INTO A (id, i, b) VALUES
( E'a2' , 20, null);
>> DBTable.query: SELECT id, i, b FROM A WHERE id = 'a1'
==>> a: A(id: a1, i: 10, b: null, cs: null)
>> createUpdate: UPDATE A SET id =  E'a1' , i = 10, b = null WHERE id =  E'a1' ;
>> createUpdate: UPDATE A SET id =  E'a2' , i = 20, b = null WHERE id =  E'a2' ;
>> createUpdate: UPDATE A SET id =  E'a1' , i = 100, b = null WHERE id =  E'a1' ;
>> DBTable.queryAll: SELECT id, i, b FROM A
==>> as: [A(id: a2, i: 20, b: null, cs: null), A(id: a1, i: 100, b: null, cs: null)]
>> DBTable.queryAll: SELECT id, i, b FROM A
>> createDelete: DELETE FROM A WHERE id =  E'a2' ;
>> createDelete: DELETE FROM A WHERE id =  E'a1' ;
>> DBTable.query: SELECT id, i, b FROM A WHERE id = 'a1'
2==>> a: null
==>deleteTables: ALTER TABLE A DROP CONSTRAINT a_b_fkey;
ALTER TABLE B DROP CONSTRAINT b_a_fkey;
ALTER TABLE C DROP CONSTRAINT c_b_fkey;
DROP TABLE A, B, C;

deleteTables done. null
>>> completed.

Saturday, October 26, 2013

Several Dart bugs I encountered => found how to avoid the problem

The problem I reported in the previous post was really annoying.
It caused bunch of strange problems and there was no clue for the real reason why import fail, why 'a is A' does not have expected value.
The actual fix was to change return type of get listeners from List<ComponnetAction> to List<RowAction>. these types are defined by typedefs. After this change, everything got normal .
  
typedef void ComponentAction(Event event, Component c);
typedef void RowAction(Event event, Row row);

// this caused the problem:
//List<ComponentAction> get listeners => table.row_listeners;

// shoudl use this instead.
List<RowAction> get listeners => table.row_listeners;

Such a subtle difference caused a lot of strange problems without any meaningful error messages. Actually, the main bug may be the failed handling of ComponentAction, but even if it cannot be used there, Dart should report such error so that it can be corrected easily. 

I was a bit feeling not to use Dart if the quality of system is such low.
In facts, there were other bugs which is quite disappointing to know  the level of quality control of bug fixes.

1) wrong type of methods for reflect(new List<A>()).type,

{
    ClassMirror cmirr = reflect(new List()).type;
    print(">>0@@ cmirr.reflectedType: ${cmirr.reflectedType}");
    cmirr.getters.forEach((k, MethodMirror md){
      Type tm = null;
      if (md.returnType is ClassMirror) {
        tm = (md.returnType as ClassMirror).reflectedType;
        print(">>1@@ k: ${k}, tm: ${tm}");
      } else if (md.returnType is TypeVariableMirror) {
        TypeVariableMirror tvmirr = md.returnType;
        print(">>2@@ tvmirr: ${tvmirr.runtimeType}");
      }
    });
  }

The result of executing this is:

>>0@@ cmirr.reflectedType: List<A>
>>1@@ k: Symbol("length"), tm: int
>>1@@ k: Symbol("_capacity@0x36924d72"), tm: int
>>1@@ k: Symbol("first"), tm: A
>>1@@ k: Symbol("last"), tm: A
>>1@@ k: Symbol("single"), tm: A
>>1@@ k: Symbol("isEmpty"), tm: bool
>>1@@ k: Symbol("isNotEmpty"), tm: bool
>>1@@ k: Symbol("reversed"), tm: Iterable<T>
>>1@@ k: Symbol("iterator"), tm: Iterator<T> 

This issue was discussed with Gilad, and he told me Google team is working on this issue. At the time, first 's type was not substituted to A, this issues was definitely fixed.
But the type parameter of the generic type of  reversed an iterator is still T, not substituted to A.
These type related implementation is quite basic, must have highest quality.
Although they fixed, the way to fix without addressing all problem was very sloppy.
I reported this issue, but they looks not setting higher priority.

2) Another case was dart2js bug, which crashed dart2js. For this issue I observed the same problem after they 'fixed' the issue, but  they could not fix all the cases. Although the response time and fixed time was good, related issued should be checked when one issue was reported.(take more time to examine related issues rather than fixing fast)

3) the reflectClass behavior is really bad. and alternative way to get runtimeType though instantiating object is just absurd.
These things indicate the design of mirror is not well guided.
They may be busy for many stuff, but some basic language core thing should be implemented in highest quality.

My impression is Dart team is too much focusing on Polymer.
Often such politically overselling approach is proved to be misguiding/useless in the end, but it will waste a lot of people's energy and time.