Closures for class/module privacy considered harmful
sidekicksrc.com
sidekicksrc.com
Back to the blog. Contrast to the claim, closure for class/module privacy is great because it separates inner implementation from public interface. I really don't want any outside code to touch the private code. Because tomorrow I might change the inner implementation, function signature, break the function into two pieces, or proxy-call other libraries. And I want the assurance that the change won't break any calling codes.
Public function is like global variable. Anyone can access it anywhere and anytime. You don't know how, where, and when people call it. If you change its signature, you pretty much have to hunt down every call of it to retrofit. Private codes have no such issue. It's best to limit the scope of codes that are intended to be private.
Testing private code is a non-issue. Nobody outside cares about your private functions. They care about your public functions serving as the public interface. You test your public functions as your users would call them. Your public functions in turn exercise the private functions.
If you really want to test the private functions, write private tests in the same scope as the private functions to call them.
Edit: Why not make all variables global? Why not just use convention to label a globally scoped variable as "global" or as "local"? You can make it work as a convention. Now apply that to the whole language and to all the developers ever use it.
Why not make everything global? For obvious reasons - modularity, memory consumption, and inconvenience of lengthy variables names.
For example I use your library and everything goes great until I'm stuck because I need to have an information hidden in a private field, if I'm in Python I would do it and add a note, fixme, todo, whatever that this is a hack and things may break in a future, but my code would work right now. And I can fork your library later and submit changes. If this is a language with real private support the only way is to use hacks (reflection) which is the same as using the field directly like in python just with some additional PITA, or to fork your library and maintain it until you merge changes, or if you not, I have to maintain it forever.
I can't see why this would not also apply to Javascript, other than that Javascript is rarely written in a very pure "OO" way.
For what its worth I find _private methods to be a horrible hack, I'd much rather have true private methods and force the next developer to think about whether they truly want to make that method public in the hope they'd consider restructuring it.
(Yes, this is a deficiency in Java amongst other languages. You don't want to be e.g. wading through the lower details of font kerning when trying to use an edit box widget, even when those sub-components need individual testing.)
(It's certainly not a tooling deficiency as there are tools that allow testing private methods in Java. IME the best developers make an explicit choice not to use them)
Unit testing has particular value because it avoids m*n problems. But that doesn't necessarily mean that m and n need to be separately addressable entities in your API. But if you unit test at the API level, then you're forced to do that.
For example, consider a web browser widget that's part of a UI framework. A web browser is an enormously complex piece of software with hundreds of individual modules doing various things. But the API at the UI toolkit level is much, much simpler; an URL and a handful of properties and methods relating to history navigation. Trying to unit-test the web browser at the API level would be ridiculous; no less ridiculous than having your testing constraints drive enormous complexity into the developer-facing API.
Inside the web browser code there will be more detailed things that should be tested - internal APIs. But the point is that these are APIs and should be built as such; they will likely need to be used by other people working on the same code. Even if not, you need this level of structure so that you can build comprehensible software. If every class can monkey around in the internals of every other one, you get an unmaintainable mess very quickly.
It does ignore the other benefit of module-closures, though (avoiding namespace collisions). Explicitly exposing your "private" functions (prefixed with _) in the module object would be a better way of achieving what the author wants.
When I read about symbols in upcoming ES6 I can't get rid off the sense of anxiety because I fear thing would get worse, the only hope is that browser vendors would implement some means to inspect private state of the objects that use Symbols.
By the way, this was one of the reasons why Guido van Rossum had chosen not to add private state in Python: https://plus.google.com/115212051037621986145/posts/7wpbQTPR...
In other situations you don't have to listen, but if a popular library doesn't pay attention to backward compatibility then they'll end up in a situation where major customers keep using an older version of their library and nobody wants to upgrade. And unless you want to keep maintaining multiple versions, you want them to upgrade.
I've encountered the exact same issues that they have. It's frustrating when code wrapped up in a function prevents you from testing or experimenting in a REPL. It's infuriating when a framework wraps your code in one of these mega-lambdas so you can't get at it. There are many programming techniques that require the ability to breach encapsulation when appropriate.
Meanwhile, the virtues of enforced privacy are overrated. There are countless ways to screw up software; trying to lock things down so the next guy can't screw them up (preventing access, etc.) is a classic mistake. Modularity is extremely important in systems design, but not as an enforcement mechanism. It's an organizational tool. It's about decomposition and factoring, not hiding things so that only you can control them.
It's worth noting that Smalltalk doesn't have private methods [1], and that this was regarded as a feature not a bug. That alone shows that there's no particular link between enforced-privacy and OO, or even enforced-privacy and encapsulation.
To some extent this is a matter of taste, but I come down on the side that sees little value (and considerable drawbacks) in the privacy fetish. It's one of those things that people believe in because it sounds like things ought to work that way, when in reality they do not.
[1] http://stackoverflow.com/questions/7399340/smalltalk-public-...
Another point is that the Javascript enforced privacy pattern only supports private, so 2 internal classes cannot get at each other even if they are maintained together as a package. That encourages creating god objects which is not surprisingly what I commonly see in projects that use enforced privacy in Javascript.
Just tried this in the developer console:
// module 'm' exposes 'p' that uses 'f' internally. Exposes
// 'f' for testing purposes.
var m = (function() { var f = function() { return 'a'; }; var p = function() { return f(); }; return {'p': p, 'internalF': f};})();
m.p();
// 'a'
m.internalF();
// 'a'
m.internalF = function() { return 'haxor';};
m.internalF();
// 'haxor'
m.p();
// 'a'As for extension, it's a pattern that is useful in some circumstances. It's not really something you would chose to use if you needed extension. I was going to say it was like saying a Singleton is harmful if you then change your mind later and decide you want multiple instances but I'm pretty sure I risk being called out for hyperbole.
Generally though I find the notion of struggling to wedge privacy into JS code a waste of effort, there are much cleaner patterns. You are always relying on personal/group discipline and good habits when coding with JS anyway so why start by disadvantaging yourself.
And this is exactly why I make implementation private. Otherwise my implementation becomes my public interface and I can't change it without breaking somebody else's patch.
> If you’ve got a tricky interaction between a few private functions it’s very helpful to be able to test them!
Then refactor those tricky functions into another class with testable interface.
var SomeModule = (function(trickyFunctionality) {
function publicFunction() {
trickyFunctionality.doTheTrick()
}
return {
publicFunction: publicFunction
}
})(new Tricky())This roughly matches what I read elsewhere, e.g. http://macwright.org/2013/01/22/javascript-module-pattern-me...
If you need to avoid this technique entirely because you're so frequently needing to unit test private methods, you have a design problem, not a testing problem.
Readability is subjective. Personally I tend to find this style a bit more readable than trying to use a naming convention to indicate privacy, as suggested later in the article.
Tooling -- any real world examples of this? It seems to me tooling would only need to worry about the public interface, not the private details.
"True privacy is a bad idea in OO" - You didn't limit this statement to javascript, so I just want to say this is ludicrous. Access control is an extremely valuable tool when you're building a large system where development may be spread amongst many teams. If you just meant client side JS, I would say your statement is debatable.
When you utilize true privacy, you're taking a very disciplined approach to building software. You prevent monkey patching or tinkering with the internal state from components who should not be concerned with that object's internal state. When you need changes, it forces you to think about how your changes impact the overall structure of your application, and whether you need to restructure aspects of your application in response to those changes. Without true privacy, sure, you could just patch some "private" method and move on with your life. As you utilize this technique more and more, however, and your application grows, it has the potential to turn into a big headache.
Enforced/True privacy is very bad, and the badness is multiplied by the fact that in Javascript it cannot be fine-tuned so when you are making it private for random application code, you are also making it private for other internal classes.
Those warnings are not part of the language, and can be done with underscore prefixed Javascript too in your build step, a fine example of programming into one's language.
Could that code be useful? Sure, but that's not the point.
Information hiding is one of the core concepts in OOP:
http://en.wikipedia.org/wiki/Information_hiding
It's not even constrained to OOP, take C for instance: why it is that all functions are not exported in a shared library? Are they nefariously hiding code they don't want you to see? No, it's just that they are minimizing the interface between components, which is a concept as old as modular programming itself.
It makes change easier to contain and allows one to reason over large systems.
This is a good thing. Hiding implementation details is a good thing. Using closures to implement private functions in javascript is not bad. It's advocated in "Javascript, the good parts", as a pattern.
Should one try and write javascript as if it were java? No, and overuse of this pattern leads to a bunch of boiler plate. One usually tries to remain state-less and write deterministic, side-effect free functions that do not depend on closed variables.
Is it handy tool in some cases to implement DRY? Yes. Should it be considered harmful? No.
var DEV = true;
(function() {
var priv = function() {};
if(DEV)
this.priv = priv;
})();
and then use Closure Compiler with option:
--define DEV=falseJust create a second entry point that exports everything you might want to test. "Secure it" (there is no real security here) to be only callable if a read-only global flag was set when the object was created.
In your private unit tests you set that flag, create the object, and get access to privates. In your normal code, there is no way to access those functions.
Yes, it is a hack. But I firmly believe that it is acceptable to have hacks to enable unit testing.
Whether or not any type of privacy enforcement is a good idea is a debate that I leave to others.
function myModuleReally() {
return [useMe, testMe];
}
function myModule() { return myModuleReally()[0]; }
It'd be nice if the programming environment gave us a "can opener" (not globally available) to open up closures we've made -- like http://gbracha.blogspot.com/2012/07/seeking-closure-in-mirro... -- but we can do plenty without it.And I'm ready to upvote the first blog post entitled "the 'considered harmful' meme considered harmful".
function privateFunction() {
}
that is sugar meaning there is a variable named privateFunction and it points to a function. So the object that is eventually returned closes around these external variables.Here's four variations that hopefully show the difference.
edit: bad link
*edit : i should add i have been making use of the fact that a lot of my modules are event emitters to work around this. so even if i don't expose the function as such, i trigger the event rather than use the function directly.
Also article is kinda crap as it fails to understand the reason they are truly necessary. But upvoting to generate discussion here.
We actually depend on real private methods.
just because what you do every day makes it useless, it's presumptuous to assume it's the same for everyone.
Exactly why I asked...
If you are running untrusted code in JS then real private methods have only given you a very false sense of security. You should have run it in a sandboxed process instead.
He basically exposes them while in a dev environment, and then uses a build tool to make them actually private. I agree with weego's comment though, its something that isn't usually worth the tradeoffs, as long as your team has discipline.