Factory Method with unnecessary parameters - scala

Let’s say we have a factory trait
trait Factory {
def createObject(paramA, paramB)
}
And now we have implementations of this Factory - FactoryV1 and FactoryV2 which are selected at runtime. While FactoryV2 uses both params to create object, FactoryV1 uses only paramA. So, when we call FactoryV1’s createObject method we pass an unnecessary parameter in paramB. How bad is passing an extra parameter? Some alternatives:
One way to improve upon it is to have paramB as a Scala Option, and depending on the factory being used, we pass None for FactoryV1.createObject and Some for FactoryV2.createObject.
Another alternative would be to have two methods in the base trait, one with just paramA and another with both parameters. Depending on the factory being used (V1 or V2), we call the appropriate method with 1/2 parameters (I don’t see a very clean way of doing this though).
What are other alternatives? I am inclined towards having a single factory method with Option parameters for those params that are not needed in all implementations of the factory.
Essentially what do we do when Factory implementations don't need all parameters of the Factory method?

I'd say it all depends on how you want to handle the absence of second parameter where you require one.
val factory: Factory = new FactoryV2 // this is the one that needs both params to create an object
// Assuming signature createObject(param1, param2 = default)
// if you use default parameter, is it ok to create an object with default value? THis may be difficult to notice.
factory.createObject(param1)
// Assuming signature createObject(param1, Option[param2])
// Is it ok to fail when second param not supplied?
factory.createObject(param1, None)
Choose your solution based on desired semantics.

Related

Pass a class name as string argument to create instance

