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.
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...
Also article is kinda crap as it fails to understand the reason they are truly necessary. But upvoting to generate discussion here.
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.
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 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.
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.
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.
Just 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.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...
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=false*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.