-
Notifications
You must be signed in to change notification settings - Fork 399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New feature: require_glob() (similar to require() but supports globs) #804
Conversation
Wow! That's a lot to take in! (That's a compliment... there's a lot of feature work going on here.) This makes me wonder where we should draw the line between what we include in the language and what we should leave out. I want to keep things simple and not turn into a competitor to Terraform, Chef, or Puppet. Like the Go language itself, I prefer to only add features that solve a pain point that exists at the time; future-proofing or including variations for completeness sake should be avoided. Let's take a step back and look at the most common use cases: recursively and non-recursively
Since the last 2 arts are the same as the defaults, we can shorten this to:
Or, if recursion is needed:
Are there any use-cases that this wouldn't cover? |
That's a good point. I was wondering about the same if
IMHO dnscontrol is far away from being a competitor for named examples - but already as great! :D
I see your point. But my opinion and decision was: Why limiting the data retrieved by Golang's Based on that point: IMHO
Also to add: It's also possible to use "patterns" as described in Golang docs. |
Hi! I think we can meet half way. require_glob() is an oft-requested feature. I think your solution for that is great and I'd love to receive a PR that implements it. Exposing glob() or eglob() to the Javascript? I don't think that belongs in helpers.js. It belongs in your own dnsconfig.js or file that your require() yourself. That's the short version. The long version is... Following the YAGNI principle, I only add features to DnsControl when they are needed. (https://martinfowler.com/bliki/Yagni.html) Every feature requires support: the code has to be maintained, bugs fixed, support questions answered, etc. Adding unused features for completeness or because someone might need it in the future adds to the work. dnscontrol isn't my full-time job so I want to keep that load to a minimum. (YAGNI exists outside of tech too. In the legal system they have a term "ripe": You can't sue someone because of a hypothetical problem a law might cause... you have to find a real situation where the law is causing a problem and sue based on that. The reason is that we can always debate a hypothetical. When something is real ("ripe") the debate is limited. ) For example, if we expose eglob()'s objects to the users, then I have to support it. I don't know Javascript. Supporting questions around that would be a big problem. There may come a day where we switch Javascript interpreters (the current one isn't getting updates) or switch to a smaller subset of javascript. The less we expose to the user the better. So, is there a "ripe" need for require_glob()? Maybe. Why not simply add a require() every time you create a new file? Most people add domains once in a while. If you are adding them constantly, this might not be the right tool for you. A major sports network uses dnscontrol to maintain 2,000+ domains without require_glob(). There are other ways get the benefit of require_glob(). For example, generate dnsconfig.js using a Makefile. Split dnsconfig.js into a front and end file, insert all the require()'s in the middle:
(That's from memory. It may not have the quoting right.) There are reasons NOT to add require_glob(): There are security issues around accidentally requiring an unintended file. require() itself is a security issue because if you require() an untrusted file, it can do anything. It can redefine Is there a "ripe" need for eglob()? You mentioned "loading JavaScript files based on modification dates" and I assume that was a joke. That said, if you have a project that is blocked because glob/eglob doesn't exist, please let me know more about the situation. I would gladly help engineer a solution... possibly surprise you with something even better than glob/eglob. This is similar to how the Go project is managed. Features like Modules, Generic, etc. could have been added years ago. However, by delaying they were able to study the issue deeply and come up with a better solution. That was more than I planned to write but I hope you read all the way here :-) |
I'm not sure if I'm getting this right. Writing an own glob() function in a .js file won't work out, as it doesn't have access to the underneath filesystem to get these kind of information. So you need corresponding code in Go and to expose it to JS to make this work. But I have to admit that I don't know the JS engine, Otto, in-depth to be sure on that. But just to make sure we align to the decision/way of implementation: Would it be fine to have
I've never heard about YAGNI principle, to be honest. But thanks for bringing this up! Haven't read linked blog post yet, but seems to be an interesting one I've saved for reading later. And also regarding the support - I've to admit, you're totally right on that. Sometimes I might be too excited, thinking too complex/big and basically keep throwing in stuff someone might need someday in some way - which is completely the opposite of YAGNI. (To my defense: I'm not in the software development (since longer time anymore)! :)) So I do appreciate bringing this to attention.
Yes. That's actually what I'm doing right now. But specially during testing I've wondered why specific changes didn't apply or ended up in expected results... What the "issue" was? You might have guessed it: Forgot running the
Yes, of course I did! I do really appreciate it! :) |
Good point. My thought is to include it in the Go code, implement glob() in helpers.js but don't document it. (Maybe with a name or comment that implies it isn't for general use?). require_glob() would be implemented as needed and documented. Tom |
What I'd suggest instead: Sounds like a plan, doesn't it? :D |
That's sounds like a plan. The require_glob() function should have a documentation page but not the glob() function. That way if someone uses it, it's obviously at their own risk. |
I've just reworked it. However I've still gone with the approach having |
This needs a "go generate" and it should be ready for merge. LMK |
As |
There's no right way to deal with this (one of the problems with Hopefully this will go away after golang/go#35950. |
Do you want me merging
Ah, yeah. Already upvoted that apparently :D |
Yes. Please |
# Conflicts: # pkg/js/static.go
There we Go! :) |
Puns are permitted on this project. In fact, they are encouraged. :) |
…StackExchange#804) * Initial implementation of findFiles/globe/glob * Fixed path, some small improvements * filepath.Dir() calls Clean() automatically anyway * Relative path support (like require()), renamed func * Check file ext prefix, further comments, var renaming * Updated static.go after merge * Added doc for glob() * Tiny adjustment of description of glob() * Updated docs for possible pattern * Reworked glob, added public-facing require_glob() * Updated docs with examples * Updated static.go * go generate
Let me introduce you...
glob()
eglob()
(extendedglob()
)It's basically like any other
glob()
function, known from other languages. You can recursively list files, for all kind of different usage scenarios.There are currently three arguments:
What was I'm trying to solve here?
I'm having a directory structure like:
So far I've been using a self-crafted bash script to merge all individual
.js
files into one singlednscontrol.js
file. But that's boring. This is way I've decided solving that with a functionality to be able to dynamically list files and include them.For example:
For example:
The major difference
However, there's one key difference between
eglob()
(extended glob) andglob()
(wrapper in JavaScript aroundeglob()
). Whileglob()
is designed for being simple and used for dynamic-loading (like above),eglob()
is the smarter brother and the actual Go-side function.glob()
will simply return an array, whileeglob()
returns an array of objects for more complex logics, if required.Let's go for an example: (
glob()
)vs (
eglob()
)A few examples:
One more important thing to note:
eglob()
is as smart asrequire()
is. It lists files always relative to the JavaScript file where it's being used in. Let's go with an example:dnscontrol.js:
domains/index.js:
This will now show files being present underneath
./domains/user1/
and NOT at below./domains/
.Hope this makes sense.