On Tuesday, 29 September 2015 at 14:57:13 UTC, Sebastiaan Koppe wrote:
Good. But why put everything in one package?

dub forces me to do it that way. It isn't my preference, but reorganizing all my files and creating twenty or thirty different github repos to house them is unacceptable.

The unit of encapsulation in D is the module. If a module does two wildly different and independent things, you would break it up. Similarly, and I think this is often neglected, if two modules are intertwined and one cannot work without the other, they are really one unit and should be merged.

The merged module will present a cleaner interface and be easier to maintain since it can handle its own private implementation without worry of exposing internals for its friend module nor having something change independently of it.

(I wish D would fix that bug where public and private symbols can conflict though. So annoying and breaks this beautiful encapsulation. You might notice simpledisplay.d has a function named toInternal for example. I'd like to name it to, but then it would break code that uses std.conv.to, despite that internal function being private! Ugh!)

That forms the basis of my general policy: make modules that stand alone and do a task as completely as necessary. I only split them up when there's a technical requirement and the split lowers overall complexity.

And, of course, when possible, I like to make those dependencies optional; they aren't required unless you actually use those specific features.

Modules in D do a pretty good job at this. They can contain most their own metadata, too: write ddoc inline, you can grep it for version options (and since D doesn't allow versions to cross module boundaries, it is as simple as a grep) and import dependencies, and you can even have some control over the linker with stuff like pragma(lib), showing system dependencies.

Modules also have a one-to-one correspondence to files, making them a natural thing to download, move around, etc. Other programs know how to handle files so you can version them and such too.

D's modules work! Why does dub reject this model?

A guy on npmjs.com goes the other extreme and he actually has a package (https://github.com/sindresorhus/negative-zero/blob/master/index.js) that consists of 1 line of code.

Disgusting. Think of all the overhead involved in that package, not just for the author, but now for everybody who use it... and everyone who uses something that uses it, and so on and so forth - right down to the end user!

There needs to be a balance struck between "don't repeat yourself" and avoiding dependencies.

It is generally considered a bad idea to do the whole system together at once. (though Docker and VMWare appliances and such do actually try to do that and have found some success in the market) Making changes to that means a lot of extra work that is easy to do wrong. (The duplication itself btw isn't a big problem to me, computers are good at doing the same thing over and over again; it is an easily automated problem, at least until something goes wrong.)

In code, we factor common functionality into functions that can be used from multiple places instead of copy/pasting the bodies everywhere.

It is similarly a bad idea to have a deep web of external dependencies. This also makes maintenance harder - where is the problem? Where do you make the change? How long will it take to get upstreamed? Do you understand what is going on anymore; will changing that dependency break some unrelated project somewhere else?

In code, we try to write our functions such that they do not use global variables. We like pure functions whenever we can. We like to use const or immutable to limit the scope of confusing changes. We like to use private to limit the function's interface.

Negative zero should be a constant (and probably a private one at that, that'd be a bizarre implementation detail to expose to an API user). Here, it is instead a public global mutable function pointer.

In the description you say "or better yet, ditch dub and do things the simple, reliable way of dmd *.d" How is that more reliable?

It works the same way every time you do it and exposes all the options dmd has without needing wrapper json options which may or may not actually be there, or documented, or keep working the same way next time you try.

I copy/pasted your arsd/dom.d code in a couple of projects. But none of them will receive updates unless I do 'm manually.

That means you don't have to put up with me randomly breaking your code! You don't have to wait for me to publish a bug fix. You aren't locked in to the way I did things and are free to customize it as you wish.

It is very easy to update it too, even if you do customize it (git will handle the conflicts, if any) - you can always do a git pull from me, then test and push back up to your copy (or, not even bother with the push and just keep the development dependencies private or ask your users to retrieve it themselves... it is just a file download, very easy to do).

However, the idea of having a package-manager is a good idea. If only to serve as documentation on the libs you package depends on.

dscanner --imports *.d | sort | uniq

Always up-to-date!

Though, dscanner and dub.json both fail to get across all the nuance possible with the D module system. For example, running that on dom.d yields:


Yet, dom.d is also standalone!

characterencodings is only needed if you call one of the character conversion functions; it is a lazy local import inside a template.

database is the same, it is only used if you actually call the fillForm function. (Which is the only reason I permit that btw, dom and database should NOT depend on one another and I might just copy/paste that function out someday).

jsvar is only used with a rare -version switch that I never finished anyway. I should probably just delete those lines.

But, how do you express the half-dependency of characterencodings in a dub.json dependencies list? Perhaps a configuration could do it.... or the character converting functions could be pulled out into a third package on which you depend to get them.... what a pain compared to just "don't call this function and you never need it but if you want it it is right there"!

Here's how I documented it in dom.d:

BTW: this file optionally depends on arsd.characterencodings, to help it correctly read files from the internet. You should be able to get characterencodings.d from the same place you got this file.

If you want it to stand alone, just always use the `parseUtf8` function

That explains it better than dub.json has the capability to.

I'm not completely against the idea of a package manager or even against dub itself. I just see very little value add from it and quite a bit of complication and associated questions about it on the support forums.

Reply via email to