JavaScript libraries in the same space (UI widgets) use two different approaches for instantiating components:

  1. Literal strings to specify types, and inlining as much as possible, for example:

    var oTable = webix.ui({
        view: "datatable",
        columns: [
            { id: "rank",   header: "", css:"rank", width: 50 },
            { id: "title",  header: "Film title", width: 200 },
            { id: "year",   header: "Released", width: 80 },
            { id: "votes",  header: "Votes", width: 100 }
        ],
        autoheight: true,
        autowidth: true,
        data: tableData
    });
    
  2. A complex class hierarchy and passing objects instead of strings:

    var oTable = new sap.ui.table.Table({
        title: "Movies",
    });
    
    
    oTable.addColumn(new sap.ui.table.Column({
        label: new sap.ui.commons.Label({text: "Film title"}),
        template: new sap.ui.commons.TextField().bindProperty("value", "title"),
        sortProperty: "title",
        filterProperty: "title",
        width: "200px"
    }));
    
    oTable.addColumn(new sap.ui.table.Column({
        label: new sap.ui.commons.Label({text: "Released"}),
        template: new sap.ui.commons.TextField().bindProperty("value", "released"),
        sortProperty: "released",
        filterProperty: "released",
        width: "80px"
    }));
    
    oTable.addColumn(new sap.ui.table.Column({
        label: new sap.ui.commons.Label({text: "Votes"}),
        template: new sap.ui.commons.TextField().bindProperty("value", "votes"),
        sortProperty: "votes",
        filterProperty: "votes",
        width: "100px"
    }));
    
    // add the other columns...
    
    var oModel = new sap.ui.model.json.JSONModel();
    oModel.setData({modelData: tableData});
    oTable.setModel(oModel);
    oTable.bindRows("/modelData");
    

In both cases, tableData is a plain JSON array, so no differences there:

[
    { id: 1, title: "Shawshank Redemption", year: 1994, votes: 678790, rank: 1 },
    { id: 2, title: "The Godfather", year: 1972, votes: 511495, rank: 2 }
]

What are the advantages and disadvantages of these two approaches, in terms of learning curve, maintainability, avoidance of antipatterns, reusability, and other software engineering best practices?

有帮助吗?

解决方案

The inline declaration can be easier to read and maintain in simple cases, easier for non-programmer types to understand and maintain, but more difficult to extend or manage dynamic concerns. i.e. in your example, if you want certain columns to only be used in certain circumstances, things start to get ugly and the simplicity and readability are negated in a hurry.

The second approach has a higher learning curve, will make less sense to non-programmers, but makes dynamic concerns straightforward, provides transparency into what is actually happening, and tends to make a greater degree of flexibility and extensibility possible.

An ideal UI library would provide both types of options.

其他提示

The latter one is easier to extend and customize, while separating concerns both for the user of the library and the author. For example, if for some reason it made sense in your application, you could very easily create different columns inside different functions. For another example, the user could create their own nifty MyLabel and MyTemplate components without the library having to know anything about it.

The former is much simpler to read, write, and maintain, at the expense of being more difficult to customize and extend. In other words, you're largely stuck with what you're given. This is a very good thing if what you're given is sufficient for your requirements. It's a very bad thing otherwise.

It boils down to the YAGNI principle. If you're pretty sure you will only ever need the standard configurations and their provided customizations, the complexity of the second approach isn't buying you anything.

许可以下: CC-BY-SA归因
scroll top