Mark is a graph advocate and field engineer for Neo Technology, the company behind the Neo4j graph database. As a field engineer, Mark helps customers embrace graph data and Neo4j building sophisticated solutions to challenging data problems. When he's not with customers Mark is a developer on Neo4j and writes his experiences of being a graphista on a popular blog at http://markhneedham.com/blog. He tweets at @markhneedham. Mark is a DZone MVB and is not an employee of DZone and has posted 553 posts at DZone. You can read more from them at their website. View Full User Profile

Scala: Do modifiers on functions really matter?

08.15.2011
| 3201 views |
  • submit to reddit

A couple of colleagues and I were having an interesting discussion this afternoon about the visibility of functions which are mixed into an object from a trait.

The trait in question looks like this:

trait Formatting {
  def formatBytes(bytes: Long): Long = {
    math.round(bytes.toDouble / 1024)
  }
}

And is mixed into various objects which need to display the size of a file in kB like this:

class SomeObject extends Formatting {
 
}

By mixing that function into SomeObject any of the clients of SomeObject would now to be able to call that function and transform a bytes value of their own!

The public API of SomeObject is now cluttered with this extra method although it can’t actually do any damage to the state of SomeObject because it’s a pure function whose output depends only on the input given to it.

There are a couple of ways I can think of to solve the modifier ‘problem’:

  • Make formatBytes a private method on SomeObject
  • Put formatBytes on a singleton object and call it from SomeObject

The problem with the first approach is that it means we have to test the formatBytes function within the context of SomeObject which makes our test much more difficult than if we can test it on its own.

It also makes the discoverability of that function more difficult for someone else who has the same problem to solve elsewhere.

With the second approach we’ll have a dependency on that singleton object in our object which we wouldn’t be able to replace in a test context even if we wanted to.

While thinking about this afterwards I realised that it was quite similar to something that I used to notice when i was learning F# – the modifiers on functions don’t seem to matter if the data they operate on is immutable.

I often used to go back over bits of code I’d written and make all the helper functions private before realising that it made more sense to keep them public but group them with similar functions in a module.

I’m moving towards the opinion that if the data is immutable then it doesn’t actually matter that much who it’s accessible to because they can’t change the original version of that data.

private only seems to make sense if it’s a function mutating a specific bit of data in an object but I’d be interesting in hearing where else my opinion doesn’t make sense.

 

From http://www.markhneedham.com/blog/2011/08/13/scala-do-modifiers-on-functions-really-matter

Published at DZone with permission of Mark Needham, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Roger Lindsjö replied on Mon, 2011/08/15 - 6:26am

I like to keep helper functions private unless they are meant to be in the interface of the object. Other classes otherwise has a tendency to start using these helper methods thus causing "strangeness" in the code.
Say you have a class where you'd like to format your bytes so you can use them for your presentation. Now, for simplicity you make this method public so it is easier to test. Other developers can now start using it as a utility which will "fix" this method for future changes. Your original class not gets a change in requirements to format the display differently but since the original method is used by other classes a new helper has to be created and the old one kept even though it no longer has any connection to the original class.
I try to avoid testing "inner functionality" directly. I should be able to test the effects of it through the public or possible protected interface.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.