2

I like to write Scala code without classes, using just functions and objects.

e.g.

object Something {
  def foo() = {
    SomeDependency().doIt()
    ...
  }
}

object SomethingElse {
  def baz = {
    val x = Something.foo()
    ...
  }
}

However, I run into the issue that I can't test that code, since I can't mock anything out. I'd have to refactor the code and make it take a parameter and then have to needlessly instantiate classes.

class Something(someDependency: SomeDependency) {
  def foo() = {
    someDependency.doIt()
    ...
  }
}

class SomethingElse(something: Something) {
  def baz = {
    val s = new SomeDependency()
    val x = new Something(s).foo()
    ...
  }
}

What I sometimes do is use implicits but it gets cumbersome since you need to add it to every method.

object Something {
  def foo()(implicit someDependency: SomeDependency) = {
    someDependency().doIt()
    ...
  }
}

object SomethingElse {
  def baz(implicit something: Something) = {
    val x = something.foo()
    ...
  }
}

In other languages like Python/JS, you can just mock the dependency directly, instead of making your class take in dependencies. Is there any way to solve this, or is just an antipattern to write scala without classes.

cigien
  • 57,834
  • 11
  • 73
  • 112
SASA
  • 21
  • 4
  • 1
    You can't have your cake and eat it. If you don't want to add arguments to your methods then you have to limit tests to verifying returned value. – michaJlS Oct 29 '20 at 20:33
  • Regarding necessity to add implicit parameters to every method please see https://stackoverflow.com/questions/64267742/pass-implicit-parameter-through-multiple-objects https://stackoverflow.com/questions/59175012/how-to-wrap-a-method-having-implicits-with-another-method-in-scala/ – Dmytro Mitin Oct 30 '20 at 09:51
  • Please don't vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right, under the [CC BY-SA 4.0 license](https://creativecommons.org/licenses/by-sa/4.0/), for Stack Exchange to distribute that content (i.e. regardless of your future choices). By Stack Exchange policy, the non-vandalized version of the post is the one which is distributed, and thus, any vandalism will be reverted. If you want to know more about deleting a post please see: [How does deleting work?](/help/what-to-do-instead-of-deleting-question). – cigien Apr 22 '21 at 00:38

1 Answers1

2

Despite being able to work imperatively in Scala, Scala is designed for Functional Programming. The fact that you need to mock things means that your functions have side effects, therefore, they are not pure functions so it isn't functional programming.

There are mock frameworks in Scala but they don't allow you to overwrite the functionality of your functions like you can do with Python, for example.

You could use also high order functions to pass dependencies, something like this:

object Something {
  def foo(someDependencyFunction: A => B): C = {
    someDependencyFunction(...)
    ...
  }
}

object SomethingElse {
  def bar(SomethingFoo: (A => B) => C)(someDependencyFunction: A => B): D = {
    SomethingFoo(someDependencyFunction)
      ...
  }
}

But I don't really see the point of avoiding classes, maybe if you explain why you don't want to use classes someone can help better on a solution

Javier Montón
  • 4,601
  • 3
  • 21
  • 29