2

When I was programming in Java, I used to have objects and managers for them. You know, a class (typically singleton), which would hold a collection of objects of a certain class and let to conviniently manage them. Now, in Scala, I am finding myself more and more in the situation, where it is quite tempting to put all that functionality in a companion object and avoid creating the distinct manager object.

It all starts with giving IDs to instances and then... why not having the collection in the companion object? And if the collection is there, why not having all the methods to work with the collection in there? And so, the manager is not needed anymore. However, one pecularity is that the companion object usually has a single name like Car (not like Cars or CarManager which presume plurality), so methods that operate with plurals look weird in their coupled wording with the object name.

I would like to know your opinion on this situation and to know if this approach is preferable over the so-seemed unnecessary bloated manager pattern. Any references to any articles on that would also be appreciated.

noncom
  • 4,962
  • 3
  • 42
  • 70
  • 1
    You can check this: https://github.com/novus/salat/wiki/SalatWithPlay http://www.playframework.org/documentation/2.0.1/ScalaTodoList – Sergey Passichenko May 03 '12 at 09:34
  • Ummm... not quite sure how this relates to the question in anyway, but thanks anyway, I'll go read it! (except for the ScalaTodoList tutorial, since I have long passed it). – noncom May 03 '12 at 10:30
  • 2
    They use companion objects to keep in it all model operations. If I understand you correctly, you try to do the same. – Sergey Passichenko May 03 '12 at 11:41
  • Oh, did not recognize it first. The Play framework is a different case, but with Salat, they seem to really practice an approach similar to what I am asking about. And they're mixing it with what thoredge has suggested - the dependency injection! – noncom May 03 '12 at 12:34

2 Answers2

4

As simple as possible is good; and a collection inside an object is indeed simple. However you should also avoid making your objects dependent on static object. That will create a rigid structure and will make testing more difficult.

I would take a look at the cake-pattern (see How do you do dependency injection with the Cake pattern without hardcoding?). This way you can have the CarManager in an object and mix it into your dependencies through a CarRepositoryComponent.

Non-compiled example:

val someService = new SomeService 
  with MyRepairServiceComponent with CarCollectionRepositoryComponent
someService.repairCar(8)

trait SomeService extends RepairServiceComponent with CarRepositoryComponent {
  def repairCar(id: Int): Status = repairService.repair(carRepository.get(id));
}

trait CarRepository {
  abstract def get(id: Int): Car
}
trait CarRepositoryComponent {
  abstract def carRepository: CarRepository
} 

object CarManager extends CarRepository {
  private var cars = Map[Int, Car]()
  def get(id: Int): Car = cars(id)
}
trait CarCollectionRepositoryComponent {
  def carRepository = CarManager
}
Community
  • 1
  • 1
thoredge
  • 12,237
  • 1
  • 40
  • 55
3

That's effectively turning a companion object into a singleton which is more of an anti-pattern than a pattern of good design. Unit testing is the main reason for this being an issue (this has been covered many times before by many people smarter than me).

An object ideally shouldn't maintain mutable state of any kind for these reasons (it'll lead to a maintenance nightmare trust me).

Sean Parsons
  • 2,832
  • 21
  • 17
  • Well, I am not using unit testing and not going to anyway soon... and I have to use much mutable state because I program resource-demanding and time-critical applications.. So I understand what you are saying, but it looks like that you are speaking from experience that is orthogonal to mine :D.. and since I do not fully adhere to functional programming, I will have to put mutable state singletions in somewhere. And the difference is that - should it be a separate object or not. If it is a bad design, and there is a way to acheive same productivity the other way, I would be glad to hear how. – noncom May 03 '12 at 09:51
  • I think blaming code for bad tools limitations is not a particularly good thing. Scalamock can mock objects. – Daniel C. Sobral May 03 '12 at 15:18
  • Having a class for managing your instances isn't an anti-pattern, the singleton pattern is. – Sean Parsons May 04 '12 at 09:39