Private parameters

I'm sure you've seen code like this:

/**
 * Loads HTML files from given URL-s.
 * @param {String[]} urls The URL-s to load.
 * @param {Object[]} alreadyLoaded For internal use only!
 */
function loadPages(urls, alreadyLoaded) {
    alreadyLoaded = alreadyLoaded || [];
    if (urls.length == 0) return alreadyLoaded;
    var url = urls.pop();
    var page = load(url);
    alreadyLoaded.push(page);
    return loadPages(urls, alreadyLoaded);
}

What I'd like to draw your attention to, is this second parameter - the parameter that you're not supposed to use, a private parameter.

Everybody knows about private methods - they are well respected citisens of OOP landscape. Similarly we have private instance variables. All good means of encapsulation.

But what about private parameters? Nobody talks about such things, but in my day-to-day work I see them popping up every now and then in various different codebases. How should I treat them. Are they a pattern or an anti-pattern?

We can definitely rewrite the above example, so that it doesn't use any private variables:

/**
 * Loads HTML files from given URL-s.
 * @param {String[]} urls The URL-s to load.
 */
function loadPages(urls) {
    return loadPagesRecursive(urls, []);
}

function loadPagesRecursive(urls, alreadyLoaded) {
    if (urls.length == 0) return alreadyLoaded;
    var url = urls.pop();
    var page = load(url);
    alreadyLoaded.push(page);
    return loadPagesRecursive(urls, alreadyLoaded);
}

Now the public loadPages acts as a simpler interface in front of a private and more complex loadPagesRecursive method. We have effectively transformed our private parameter into a private method.

That's actually how we would have written it in the first place in a language like Java that doesn't directly support optional parameters - forcing you to define a separate method when you need a different number of parameters.

Of course Java is mainly a great example of a very verbose language. Optional parameters are such a useful language feature, nobody ever argues against them. And private parameters sure are a very convenient thing too - the first code examples was shorter, there was just one method, no need to think up a name for our silly helper method.

But what kind of convenience are we talking about in here? It's the convenience of the library author - his convenience of writing less code.

With optional parameters, there's also the convenience of a library user - without optional parameters he would need to pass in the default values by himself, introducing lots of hairy duplication.

But private parameters provide absolutely no help for the user. Quite the contrary - he is forced to learn about this parameter that he is forbidden from using. Basically the private parameter is an implementation detail which we are revealing to the user.

Also, because not a single language that I know of supports the concept of private parameters, one has to rely on documentation to convey the meaning of these parameters being private. In the simplest case one could just skip documenting these parameters - when the documentation says there's just two parameters (although the method actually takes three) the user never needs to bother his head with our secret third parameter. But that logic breaks down as soon as somebody looks at the source code - then he will see the undocumented third parameters and wonder wether this was just forgotten to be documented.

At that point one might want to turn to his documentation tool for help on documenting these private paramters, but at this point I will say: STOP.

I feel like we've seen enough evidence already to conclude that private parameters are an anti-pattern. And JSDuck, which is an opinionated little duck, simply won't support such a nasty thing.

Instead JSDuck will provide you a warning when he sees you haven't documented all your parameters, to help in keeping your code and comments in sync.

Quack.

Kirjutatud 15. veebruaril 2013. Kommentaarid (361)

Why not support this valid JavaScript?

Every once in a while I get asked why doesn't JSDuck support a certain character in the names of various entities. The character is usually some punctuation like the dot (.) or dash (-). The names in question are the names of classes and class members (methods, properties, events, etc).

So why doesn't JSDuck allow you to document a class named My.Special-Class or method named my+method? Why doesn't the freaking tool just get out of the way and allow you to do what you want? Supporting just one more character can't be so hard - why not simply do it?

Three reasons:

It's not sensible

The problem here is that JavaScript, unlike most other object-oriented languages, doesn't require the names of object properties and methods to be proper identifier names. Objects are just hash tables - any string is a valid key, and therefore also a valid method/property name.

So when I implement support for dash and dot, the next user comes along and asks why doesn't JSDuck support colon? Then the third one comes and asks to support spaces. Soon we're talking about supporting the whole Unicode including Egyptian hieroglyphs.

A tourist studying Egyptian hieroglyphs

We need to practice some moderation. Thankfully JavaScript itself gives us some guidance on this: although we can name methods with any imaginable string, like so:

window["My class"]["ho-ho-hoo!"]();

only when using proper identifier names will they be convenient to use:

MyClass.hoHoHoo();

