This is more a design question that a technical question, but since there is a tag called design-patterns
I think it makes sense.
My scenario is as follows: I have a CSV file, that I want to use to populate an object and then use that object for making an API call. So far so good.
The tricky part is that the CSV data could require some conversions before populating the object, and once the object is created and populated I want to edit some of those object properties.
The view and controller operations are going to be provided by angular and I have focused on the template stuff.
How is the object composed? Well, my idea is as follows:
- The result will be a hasmap of objects, where each object has a collection of fields which are also objects. This object represents a row, and each field a column.
- Each field will have a
value
property, this way angular can do it's two way data binding magic. It will have also a set of methods for querying and interacting with the object, like asking for the object class (ng-dirty
if it is required and empty), adding another element if it is a collection instead of a single value, and that kind of things.
- Each field will have a
To build this object I will proceed this way:
- First build a set of rules for parsing each column/field data.
- Each rule has a parser method that parses the data, and a constructor method, which returns the "field" object I mentioned above.
- The constructor calls the parser, which will parse the data and return a valid representation of that data. The constructor will then return an object field with the parser result as value and a set of method for interacting with that object.
- Rules are created using the ruleFactory function. This function receives the "type" of the field, if it is required (mandatory) or not, the constructor to use and an object for additional options such the parser to use and returns a rule.
Some constructors are built on top of other constructors. For example, the basic constructor is used by the arrayConstructor
, that extends the object the basic constructor returns and then returns it. The arrayConstructor
is used by the limitedValuesConstructor
and so on. If you did not noticed, some constructors falls back to a default parser if it is not defined.
My idea wish is that this is extensible, so if in the future if the format of the data changes, I just add another parser, or I update an existing parser. Same stuff for the constructors.
But, I feel that I'm going to complicated for this task, and I want your opinion about it. Another thing that scares me a lot is that I feel that this does not fit under any valid design pattern that I know. It is not prototypical, not classical, not a module pattern (closure) and I'm not familiar with composition, but I feel that this is not valid composition neither.
Below you can find the basic code inside a closure.
(function () {
function ruleFactory (type,required,constructor,options) {
constructor = constructor || basicConstructor;
var column = {
'type': type,
'required': required || false,
'parser': options && options.parser ,
'constructor': function (data) { return constructor.apply(column,[data,required,options])}
};
return column
}
function strParser (data){
if( typeof data === "string" ){
return data
} else if( data && data.toString){
return data.toString();
}
return ''
}
function arrParser (data){
if(!data){
return []
}
if( angular.isArray(data) ){
return data
}
return strParser(data).split(' ');
}
function basicConstructor (data,required) {
var parser = this.parser || strParser; //fallback to the most basic parser
var column = {};
column.value = parser(data);
column.getClass = function (){
if( required && ! this.value ){
return 'ng-dirty'
}
return ''
};
return column
}
function arrConstructor (data,required) {
this.parser = this.parser || arrParser; // default parser for this constructor
var column = basicConstructor.apply(this,arguments);
column.addValue = function (value) {
column.value.push(value);
}
column.getClass = function ( ) {
if ( column.value.length <= 0 && required ) {
return 'ng-dirty'
}
return ''
}
return column
}
})()
The "rules" object (or array or whatever you want) is built like this:
var rules = {
"someColName": ruleFactory('number',true), // true means required. Defaults to false
"someList" : ruleFactory('array',false,arrConstructor), //No parser defined, so fallbacks to default parser for arrConstructor
"otherList" : ruleFactory('array',false,arrConstructor, {parser:arrParser}) }
Any opinion / constructive criticism is very welcome.
Regards
Aucun commentaire:
Enregistrer un commentaire