Mark Needham

Thoughts on Software Development

Scala: Do modifiers on functions really matter?

with 8 comments

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.

Be Sociable, Share!

Written by Mark Needham

August 13th, 2011 at 2:10 am

Posted in Scala

Tagged with

  • http://patforna.blogspot.com Patric Fornasier

    Visibility modifiers can also help to make code more expressive. If I’m looking at a variable or method that has a “private” modifier, I know that it’s not used anywhere else, which helps me reason about it. If it doesn’t have the modifier, I either have to find usages, do a search or just guess whether it’s used elsewhere.

  • http://twitter.com/markhneedham Mark Needham

    @290f8765c4c46352b65fc90107560f53:disqus that’s true. I’m also wondering whether if we have something as a private modifier somewhere that it shouldn’t be a public modifier somewhere else instead? 

    Scanning through our code base the private modifier seems to be used like this:
    1. To capture an intermediate state that gets reused in a few places
    2. For functions that are only used in that object – many could be useful elsewhere though
    3. To increase expressability of other code in an object

    For 2. I think we should be looking to pull those functions out to another object/trait so they can be reused.
    For 3. I think if you can find a nice way of chaining functions together either by having them on objects or with partial functions then code can be equally expressive without private functions.
    For 1. I guess it makes sense to reduce duplication in the code but I’m not sure if it makes the code easier to read since you have to click/follow a few functions to see what’s going on

  • http://twitter.com/ctford Chris Ford

    Marking methods private also prevents anyone from depending on logic that you might want to change or remove without notice. If methods that are intended only ever to be called internally are made public then you break encapsulation even if you don’t allow data to be mutated into an inconsistent state.

  • http://twitter.com/markhneedham Mark Needham

    @twitter-20753504:disqus that’s true. I guess I’m wondering whether it’s actually possible to write our code in such a way that we don’t ever actually use private methods. 

  • http://twitter.com/alexey_r Alexey Romanov

    Make it protected, of course. Easy to test (just extend the trait), and unrelated classes can’t call it.

  • http://twitter.com/markhneedham Mark Needham

    @twitter-19354604:disqus didn’t think of that! Will change the code on Monday!

  • http://twitter.com/gclaramunt Gabriel Claramunt

    Why not in an object? A formatting method in particular looks like an utility function, I don’t think it belongs to a trait.

  • Alois Cochard

    I agree with @twitter-14052358:disqus , this kind of pure utility function should be put in a helper function bag (singleton) … because there is no need of mocking them when testing.

    Providing *UTILITY* function thru trait isn’t a good idea IMO, just imagine you need to mix a trait that have the same method signature with a different functionality.

    Would really prefer composition here :)