On Thursday, October 26, 2017 12:53:38 JN via Digitalmars-d wrote: > On Wednesday, 25 October 2017 at 22:19:23 UTC, Walter Bright > > wrote: > > for core D devs. > > > > "How Non-Member Functions Improve Encapsulation" by Scott Meyers > > > > http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/1844 > > 01197 > > > > Note that I'm as guilty as anyone for not understanding or > > following these guidelines. I expect we can do much better. > > As a counterpoint. I guess UFCS makes it less of a problem, but > it's nice when using an IDE to just type foo. , press ctrl-space > and see a nice list of methods that can be used with the class. > When having free functions, you don't get to enjoy that :)
At a previous job, we had our own string class which wrapped std::string just because some of the developers wanted our extra string functions on the type where they would be easy to find (even just for documentation purposes). They were of the opinion that once you separate the functions from the class, your project will ultimately end up with multiple header files of functions doing similar things, because at least some of the time, developers wouldn't know about the existing functions and would add their own own. And with sufficiently large projects, that does seem to happen all too often. I still don't agree with the idea that putting stuff on the class is better just because it makes stuff easier to find, but I can see why someone would think that. As has been pointed out elsewhere in this thread, the encapsulation benefits don't exist in the same way in D unless you put the free functions in separate modules, and then you have to import other stuff to use them, whereas in C++, you can just put the free functions next to the type and still get the encapsulation benefits. So, the benefit of splitting the functions out within a module is fairly minimal in D. Rather, the main reason I see for splitting functions out is in order to make them more generic, and I think that the push to do that in D has a tendency to make a lot of functions free functions that might have been member functions in most other languages. And in D, there's the issue that declaring a function to be used with UFCS instead of as a member function can be a bit of a pain when the type is templated. You have to repeat a bunch of stuff that's just part of the templated struct or class. You end up with additional templates and template constraints (much of which is duplicated) just to separate the functions from the type. That being said, the time that I'm most likely to turn a member function into a free function when the function isn't going to be made generic is when the type is templated simply because then I can put the unittest block right next to the function without having it be part of the template (since that's almost always the wrong thing to do if you don't do some boilerplate with static ifs to make it so that they're only compiled into a single instantiation that's intended just for testing). Overall, I think that the idea that functions should be free functions where reasonable is good advice, but it needs to be taken with a grain of salt. - Jonathan M Davis
