private keyword dont appear to do anything

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Nov 3 23:32:52 UTC 2017


On Fri, Nov 03, 2017 at 04:30:21PM -0600, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Friday, November 03, 2017 14:52:22 H. S. Teoh via Digitalmars-d-learn 
> wrote:
[...]
> > Arguably, many of these large flat files ought to be split up into
> > smaller files.  For example, std.algorithm.* and std.range.* all
> > tend to be conglomerations of basically-independent groups of
> > structs and functions.  Iota and Cycle never interact with each
> > other, and neither of them interacts with Recurrence, yet these all
> > sit in the same file.
> >
> > Seems to me like a typical case of low cohesion, which, according to
> > the ideals of encapsulation, ought to be grounds for splitting up
> > the file into self-contained parts.
> >
> > But of course, there are pragmatic reasons for the way things
> > currently are.
> 
> If you take that to the extreme, you just end up with a function per
> module, which is pretty ridiculous IMHO (though that may be what you
> mean by pragmatic reasons).

It's not that ridiculous if you consider that some of the more
heavily-used Phobos functions are actually not individual functions, but
overload sets.  I know we have been trying to merge some of the
unnecessary overload sets for other reasons, but some of these overload
sets can get pretty big.  Compound that with the long string of
unittests associated with each overload, that has accumulated from a
long string of bug fixes, etc., and you have pretty good justification
for keeping just that single overload set in its own file, together with
its associated unittests, and potentially also other paraphrenalia like
enums or other declarations used by the overload set, but not used
anywhere else.


> And really, free functions like that are exactly the sort of places
> where encapsulation tends not to matter much, because there's nothing
> to encapsulate beyond the guts of the functions themselves, which are
> already encapsulated.

Arguably, once a function grows past a certain length, it's time to
break it down into more manageable pieces.  Having a function sit in its
own file gives you a nice working space for this sort of refactoring,
without worrying about namespace conflicts with unrelated code.

Still, I agree that some degree of judgment is involved here.  If we're
talking about a simple function that will never grow past 5-10 lines, it
does seem a little pointless to keep it in its own file, just to adhere
to some ideal of encapsulation.

But IME, with Phobos code even simple functions eventually grow into
multi-page monsters over time, once you start adding type-specific
specializations to deal with performance issues and the like.  Just look
at std.algorithm.searching.find, for example.  Several different
overloads, and static if blocks within an overload, sometimes on the
lengthy side depending on the specific optimization being implemented.
Arguably we should factor out some of the static if blocks or overloads
into separate private functions for easier future maintenance /
management if more specializations are added, or we need to balance
between different optimizations based on different factors. Static-if /
else blocks just aren't very conducive to this sort of thing.  And being
able to do this in a file dedicated to .find would be cleaner than
having to do surgery in a 4600-line file (and having to deal with
potential merge conflicts with other unrelated changes to the same file
-- though git is so good at this that one generally doesn't run into
much of a problem).


> The situation is very different from something like std.container
> where you have types which have member variables which could be
> protected from access by other stuff in their modules if private
> worked differently.

Well, std.container *has* been split into submodules per container type.
I think that's a much better organization than in std.algorithm.*.


> Figuring out a good way to organize a bunch of free functions is
> difficult (as evidenced by the fact that plenty of folks have a hard
> time remembering what is where inside of std.algorithm and std.range),
> but that's really not an encapsulation problem, just a code
> organization problem.
[...]

<half-serious> Perhaps the solution is to go the
one-overload-set-per-file route, with std/algorithm/package.d basically
importing everything underneath. :-P </half-serious>

(Shhh, don't tell Andrei, or we'll get another lecture about wasting
time on worthless things while more important things are left to do.)


T

-- 
All problems are easy in retrospect.


More information about the Digitalmars-d-learn mailing list