User not logged in - login - register
Home Calendar Books School Tool Photo Gallery Message Boards Users Statistics Advertise Site Info
go to bottom | |
 Message Boards » » JavaScript devs, check me on this Page [1]  
FroshKiller
All American
51152 Posts
user info
edit post

I don't write a lot of JavaScript. A product I work on uses several JavaScript libraries for rendering fancy client-side controls of different types. We've been known to switch libraries. So what I'm doing is writing some initializer functions that wrap the libraries' initializers. That way, if we jump ship to some other plug-in for a control, I hopefully only have to change the definition of the adapter. Fine.

Most of these things seem to follow a pattern of taking a single parameter: an object with various fields for the options. For instance, one might take an object like this:

{ allowMultipleEntries: true, minimumLength: 3, maximumLength: 60, }


Some libraries have reasonable defaults, and others don't. Some require certain parameters to be declared outright, and others don't. To insulate myself from having to jump through a lot of hoops, I've adopted the pattern of my wrappers taking an optional additionalOptions object then using Object.assign to merge & overwrite an object with the specific library's defaults for our application.

So for instance, if I had some jQuery plug-in, I might have a wrapper for that control that looks like this:

function fancyControlWrapper(controlId, additionalOptions) {
//defaults for this plug-in
var options = {
allowMultipleEntries: true,
minimumLength: 3,
maximumLength: 60,
};

if (typeof additionalOptions == 'object') {
options = Object.assign(options, additionalOptions);
}

var baseControl = document.getElementById(controlId);
$(baseControl).fancyControlInitializer(options);
}


For older browsers, I include a polyfill for Object.assign.

Is this a sane pattern? I figure this allows me to override allowMultipleEntries, for example, without having to change a bunch of function calls in the future if a new plugin has different options or different names for analogous options. And I could set fields on the options object in the wrapper consistent with our conventions, so like if next release introduces a replacement for this control except their field for allowing multiple entries is just called multiple, I can just set options.multiple = additionalOptions.allowMultipleEntries or some shit and map them myself.

I mean, I know the general pattern of writing an adapter is sane, but is merging option objects like this a sane approach that I'll be glad I committed to?

[Edited on October 31, 2017 at 10:24 AM. Reason : ///]

10/31/2017 10:22:27 AM

wwwebsurfer
All American
10135 Posts
user info
edit post

This sounds like a bad situation. Code with more than a couple of libraries usually grows into an unmaintainable monstrosity and then questionable ideas like wrapping the wrappers come into play.

In theory, I don't see why what you're talking about wouldn't work.


If it was me, I'd probably pass in a name of what I was about to initialize in addition to the additionalOptions, then just put in an if statement to do the right one. That way you could set all your defaults in a common place, and only optionally override those defaults with additionalOptions.


Really it sounds like it's time to do some cleanup refactoring.

11/1/2017 11:39:58 PM

FroshKiller
All American
51152 Posts
user info
edit post

I guess it's a bad situation, but I don't feel the pain that much. The base application brings all that baggage, but I'm only working on a plug-in. That does mean that I don't have a lot of influence on when and what to clean up, though.

So you're saying add a parameter for the control type and have, like, a big switch statement? I don't think that really saves me any trouble. I still have to go replace the initializers, and there isn't really any common code that belongs in a common initializer. Is there another benefit I'm not seeing?

11/2/2017 6:53:09 AM

EuroTitToss
All American
4753 Posts
user info
edit post

I don't see a problem with this.

Only thing is if `allowMultipleEntries` is renamed and you override it with `multiple` then the first property is still sitting in your base options, which probably isn't a big deal... but you could imagine a scenario where you don't want to pass the original.

11/5/2017 9:31:57 AM

CaelNCSU
All American
6266 Posts
user info
edit post

I'd probably break it up so the default setting logic isn't tied to the specific control.


// option one OO like
var ctrl = control(id).defaults(defaults);
ctrl.fancyControlInitialize.call(ctrl,options);

// option two functional like
control(id).fancyControlInitialize.call(null,merge(defaults, options));


That way it reduces the boilerplate of initializing the defaults.

11/5/2017 11:01:30 AM

FroshKiller
All American
51152 Posts
user info
edit post

EuroTitToss said:
Quote :
"Only thing is if `allowMultipleEntries` is renamed and you override it with `multiple` then the first property is still sitting in your base options, which probably isn't a big deal... but you could imagine a scenario where you don't want to pass the original."


Yeah, I didn't really describe the current state of things accurately. When I'm able to standardize the set of control options the application requires, there won't be any reason to merge option objects anymore. Instead, the initializers will just set the library-specific settings based on the values of the standard properties passed in the standard options provided as an optional parameter in the initializer.

But right now, I'm using this fancy table plugin with some options that I know should be the defaults, and I'm overriding certain values on specific calls. So there's information about the plugin leaking into the callers, but it's quick and easy today to just merge the option objects.

Tomorrow (or sometime), it's going to be stricter. I'm gonna say, like, any table plugin we use must support pagination. The setting you will use to set the number of rows per page will be called rowsPerPage. We're gonna set an application default for that in the initializer for the control. If you want to override that default, you're welcome to do it by setting the rowsPerPage property in the options object you pass to the initializer.

In the initializer, the current plugin expects rowsPerPage. So my default options include that property with the application's default value, and since the property names are the same, it's simpler just merge the default & caller-provided options.

But the next plugin will expect a setting called paginationRows. Callers won't need to do anything. Instead, I'll change the initializer to explicitly set paginationRows to the value of the caller's rowsPerPage property. The merge will disappear completely. Hell, it could disappear completely now--it was just expedient for me. Make sense?

CaelNCSU said:
Quote :
"I'd probably break it up so the default setting logic isn't tied to the specific control.

<snip>

That way it reduces the boilerplate of initializing the defaults."


There isn't any boilerplate. The defaults per control type (e.g. our date input) would be declared in the initializer for that control type. That's the only place they'd be defined.

11/7/2017 9:24:09 AM

CaelNCSU
All American
6266 Posts
user info
edit post

If you do this:


if (typeof additionalOptions == 'object') {
options = Object.assign(options, additionalOptions);
}


For every control type is what I meant by boilerplate.

[Edited on November 7, 2017 at 10:31 AM. Reason : A]

11/7/2017 10:31:08 AM

FroshKiller
All American
51152 Posts
user info
edit post

Well, maybe I could make a decorator or some shit and transpile to whatever fuckin' garbo IE11 implementation we might need. I'm not super worried about that.

11/7/2017 1:13:42 PM

FroshKiller
All American
51152 Posts
user info
edit post

I recently upgraded a JavaScript library for a control and was very glad I took this approach earlier.

2/5/2019 7:39:20 AM

 Message Boards » Tech Talk » JavaScript devs, check me on this Page [1]  
go to top | |
Admin Options : move topic | lock topic

© 2019 by The Wolf Web - All Rights Reserved.
The material located at this site is not endorsed, sponsored or provided by or on behalf of North Carolina State University.
Powered by CrazyWeb v2.37 - our disclaimer.