2 ms·
The ultimate perpetrator in this example is to have more than one positional (i.e. unnamed) boolean parameter. Even having a single positional boolean is a lot
by DemocracyFTW2 4y ago
The ultimate perpetrator in this example is to have more than one positional (i.e. unnamed) boolean parameter. Even having a single positional boolean is a lot of the time bad design. I'm aware of one piece of (JS) software (https://chevrotain.io/docs/ https://chevrotain.io/docs/) whose entire API is (apparently) built on the principle that each method accepts a single argument (an object with key/value pairs) and returns a single value (of the same shape). Personally, I try to somewhat keep to the first part of that pattern, but don't quite manage to—quite a few methods have very obvious mandatory, first parameters that I then often accept as positionals as in `f = ( image, cfg ) => ...`.
In this particular example, though, one might argue that picture data may be communicated in many different ways: as an URL, an FS path, a buffer, a stream...; question is: do you really want your `resizeImage()` method to read from the network or from the file system? I'd say that this is probably in violation of the principle of separation of concerns. The best choice for the first, mandatory argument is probably a stream of octets in this case, and when you can't be 100% sure, then indeed the way to design such an interface is to first constrain the method to accept a single object (dictionary) of properly named values, and at first only implement `{ stream: ..., width: ..., height: ..., ..., }`. Later on, when the software has shown it's up to the task, it will almost always be possible to introduce new parameters (say, `path` and `url`, all exclusive with `stream`), and, if need be, allow `resizeImage stream, { width: ..., ..., }` as a variant.