Required Reading: "How Non-Member Functions Improve Encapsulation"

H. S. Teoh hsteoh at quickfur.ath.cx
Tue Oct 31 15:45:42 UTC 2017


On Tue, Oct 31, 2017 at 01:44:58AM +0000, codephantom via Digitalmars-d wrote:
> On Monday, 30 October 2017 at 23:03:12 UTC, H. S. Teoh wrote:
> > 
> > But in D, UFCS allows obj.func() to work for both member functions
> > and free functions, so if the client code uses the obj.func()
> > syntax, it won't have to care about the difference.
> > 
> 
> I don't like it.
> 
> When I see obj.func(), to me, func() is a member function. Why should
> I spend any time trying to work out whether it's a member function or
> a free function? It doesn't make sense to me.

The point is, you *shouldn't have to care*.  If I use a library L that
provides some type T, and the library provides operation X that I can
perform on type T, all I care about is that variables of type T can have
X performed on it.  Is X a member function? A free function?  Who cares!
That's just an implementation detail. As the user of library L, how T
and X are implemented are none of my business.  X can be a remote
procedure call to a network service for all I care -- my code doesn't
have to know.  All it needs to know is that type T can have operation X
performed on it.

That's the whole point of encapsulation.  You *don't have to know* how
something is implemented.  In fact, it's better that you don't, because
later when you upgrade library L, and X changes from member function to
free function, or vice versa, *your code doesn't have to change at all*.
That's why we care about encapsulation in the first place.  Why should
*I* have to change my code just because the upstream authors of library
L decides that X is better implemented as a free function vs. a member
function, or vice versa?  I don't care, and I shouldn't have to care.
Having the same interface (i.e., UFCS syntax) to call X regardless of
how it's implemented is a big advantage, because it frees me, the
downstream user, from needing to care about fiddly details of library
L's implementation.  Instead of upgrading library L and then having to
spend 10 hours fixing all my function calls to X, I can just upgrade
library L and let the compiler figure out which calls are member
functions and which are free functions. My code doesn't have to change
one bit.  Let the machine do the grunt work, free up the human to do the
higher level stuff.

The one case where the difference matters is when you're trying to debug
something.  In that case, I'd say the onus is really upon the debugger
to tell you what kind of function it was.  Surely the debugger must have
this information; it's just a matter of conveying the information to the
user adequately.  If current tools don't allow you to do this easily,
that's a problem with the tools, not with the concept of encapsulation.


T

-- 
Государство делает вид, что платит нам зарплату, а мы делаем вид, что работаем.


More information about the Digitalmars-d mailing list