Friday, December 28, 2012

Looking for JavaScript grid/table component

Recently I was looking for grid/table component in Javascript which is would be open-source, flexible enough and not tied heavily to some large framework. I'd like to share with you some brief notes of that research. I like SlickGrid more so I've explored it more.

SlickGrid

  • https://github.com/mleibman/SlickGrid/wiki
  • License: MIT
  • PROs:
    • Supports huge datasets via virtual scrolling. Looks like it's the only grid that supports horizontal virtual scrolling.  
    • Supports trees
    • Data provider API - allows model creation. Transparent update of model.
    • Long text editor support: double-clicick the cell and edit its content in a pop-up
    • Automatic shortening of long content
    • Supports cell horizontal spanning
    • Hosted on GitHub and actively accepts pull requests
  • CONs:
    • Poor documentation
    • No built-in dropdown editor
    • No fixed columns
    • Doesn't support cell vertical spanning.
    • Column width specified only in pixels - no percents. However, with grid.autosizeColumns() columns can be proportionally resized
    • Width adjusting is weird. Involves JavaScript handling, not just CSS.
    • Always displaying editor (for example, dropdown box) is not easy. It requires asyncPostRenderer
    • Mobile devices officially not supported (and not planned to support ever), but on my Android 4 tablet most functionality work OK. And there is a fork with support of mobile devices: https://github.com/reebalazs/SlickGrid-touch  

EditableGrid

jqGrid

  • http://www.trirand.com/blog/
  • License: MIT
  • PROs:
    • Rich feature set: trees, subtables etc
    • Mobile beta available
    • Supports column hierarchy, though API for this is a nightmare.
    • Hosted on GitHub, sometimes accept pull request
  • CONs:
    • No data model
    • Inconvinient configuration (for example, proprietary format for dropdown lists instead of using JS object)
    • Some plugins (for example, table to grid converter) pollute global namespace

DataTables

  • http://www.datatables.net/
  • License: GPLv2, BSD
  • PROs
    • Lightweight
  • CONs
    • Editability requires plugin
    • No data model
    • No tree support
    • Plugin for changing column width is buggy

Wednesday, December 19, 2012

Antipatterns: initialization after usage

I've seen such problem fiew times and I'm going to describe it as an antipattern - let's call it "initialization after usage". It could sound a bit like Captain Obvious, but isn't it typical for some pattern/antipattern catalogs? :)

The problem:

There is an object which has some fields initialized in one place, some in completely different place, and in the meantime the object is used somewhere. So when using the object it's not clear if its fields are completely initialized or not.

As an example - let's see Java object:

public class Person {
  private String firstName;
  private String lastName;
  private String postalIndex;
  private String city;
  public Person(String firstName, String lastName, String postalIndex) {
//apply values here
 }
//getters and setters go here
}
Its fields firstName, lastName and postalIndex are initialized immediately. The city is searched a lot later in some database by index and gets assigned later. In the meantime Person object can be displayed on some page, saved to DB etc., and during these operations nobody can be sure if city field is available or not.

Notice that problem doesn't apply to lazy-loaded or lazy-initialized fields as they can be retrieved on demand.
I'm also not talking about objects where some fields may not be applicable due to domain-specific concerns.
I'm talking just about fields that are set by some external systems that can't be controlled by the object itself and which always make sense from business point of view. Like in the example - if Person has a postalIndex then there's certainly some city assotiated with it (all right, could as well be village).

Possible solutions:

  1. Initialize all the fields immediately. However this may not be the option sometimes due to costly initialization of data which aren't used in all the cases.
  2. Factor out initialization to some utility method of another class. This is possible only if object contain enough information to build missing part, possibly with using external services.
  3. Move out fields to a wrapping class which maintains link to original object. Then in the second phase of initialization wrapped class instance would be created and used whereever additional fields needed. But this could be an overkill in some cases. A rather contrieved example could be like this (here it's definitely overkill, but it shows an approach):
  4. 
    public class PersonAddress {
      private Person person;
      private String city;
    //constructors, getters, setters go here
    }
    
  5. Modification of point 3 - subclass from original class