Is there any possible way to pass a class name/path as String argument to call it in code in runtime?
Im working with some legacy code and i have no way to change it globally. Creating new integration to it suggest me to create new copy of class X, rename it, and pass new instance of Y i have created manually. My mind tells me to pass Y as some kind of argument and never copy X again.
I don't quite understand why you (think that) you need to do what you are trying to do (why copy class in the first place rather than just using it? why pass classname around instead of the class itself?), but, yeah, you can instantiate classes by (fully qualified) name using reflection.
First you get a handle to the class itself:
val clazz = Class.forName("foo.bar.X")
Then, if constructor does not need any arguments, you can just do
val instance = clazz.newInstance
If you need to pass arguments to constructor, it gets a bit more complicated.
val constructor = clazz.getConstructors().find { c =>
c.getParameters().map(_.getParameterizedType) == args.map(_.getClass)
}.getOrElse (throw new Exception("No suitable constructor found")
// or if you know for sure there will be only one constructor,
// could just do clazz.getConnstructors.headOption.getOrElse(...)
val instance = constructor.newInstance(args)
Note though, that the resulting instance is of type Object (AnyRef), so there isn't much you can actually do with it without casting to some interface type your class is known to implement.
Let me just say it again: it is very likely not the best way to achieve what you are actually trying to do. If you open another question and describe your actual problem (not the solution to it you are trying to implement), you might get more helpful answers.

Quick Documentation For Scala Apply Constructor Pattern in IntelliJ IDE

I am wondering if there is a way to get the quick documentation in IntelliJ to work for the class construction pattern many scala developers use below.
SomeClass(Param1,Parma2)
instead of
new SomeClass(param1,Param2)
The direct constructor call made with new obviously works but many scala devs use apply to construct objects. When that pattern is used the Intelij documentation look up fails to find any information on the class.
I don't know if there are documents in IntelliJ per se. However, the pattern is fairly easy to explain.
There's a pattern in Java code for having static factory methods (this is a specialization of the Gang of Four Factory Method Pattern), often along the lines of (translated to Scala-ish):
object Foo {
def barInstance(args...): Bar = ???
}
The main benefit of doing this is that the factory controls object instantiation, in particular:
the particular runtime class to instantiate, possibly based on the arguments to the factory. For example, the generic immutable collections in Scala have factory methods which may create optimized small collections if they're created with a sufficiently small amount of contents. An example of this is a sequence of length 1 can be implemented with basically no overhead with a single field referring to the object and a lookup that checks if the offset is 0 and either throws or returns its sole field.
whether an instance is created. One can cache arguments to the factory and memoize or "hashcons" the created objects, or precreate the most common instances and hand them out repeatedly.
A further benefit is that the factory is a function, while new is an operator, which allows the factory to be passed around:
class Foo(x: Int)
object Foo {
def instance(x: Int) = new Foo(x)
}
Seq(1, 2, 3).map(x => Foo(x)) // results in Seq(Foo(1), Foo(2), Foo(3))
In Scala, this is combined with the fact that the language allows any object which defines an apply method to be used syntactically as a function (even if it doesn't extend Function, which would allow the object to be passed around as if it's a function) and with the "companion object" to a class (which incorporates the things that in Java would be static in the class) to get something like:
class Foo(constructor_args...)
object Foo {
def apply(args...): Foo = ???
}
Which can be used like:
Foo(...)
For a case class, the Scala compiler automatically generates a companion object with certain behaviors, one of which is an apply with the same arguments as the constructor (other behaviors include contract-obeying hashCode and equals as well as an unapply method to allow for pattern matching).

Scala Argument Capture of External Class

So I want to check arguments that I send to an external class that I do not control. The external class is assumed tested, I simply want to test if I passed it the right parameters. I have tried some combination of ArgumentCaptor etc, but not much luck
import org.ABC.ExternalClass
case class Foo(i:Int, j: Int...) {
val EC = CreateExternalClass()
def CreateExternalClass(): ExternalClass = {
new ExternalClass (i, j, ....many parameters)
}
}
I think you are getting things wrong here: you can only use an ArgumentCaptor on calls to mocked objects. You can't use them to "intercept" arbitrary calls between all kinds of objects.
Meaning: you could only use an ArgumentCaptor if you would be using a mocked ExternalClass object. But then you would not need to capture, as you probably could do simply method call argument verification.
But of course, you can't use Mockito to mock that call to new in your production class. The options you have:
Turn to PowerMockito or JMockit; frameworks that allow to mock calls to new. Not recommended.
Rework your production code to not do that call to new. Probably not helpful here; as this class might already be a wrapper around that external class
Go for checking on the created object: check if you could use getter methods to simply query the newly created object to have the values that you expect to show up inside

Override a method in a mock object

I need to write a unit test in which one of the dependencies of the tested object will be mocked. In that mocked object I would like to override one function (I do not care about the other functions at all).
What I need to do, is to provide a completely new implementation of that function. I am not particularly happy with providing mockito-style when / thenResult pairs for each potential input, i.e. I do not want to write:
when(mock.foo(5)).thenResult(3)
when(mock.foo(7)).thenResult(121)
...
I would rather like to write something like:
mock.foo = (a: Int) => if (a == 5) 3 else ...
Which mocking framework should I choose to substitute the whole implementation of a function in an easy way?
You don't need a mocking framework at all if you're only overriding one method and want to do it by actually defining the method.
If it's a class, just extend your class, override the method and inject your extension.
If it's an object or a final class of course you can't extend, but then you wouldn't be able to mock with many frameworks either, or inject an alternate easily.
http://scalamock.org/user-guide/advanced_topics/
See "onCall" method
(fooMock.increment _) expects(*) onCall { arg: Int => arg + 1}

Dynamic Proxy using Scalas new Dynamic Type

Is it possible to create an AOP like interceptor using Scalas new Dynamic Type feature? For example: Would it be possible to create a generic stopwatch interceptor that could be mixed in with arbitrary types to profile my code? Or would I still have to use AspectJ?
I'm pretty sure Dynamic is only used when the object you're selecting on doesn't already have what you're selecting:
From the nightly scaladoc:
Instances x of this trait allow calls x.meth(args) for arbitrary method names meth and argument lists args. If a call is not natively supported by x, it is rewritten to x.invokeDynamic("meth", args)
Note that since the documentation was written, the method has been renamed applyDynamic.
No.
In order for a dynamic object to be supplied as a parameter, it'll need to have the expected type - which means inheriting from the class you want to proxy, or from the appropriate superclass / interface.
As soon as you do this, it'll have the relevant methods statically provided, so applyDynamic would never be considered.
I think your odds are bad. Scala will call applyDynamic only if there is no static match on the method call:
class Slow {
def doStuff = //slow stuff
}
var slow = new Slow with DynamicTimer
slow.doStuff
In the example above, scalac won't call applyDynamic because it statically resolved your call to doStuff. It will only fall through to applyDynamic if the method you are calling matches none of the names of methods on the type.