3 ms·
I really think fetch may be a poor example for the purposes of this discussion. Fetch is roughly analogous to HTTP, its semantics are well known and pretty clea
by eyelidlessness 5y ago
I really think fetch may be a poor example for the purposes of this discussion. Fetch is roughly analogous to HTTP, its semantics are well known and pretty clear… and importantly, its scope is unlikely to significantly grow branchy optional junk.
Again, I would not object to fetch if I encountered it in a design document or code review. That implicitly means I would not object to headers as represented in its signature (it’s just Record<string, string> after all… a very common type in plenty of well-defined interfaces).
An example that would better illustrate when to “consider whether you’re writing more than one function” would be a generalized data access function that may use the following data sources, directly accepting whatever details needed/appropriate for the specific usage:
- HTTP
- SSH
- Postgres
- Redis
- Local file system
- In-memory POJO or equivalent
Sure, you can define such a function. But can you clearly define its usage? And sure, it might defer to smaller units as an implementation detail, but is that single function actually providing any benefit to users? Won’t they (1) find it easier to reason about the different interfaces directly and (2) be able to consume or produce a more usable general function which defers to a single, consistent interface abstraction?
I mean, yeah sure now you need to reference both that function and the implementation satisfying its signature. That’s twice as many imports, surely it’s twice as bad right? Or… maybe it’s better not to have to remember (or even try to document) all the different variations of parameters you must/may pass depending on which data source you’re accessing.
- wruza 5y agoWe could use webpack-dev-middleware as an example, cause it has much more options and tool diversity. Or Intl.NumberFormatter, for a lesser example. If these APIs were built in a composable way, it would be even harder to wrap your head around their configuration and just too wordy to both write and read. Sure, you can define such a function. But can you clearly define its usage? Yes! In your example I see many db drivers for a single db/orm-like sort of api (not exactly orm, but very similar). It’s much easier to learn one common interface, and then only learn/discover differences in connection strings and subtle functions that do or do not work for a specific access method. While db/orm is not a single function, it is usually a collection of functions that target multiple very different storages (the same convergence which you find wrong with GET vs POST etc). If I were to use these native APIs, that would be mental overload x 6 for me. Libraries like sequelize and sqlalchemy are very usable because you may use them in both serious postgre projects and your pocket sqlite tools, by changing only the connection string. Of course we discussed functions, not APIs, but if I were to design dropbox-like thing for developers, e.g. store/access your foo config anywhere, it could be: f(data, options) options: { conn_string: “…”, // driver-specific opts… } Not because my users are too dumb or too lazy, but because in the scope of this function all of these accessors minutiae details are irrelevant to them. They just want f(data, {conn:postgreconn, table:”FooConfigs”}) or f(data, {conn:”webdav://…”, method:”put”}), or just f(data, config.foo_options), the entire options imported from devops-aware config. All of them would be described in one github readme.md page and usable in 15 minutes instead of hours of reading on manuals. This all only works because I reduced the scope of that function to a single operation compatible with all access methods, but that’s exactly my counterpoint for 3, 5. It’s almost like cat data > /dir/file, where <dir> is a mountpoint of hdd, cdrom, nfs, webdav, mongodb, aws kms, mailbox (file is mail folder), sshfs, postgrefs (file is table name) and so on. But for developers, not shell users.