So, by only allowing proper identifier names, JSDuck is asking you to take the sensible route.

The main thing here is that JSDuck is opinionated. It wants you to write your code in a certain way. And if you want to do things differently it's going to be painful. In that case you might have chosen the wrong tool.

It's troublesome to implement

In addition to the above, supporting the whole range of possible characters is far from easy to implement. Even adding support for just one more punctuation character is a considerable amount of work.

Hard working woman

There's a lot of convenience that derives from the assumption that class and member names are always proper identifier names. It allows us to use the same names in URL-s, HTML id-s and other generated code without a need to do additional escaping.

For example when supporting dot in member names, we need to ensure we encode the dot somehow when using the name inside HTML id attribute, because the following is not valid:

<p id="ho.ho.hoo">

JSDuck is already doing this kind of escaping to support the $ character which is valid in JavaScript identifiers but invalid as HTML id. So an identifier $foo becomes S-foo in HTML. Not a prettiest solution, but it's a mandatory thing for a JavaScript documentation tool to support.

But supporting all kinds of other characters is just complicating the code base while helping only a rary minority of users who want to do some weird things.

It's not just JSDuck

Finally, using non-identifier names for classes and members is just asking for trouble. Even if JSDuck implements a support for it, you will soon face some other tool which also chokes on your unconventional code. Sure, you can have a slash (/) in your class names, but good luck with your filesystem if you want to save it into a file with the same name.

German shepherd jumping through a ring of fire

But in the end there's nothing to stop you. Go ahead, write the craziest JavaScript possible. I do encourage you. It's the land of the wild and brave. But it's not the land of great tooling support.

Photo credits: Het Leven, 1927, Copying Egyptian hieroglyphs; Lewis W. Hine, 1920, Woman with Machine; George Jackman, Ten lords a' leaping.

Kirjutatud 17. septembril 2012. Püsilink.

Singletons in Ruby

Ruby provides a nice builtin module that lets easily turn your class into a singleton:

require 'singleton'

class MyClass
  include Singleton

  def say
    puts "Hello"
  end
end

MyClass.instance.say  # ---> "hello"

Problem

But I'm not quite happy with that. I'm not talking about the general wide overuse of the singleton pattern. What bothers me, is that the fact of MyClass being a singleton is just an implementation detail and it shouldn't change how I'm interfacing with this class.

For example, I might decide that instead of having a singleton I'd just like to have a class with static methods:

class MyClass
  def self.say
    puts "Hello"
  end
end

Nice. But now I have to go through all of my code and replace all the uses of MyClass.instance.say with MyClass.say.

That's not good. The rest of my code shouldn't care if MyClass is implemented as a singleton or not.

Additionally I like my lines short. For me MyClass.say looks much cleaner and simpler to understand than MyClass.instance.say.

Maybe in Java and friends that's the best you can do, but in Ruby there sure is some better way.

Solution

So, after fiddling around a bit with some ruby meta-programming, I came up with my own improved version of the Singleton module:

require 'singleton'

module MySingleton
  def self.included(base)
    base.class_eval do
      # Include the builtin Singleton module
      include ::Singleton

      # Redirect calls from MyClass.method to MyClass.instance.method
      def self.method_missing(meth, *args, &block)
        self.instance.send(meth, *args, &block)
      end
    end
  end
end

You use it just like the standard Singleton:

require 'my_singleton'

class MyClass
  include MySingleton

  def say
    puts "Hello"
  end
end

With the important difference of how you call the methods on your instance:

MyClass.say  # ---> "hello"

Oh, and if you need it, you can still use the old way of calling out the singleton. This will still work:

MyClass.instance.say  # ---> "hello"

Extra

I have always found static methods in ruby to be too painful to define. You need to prefix all the static methods with self.:

class MyClass

  def self.foo
  end

  def self.bar
  end

  def self.baz
  end

end

And then, when you decide to change them all into instance methods, you'll need to remove all the self. prefixes. Not good at all.

But with our new Singleton implementation we can just turn this same class into a singleton and make it behave as a class with static methods:

class MyClass
  include MySingleton

  def foo
  end

  def bar
  end

  def baz
  end

end

And when you change your mind, you just remove that one line and you've got a nice instantiable class again.

A win-win I would say.

Kirjutatud 10. septembril 2012. Püsilink.

Trinoloogialeht

Eesti Trinoloogide Maja. Eesti trinoloogiahuviliste avalik kogunemiskoht. info@triin.net

Peamenüü

Viimased artiklid

RSS, RSS kommentaarid, XHTML, CSS, AA