This topic is probably one of the most misunderstood aspect of OOP, I struggle a lot explaining this to my colleagues. Also decades of bad practices (ex. Qt) don't help. Every C++ programmer should watch this talk, very nice job!
You don't need to convince me, but your presentation was the better I have never seen presenting this subject. I'll share it will all my colleges. Kudos.
The first time I saw this talk, I thought to dislike it. But as many times I started to see it, I started to love it. And by now it's my most viewed talk. Thanks man thanks a lot.
Superb talk! I will change my ways, or at least try to :-) Also a very relaxed voice, not too many slides (makes a change!). Well executed and very well done!
Great presentation! It would be nice to get some more suggestions on where to keep free functions (in what translational unit). Keeping the free functions with a class can slightly inhibit flexibility and readability if multiple classes are using that free function. I don't have a better idea on the top of my head.
Modules would help a lot with finding and even more interestingly encapsulating all kinds of free functions. Also concepts. Here's to next C++ standard. As to mocking, you can provide a different implementation by replacing a header + implementation, preprocessor - or perhaps in future, a mock module. With a class, that is almost impossible as you cannot "pull in" bits and pieces thereof easily.
I really hope for some more language support for this. The worst is that C++ is still not doing any standardization or recommendation of the build system. Switching implementation files is not easy.
I like free functions, but in my experience my colleagues do not find them and lots of time write their own versions again. Does anybody have an idea how to properly advertise the existence of my functions? Member functions on the other side have the advertisement built into intellisense and co.
I don't really get the testing point. Sure, the production code should not be affected by external testing code/classes but there are dozends of good approaches to make the code testable without free functions. At a higher abstraction level, it's all about well designed interfaces. At a lower level, it's all about correct encapsulation and the definition, what the unit really is for the given context.
With the IDE completion, the same thing can be done with some_namespace:: Admittedly it is more effort to type than "object.", but why would you optimise *C++* for speed of writing?
Werner Herzog's little brother ;) Great talk, I wonder how applicable it is to other languages with their lookup rules. Some of it seems very general software design stuff rather than specific to C++.
Interesting discussion about free functions and examples on using them, but this discussion doesn't consider the question of code readability or discuss when generic programming can actually make code less readable. The advice is also based on beliefs from Scott Meyers, that non-member functions encapsulate better than member functions, and so I find all the examples and arguments used only show the non-member function approach as the best approach, and doesn't acknowledge when a member function might be a better chouce. I would be pleased to see a following CppCon regarding this topic, which can provide a balanced view between these ideas, and give good examples for both member functions and free functions.
The most important detail of the discussion is provided too late by far within the presentation: Encapsulation and location of free functions (using namespaces, moving to cpp-File (not robustly applicable in UnityBuilds but other topic...). Why is this presented that late (around 34:00)? A lot of "conservative" viewers at least on youtube might not be convinced within the first twenty minutes (since encapsulation of functions is their major counter argument for sure) and it's very likey that they leave it before they've seen the whole stuff since almost (almost) all other presented Pro-arguments can be achieved without free functions too in an acceptable way.
Learning programming with Java has ruined many new developers, I think - me included. I have to keep reminding myself not to fall into the habit of organizing everything into classes. There's a certain level of satisfaction of doing so, up to a certain point where things become a mess. On a theoretical level, I believe PODs and functions is all that's necessary. He mentions you can move implementation details into their own namespace to make them "inaccessible" to consumers. With the upcoming modules support, you can simply choose not to export them.
I don't agree that private member functions offer less encapsulation than free functions. The idea behind a private function is, that it should only be called in a certain context, which is controlled by the object. For example private function B might only make sense, after private function A was called. If you make them free functions, you don't control when they are called. Also you have to provide a pretty broad interface of your class, meaning that you have to make some member variables, that should be private public instead, otherwise the free function can not operate on those fields.
I like this a lot. But... "There shouldn't be long chains of calls."? What's the reasoning here? That seems to me to be a pretty useful idiom. Admittedly, I've been JavaScripting a lot lately. But a lot of those patterns should work fine in C++.
It does depend on the context. Deep call stacks can lead to hidden allocations, indirection that's hard to trace, unclear lifetime of variables, multiple unnecessary copies, and of course a (mild?) performance hit. I suppose it can be difficult to keep a logically structure for complex projects, but it does help overall. As you say, C++ can accommodate the chained approach, but it's not ideal for us humans (or simpleton devs)
where do you put all these tho? just make a struct with a ton of returning methods? like a toolbox of free floating methods? or a header with a namespace I guess
A namespace makes the most sense: comsider if you get another library from a third party, it wouldn’t be unusual to have identical function names, and thus why namespaces exist.
3 года назад+4
This video doesn't prove free functions are better, but instead that principles are relative. Also, you forgot the readability and maintainability principle. Also, member functions do encapsulate behavior, Scott is wrong on that one. If the thing a method does is generic, create a free function that is called by the member function. The standard library uses free functions to help write generic code, just for that. Classes in the standard library are filled with methods. Private functions should either not be tested (public functions call them, so if these are tested, the former are), or just do the friend thing in a generic way (or delegate critical functionality to free functions, etc). And the ADL thing... don't even get me started. "I never said don't use member functions". In the 'clearEverything' example, you're pretty much saying that. 'clearEverything' is a perfectly valid member function, with increased readability as such instead of a free function. It exposes better the fact that you're doing something to the 'WebBrowser'. As a free function, you're just saying 'clearEverything' in a very generic way, and you rely on overloads and the ADL messing you around. In the 'resetValues' you're also pretty much saying it. Even thou 'resetValues' does a very simple thing, private member functions can do more complex things tightly related to the class. Start using free functions instead of methods where your shouldn't and your code will be an unmaintainable mess, and maybe .1% more efficient.
At 18:00, how does this work? doesn't the templated function would call reset(int &) if we send it std::vector& as an argument, but what if we send an std::vector of something that is not a numeric type? what if we for example send something that is not assignable to zero, shouldn't we template the first reset function to take in T and calls the default constructor or something similar?
It could go worst, you could send a std::vector and since int& can't be translated to float& it will crash at compile time. Now (ignoring that obvious bug there) if reset would be a template reset(T&) you could use "enable_if" (en.cppreference.com/w/cpp/types/enable_if) to ensure it will be a numeric type. Also with the concepts that will came with c++20 it can be done in a more generic form.
Think the point there is that it won't compile for other types until you create a reset function that takes a reference to that type. References are pointers, and can't really implicitly convert from one pointer type to another.
I find it very useful actually... If the entire example is encapsulated in a namespace (as he suggests later), it's as simple as implementing reset(float) on the same namespace of the original class (extending it) wherever you want. Even if you don't have access to the original reset source code. That is something that cannot be done without inheritance if the function is a private member.
After 20+ years of c++ it seems very unusual in my view to have global/namespace functions in c++. I will accept free standing functions as long as they are not public for all other cases I would prefer to see static class function. And about coupling test with production: have a class XxxTest that contains all the functions to support tests. All you need is forward declaration of the class and friend.
YuFan Lou I think he properly addressed that in his talk: The examples are absolutely not functional programming. But the style blends well with using (non-strict) functional programming where that is the best solution (as it often is, in my experience).
C++ has always been multiparadigm, though with adding lambdas and some other things, its flexibility has grown: it’s only as OO as you want it to be, including not at all, and that’s always been so.
@@strictnonconformist7369 Honestly cpp feels like the only all-paradigm language. Even logical programming is surprisingly non-ugly: people.cs.umass.edu/~yannis/lc++/family_cc_snippet.txt
I am still not convinced and I think the talk is incomplete at best. Note that writing application code and libraries are two different things. If you provide a library you want its interface to be minimalistic and as stable as possible to minimize the effort required to maintain and support your library. You never know if a function might need access to private members in the future. (This is why the WebBrowser example at beginning is very bad.) You should not use non-member function if it makes no sense to overload them and if they do not provide functionality that can be useful elsewhere. Data encapsulation can still be achieved with the pointer to implementation idiom. The testing approach with "#define private public" is not pretty but ok, since nobody really cares how testing code does it thing. The optimization argument is plain wrong. It makes no difference for the compiler if you call a member or non-member function. Both can be equally optimized if they are inlinable.
Not everything in the STL is a thing of beauty. Standard (std::iostream, etc) breaks a number of the design principles. It's an abomination of multiple responsibilities and problematic state-retention. The allocator concept is a hot mess that's only just now being plastered and painted over to seal off the exudate. Standard is an over-engineered Goldberg mechanism. Pairs of iterators that indicate a range are not bound into a single object. You can probably think of more.
Ranges are being worked on. Allocators are being reworked with that polymorphic new stuff. Random is pretty good actually but could be improved too - it is just explicit - if you don't need that you can still use rand.
is the best thing to ever happen to this godforsaken language! It covers many bases whilst still being easy to use and implementation independent; looking at you, rand()... is a thing of beauty. Just like !
This is a good workaround for the shortcomings of the language. But the audio is terrible, he is too quiet but his sibilance is way up makes it unpleasant to listen to...
This talk contradicts the whole principle of C - even way way before C++ came into play. You want your code files to be as self sufficient as possible and not depent on a huge variety of silly headers/libraries that implement trivial functions. Its even better to do them inline than via free functions. Currently it is even common to create a whole class whose main purpose is to execute a single member function. While other member functions are just support for input / output / other utility.
A very poor presentation. A very good topic can only be ruined like that.. All you have done is you take the example from Scot Mayers book and repeating what he had said again and again what he already told us in 2013. Although you"ve admitted your next example is unrealistic , you've tried to convince us that the features you had showed us is very cool that can not be used in the context of your example. Programs are not written with slogans,This topic can be explained very good with real life example code. You would take a real life example and step by step you could show us how free functions are so cool.
This topic is probably one of the most misunderstood aspect of OOP, I struggle a lot explaining this to my colleagues.
Also decades of bad practices (ex. Qt) don't help.
Every C++ programmer should watch this talk, very nice job!
You don't need to convince me, but your presentation was the better I have never seen presenting this subject. I'll share it will all my colleges. Kudos.
The first time I saw this talk, I thought to dislike it. But as many times I started to see it, I started to love it. And by now it's my most viewed talk. Thanks man thanks a lot.
Thanks for sharing!
Superb talk! I will change my ways, or at least try to :-)
Also a very relaxed voice, not too many slides (makes a change!). Well executed and very well done!
Yay
Great presentation! It would be nice to get some more suggestions on where to keep free functions (in what translational unit). Keeping the free functions with a class can slightly inhibit flexibility and readability if multiple classes are using that free function. I don't have a better idea on the top of my head.
If it's used by multiple classes, it should be moved to his own file.
Bjarne Stroustrup wants unified call syntax for more than 20 years! Maybe the time has arrived?
Great talk. I like the part about IDE support for free functions.
Excellent speaking! There was considered every aspect of the question.
Glad you think so!
You might consider becoming a professor. Your presentation is awesome.
2:42 *PERFOMANCE* Of course, every c++ programmer needs that.
Seems like a whole host of issues rust does away with :o) Nice talk.
Modules would help a lot with finding and even more interestingly encapsulating all kinds of free functions. Also concepts. Here's to next C++ standard.
As to mocking, you can provide a different implementation by replacing a header + implementation, preprocessor - or perhaps in future, a mock module. With a class, that is almost impossible as you cannot "pull in" bits and pieces thereof easily.
And with c++20 we have both modules and concepts.
I really hope for some more language support for this. The worst is that C++ is still not doing any standardization or recommendation of the build system. Switching implementation files is not easy.
I like free functions, but in my experience my colleagues do not find them and lots of time write their own versions again.
Does anybody have an idea how to properly advertise the existence of my functions?
Member functions on the other side have the advertisement built into intellisense and co.
Perhaps namespaces. Classes often use capitals and namespaces lowercase. Writing the class name with lower case will list all available functions.
@@JMRC then you could just make them static.
One of my favourite talks this year.
I'll be sharing this with my team.
Thanks so much for the effort in your presentation.
Kudos! :)
I don't really get the testing point. Sure, the production code should not be affected by external testing code/classes but there are dozends of good approaches to make the code testable without free functions. At a higher abstraction level, it's all about well designed interfaces. At a lower level, it's all about correct encapsulation and the definition, what the unit really is for the given context.
With the IDE completion, the same thing can be done with some_namespace::
Admittedly it is more effort to type than "object.", but why would you optimise *C++* for speed of writing?
Werner Herzog's little brother ;) Great talk, I wonder how applicable it is to other languages with their lookup rules. Some of it seems very general software design stuff rather than specific to C++.
private friend void testReset() is still way better than #define private public .. which I've come across a couple times.
Interesting discussion about free functions and examples on using them, but this discussion doesn't consider the question of code readability or discuss when generic programming can actually make code less readable.
The advice is also based on beliefs from Scott Meyers, that non-member functions encapsulate better than member functions, and so I find all the examples and arguments used only show the non-member function approach as the best approach, and doesn't acknowledge when a member function might be a better chouce.
I would be pleased to see a following CppCon regarding this topic, which can provide a balanced view between these ideas, and give good examples for both member functions and free functions.
Did you watch the whole thing?
Waiting for t-shirt with "Free Functions!" on it.
The most important detail of the discussion is provided too late by far within the presentation: Encapsulation and location of free functions (using namespaces, moving to cpp-File (not robustly applicable in UnityBuilds but other topic...). Why is this presented that late (around 34:00)? A lot of "conservative" viewers at least on youtube might not be convinced within the first twenty minutes (since encapsulation of functions is their major counter argument for sure) and it's very likey that they leave it before they've seen the whole stuff since almost (almost) all other presented Pro-arguments can be achieved without free functions too in an acceptable way.
59:30 - As soon as we get unified call syntax, chaining free function will no longer be a problem,
So, I have an object Foo and have to do something with it... move to rehsarper or die? Hopefully VS will catch up
Learning programming with Java has ruined many new developers, I think - me included. I have to keep reminding myself not to fall into the habit of organizing everything into classes. There's a certain level of satisfaction of doing so, up to a certain point where things become a mess. On a theoretical level, I believe PODs and functions is all that's necessary.
He mentions you can move implementation details into their own namespace to make them "inaccessible" to consumers. With the upcoming modules support, you can simply choose not to export them.
I don't agree that private member functions offer less encapsulation than free functions.
The idea behind a private function is, that it should only be called in a certain context, which is controlled by the object. For example private function B might only make sense, after private function A was called. If you make them free functions, you don't control when they are called.
Also you have to provide a pretty broad interface of your class, meaning that you have to make some member variables, that should be private public instead, otherwise the free function can not operate on those fields.
I like this a lot. But... "There shouldn't be long chains of calls."? What's the reasoning here? That seems to me to be a pretty useful idiom. Admittedly, I've been JavaScripting a lot lately. But a lot of those patterns should work fine in C++.
It does depend on the context. Deep call stacks can lead to hidden allocations, indirection that's hard to trace, unclear lifetime of variables, multiple unnecessary copies, and of course a (mild?) performance hit. I suppose it can be difficult to keep a logically structure for complex projects, but it does help overall. As you say, C++ can accommodate the chained approach, but it's not ideal for us humans (or simpleton devs)
where do you put all these tho? just make a struct with a ton of returning methods? like a toolbox of free floating methods? or a header with a namespace I guess
A namespace makes the most sense: comsider if you get another library from a third party, it wouldn’t be unusual to have identical function names, and thus why namespaces exist.
This video doesn't prove free functions are better, but instead that principles are relative. Also, you forgot the readability and maintainability principle. Also, member functions do encapsulate behavior, Scott is wrong on that one. If the thing a method does is generic, create a free function that is called by the member function. The standard library uses free functions to help write generic code, just for that. Classes in the standard library are filled with methods. Private functions should either not be tested (public functions call them, so if these are tested, the former are), or just do the friend thing in a generic way (or delegate critical functionality to free functions, etc). And the ADL thing... don't even get me started.
"I never said don't use member functions". In the 'clearEverything' example, you're pretty much saying that. 'clearEverything' is a perfectly valid member function, with increased readability as such instead of a free function. It exposes better the fact that you're doing something to the 'WebBrowser'. As a free function, you're just saying 'clearEverything' in a very generic way, and you rely on overloads and the ADL messing you around. In the 'resetValues' you're also pretty much saying it. Even thou 'resetValues' does a very simple thing, private member functions can do more complex things tightly related to the class.
Start using free functions instead of methods where your shouldn't and your code will be an unmaintainable mess, and maybe .1% more efficient.
At 18:00, how does this work? doesn't the templated function would call reset(int &) if we send it std::vector& as an argument, but what if we send an std::vector of something that is not a numeric type? what if we for example send something that is not assignable to zero, shouldn't we template the first reset function to take in T and calls the default constructor or something similar?
It could go worst, you could send a std::vector and since int& can't be translated to float& it will crash at compile time. Now (ignoring that obvious bug there) if reset would be a template reset(T&) you could use "enable_if" (en.cppreference.com/w/cpp/types/enable_if) to ensure it will be a numeric type. Also with the concepts that will came with c++20 it can be done in a more generic form.
Think the point there is that it won't compile for other types until you create a reset function that takes a reference to that type. References are pointers, and can't really implicitly convert from one pointer type to another.
I find it very useful actually...
If the entire example is encapsulated in a namespace (as he suggests later), it's as simple as implementing reset(float) on the same namespace of the original class (extending it) wherever you want. Even if you don't have access to the original reset source code.
That is something that cannot be done without inheritance if the function is a private member.
After 20+ years of c++ it seems very unusual in my view to have global/namespace functions in c++. I will accept free standing functions as long as they are not public for all other cases I would prefer to see static class function. And about coupling test with production: have a class XxxTest that contains all the functions to support tests. All you need is forward declaration of the class and friend.
extension methods much?
who is this so called OO crowd anyway and how dare they send angry emails
Haskellers be like “Welcome to functional programming”
Pseudo functional.... but C++ has been indeed evolving.. contrary to other OO based languages.
YuFan Lou I think he properly addressed that in his talk: The examples are absolutely not functional programming.
But the style blends well with using (non-strict) functional programming where that is the best solution (as it often is, in my experience).
C++ has always been multiparadigm, though with adding lambdas and some other things, its flexibility has grown: it’s only as OO as you want it to be, including not at all, and that’s always been so.
@@strictnonconformist7369 Honestly cpp feels like the only all-paradigm language.
Even logical programming is surprisingly non-ugly: people.cs.umass.edu/~yannis/lc++/family_cc_snippet.txt
I am still not convinced and I think the talk is incomplete at best. Note that writing application code and libraries are two different things. If you provide a library you want its interface to be minimalistic and as stable as possible to minimize the effort required to maintain and support your library. You never know if a function might need access to private members in the future. (This is why the WebBrowser example at beginning is very bad.)
You should not use non-member function if it makes no sense to overload them and if they do not provide functionality that can be useful elsewhere. Data encapsulation can still be achieved with the pointer to implementation idiom.
The testing approach with "#define private public" is not pretty but ok, since nobody really cares how testing code does it thing.
The optimization argument is plain wrong. It makes no difference for the compiler if you call a member or non-member function. Both can be equally optimized if they are inlinable.
So, no... not really, except for trivial classes. What I'm seeing here is basically a class called "namespace X".
Not everything in the STL is a thing of beauty. Standard (std::iostream, etc) breaks a number of the design principles. It's an abomination of multiple responsibilities and problematic state-retention. The allocator concept is a hot mess that's only just now being plastered and painted over to seal off the exudate. Standard is an over-engineered Goldberg mechanism. Pairs of iterators that indicate a range are not bound into a single object. You can probably think of more.
Ranges are being worked on. Allocators are being reworked with that polymorphic new stuff. Random is pretty good actually but could be improved too - it is just explicit - if you don't need that you can still use rand.
is the best thing to ever happen to this godforsaken language! It covers many bases whilst still being easy to use and implementation independent; looking at you, rand()... is a thing of beauty. Just like !
This is a good workaround for the shortcomings of the language. But the audio is terrible, he is too quiet but his sibilance is way up makes it unpleasant to listen to...
How to make cpp even more pythonic (To be clear, this is a great trend, imo).
Please no, just ... NO.
This talk contradicts the whole principle of C - even way way before C++ came into play.
You want your code files to be as self sufficient as possible and not depent on a huge variety of silly headers/libraries that implement trivial functions. Its even better to do them inline than via free functions.
Currently it is even common to create a whole class whose main purpose is to execute a single member function. While other member functions are just support for input / output / other utility.
A very poor presentation. A very good topic can only be ruined like that.. All you have done is you take the example from Scot Mayers book and repeating what he had said again and again what he already told us in 2013. Although you"ve admitted your next example is unrealistic , you've tried to convince us that the features you had showed us is very cool that can not be used in the context of your example. Programs are not written with slogans,This topic can be explained very good with real life example code. You would take a real life example and step by step you could show us how free functions are so cool.