Why I need that field like that - scala

case class AlertWindowDto(id: String)
protected val InitialWindowPeriodOneOnPeak = AlertWindowDto(ValidId)
protected val ValidId = "someSite"
I saw these there lines in different different classes. just I put together for understanding.
In general, If i am creating an dummy or some object of Class, then I give some value or null or empty string. What is the need of creating another field ValidId and assign some value and assign that field to final object.
is there any benefit, or anything help in test cases.
could you please help me.

Imagine this:
protected val InitialWindowPeriodOneOnPeak = AlertWindowDto("someSite")
Does it convey the information that "someSite" is a valid id for an alert window?
This is a trivial example, but the general idea is that sometimes breaking down expressions and assigning names to them is great for expressing meaning.
I would also add that the more this naming information is in the types, the better. For instance, here's another way of achieving the same result, without using a variable name.
case class ValidId(value: String) extends AnyVal
case class AlertWindowDto(id: ValidId)
protected val InitialWindowPeriodOneOnPeak = AlertWindowDto(ValidId("someSite"))
Same information, but the "valid id" information is now stored in the type system.

Related

Case class Members not accessible via Companion Object

Lets start off with a story
I am in contact with a fictious club namd Foo where people have registered for a party. The manager has asked me to maintain separate list of member names and member ids. The manager came to me one day and told about the problem. I as a developer playing around with scala gave him a solution like the aforementioned.
I wanted to maintain a class which will contain the name of the members and their ids. The code was very crude in nature and I absolutely had performed no validations
STEP 1: I created a class called NonEmptyFoo
case class NonEmptyFoo(bar1:String,bar2:String)
while drinking beer in the club, I found few people registering
STEP 2: Adding users (username,userid) both are String objects
val member1=NonEmptyFoo("member1","Foo_member1")
val member2=NonEmptyFoo("member2","Foo_member2")
val member3=NonEmptyFoo("member3","Foo_member3")
many people registered later, which was really good for the manager
STEP 3: Creating separate lists for username and userid
val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip
Whoooah! my solution seemed to work unless one day the manager came and told me;
"Man! people are so excited, that at times, they are registering without even entering the data; I am not able to get the correct list of member names and their ids as the list have many empty fields. This got on my nerves.
I assured the manager of the club to provide him with a robust solution the next day.
Two things came to my mind
1. If I write the code from scratch I need to remove the old code and the new code may not be readable
2. I need to keep the code readable and make it in a way such that the new developer can find it easy to maintain the new code and add/remove features from it
At night I thought to add abstractions to it. I added the following code
STEP 1 Created a trait Foo with NonEmptyFoo for users with valid entry and EmptyFoo for people with invalid entries
trait Foo
case class EmptyFoo() extends Foo
case class NonEmptyFoo(bar1:String,bar2:String) extends Foo
object Foo{
def apply(bar1:String,bar2:String)= (bar1,bar2) match{
case (x,y)=>if(x.isEmpty||y.isEmpty) EmptyFoo() else NonEmptyFoo(x,y)
case _=> EmptyFoo()
}
}
The above code has benefits. First off I am able to validate users with valid entry and users with invalid entry. Secondly I am abstracting out the empty and non empty Foo to only Foo such that the new methods can easily be added into Foo and implemented thereby in the child classes which as a result hides the inner implementation.
As the user enters a valid data as under
val mamber1=Foo("member1","Foo_member1")
The output on the worksheet is being shown as
member1: Product with Serializable with Foo = NonEmptyFoo(member1,Foo_member1)
and, when someone misses to enter one of the fields as given below
val member2=Foo("member2","")
The output on the worksheet is being shown as
member2: Product with Serializable with Foo = EmptyFoo()
Interesting!! it works...
Please be little patient;
I am able to perform an abstraction and able to come out with a minimal yet good solution. But, I was facing real problem when I wrote the code as follows
val member1=Foo("member1","Foo_member1")
val member2=Foo("member2","Foo_member2")
val member3=Foo("member3","Foo_member3")
val clubMembers=List(member1,member2,member3)
//heres where the problem occurs
val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip
Whooah! I got stuck here, because the compiler, in the lambda expression given below
x=>(x.bar1,x.bar2)
was not able to recognize bar1 and bar2.
But, this solution worked well;
val member1=NonEmptyFoo("member1","Foo_member1")
val member2=NonEmptyFoo("member2","Foo_member2")
val member3=NonEmptyFoo("member3","Foo_member3")
val clubMembers=List(member1,member2,member3)
//heres where the problem occurs
val (memName,memId)=clubMembers map(x=>(x.bar1,x.bar2)) unzip
Apparently, the solution violates abstraction since I am explicitly using the inner class names whereas I should have made use of the name of the trait from where based upon the validation, the compiler shall infer the need for instatiation of the objects as per the inner classes.
Could you please suggest what could be wrong with the new solution.
The reasons due to which the compiler did not recognize bar1 and bar2 will be highly appreciated. Yes alternate solutions do exist yet I would love to be suggested with the problems existing solution and that may be followed by an alternate solution which completely upon your discretion.
Thanks in advance for help!
Inferred type of clubMembers is List[Foo] (even though concrete elements are instances of NonEmptyFoo) and since Foo doesn't have bar1 and bar2 fields, you can't access them in your map invocation. One possible solution would be to add bar1 and bar2 to the Foo:
sealed abstract class Foo(val bar1: String, val bar2: String)
case object EmptyFoo extends Foo("", "")
case class NonEmptyFoo(override val bar1: String, override val bar2: String) extends Foo(bar1, bar2)
object Foo {
def apply(bar1: String, bar2: String): Foo = {
if (bar1.isEmpty || bar2.isEmpty) EmptyFoo else NonEmptyFoo(bar1, bar2)
}
}

Enforce values a class member can be assigned : Scala

I intend to restrict the values the string member of my class can take. For eg: for a member named country, only allowable values should be the countries that i have defined like 'US', UK, CN, etc. This constants need to be string constants.
I thought of using Enum, but that does not give me flexibility with the String constants. Or may be i am not aware of how to use it.
Any suggestions?
What is the problem with the enum? Seems like a good fit for what you need. Here is an example:
object Country extends Enumeration {
val US = Value("United States")
val UK = Value("United Kingdom")
}
case class MemberCountry(country: Country.Value)
//example instantiation
MemberCountry(Country.UK)
MemberCountry(Country.withName("United States"))
Enum support is not that good in Scala. First, scala's built-in Enumeration is crap, don't use it.
The common approach for enumerations is sealed trait/class:
sealed abstract class Country(val name:String)
object Country {
case object US extends Country("US")
case object UK extends Country("UK")
case object CN extends Country("CN")
val values = Set(US, UK, CN)
}
Country.values.find(_.name == "US")
It has one problem, if you want the list of all possible values, you need to enumerate them yourself (the values field in the example above).
However, there are alternatives that solve that problem.
You can go with macro (check this thread).
Or use third-party library.
Enumeration has its strengths and weaknesses in Scala.
You could use any approach highlighted above namely:
Enumeration subclass
Use Sealed Trait/Class.
Both approaches have benefits and potential tradeoffs. It might be worth reading through this informative article on this issue:
http://underscore.io/blog/posts/2014/09/03/enumerations.html

Scala type alias with companion object

I'm a relatively new Scala user and I wanted to get an opinion on the current design of my code.
I have a few classes that are all represented as fixed length Vector[Byte] (ultimately they are used in a learning algorithm that requires a byte string), say A, B and C.
I would like these classes to be referred to as A, B and C elsewhere in the package for readability sake and I don't need to add any extra class methods to Vector for these methods. Hence, I don't think the extend-my-library pattern is useful here.
However, I would like to include all the useful functional methods that come with Vector without having to 'drill' into a wrapper object each time. As efficiency is important here, I also didn't want the added weight of a wrapper.
Therefore I decided to define type aliases in the package object:
package object abc {
type A: Vector[Byte]
type B: Vector[Byte]
type C: Vector[Byte]
}
However, each has it's own fixed length and I would like to include factory methods for their creation. It seems like this is what companion objects are for. This is how my final design looks:
package object abc {
type A: Vector[Byte]
object A {
val LENGTH: Int = ...
def apply(...): A = {
Vector.tabulate...
}
}
...
}
Everything compiles and it allows me to do stuff like this:
val a: A = A(...)
a map {...} mkString(...)
I can't find anything specifically warning against writing companion objects for type aliases, but it seems it goes against how type aliases should be used. It also means that all three of these classes are defined in the same file, when ideally they should be separated.
Are there any hidden problems with this approach?
Is there a better design for this problem?
Thanks.
I guess it is totally ok, because you are not really implementing a companion object.
If you were, you would have access to private fields of immutable.Vector from inside object A (like e.g. private var dirty), which you do not have.
Thus, although it somewhat feels like A is a companion object, it really isn't.
If it were possible to create a companion object for any type by using type alias would make member visibility constraints moot (except maybe for private|protected[this]).
Furthermore, naming the object like the type alias clarifies context and purpose of the object, which is a plus in my book.
Having them all in one file is something that is pretty common in scala as I know it (e.g. when using the type class pattern).
Thus:
No pitfalls, I know of.
And, imho, no need for a different approach.

what is the input type of classOf

I am wondering what type do I put in place of XXX
def registerClass(cl:XXX) = kryo.register(classOf[cl])
EDIT: For why I want to do this.
I have to register many classes using the above code. I wanted to remove the duplication of calling kyro.register several times, hoping to write code like below:
Seq(com.mypackage.class1,com.mypackage.class2,com.mypackage.class3).foreach(registerClass)
Another question, can I pass String instead? and convert it somehow to a class in registerClass?
Seq("com.mypackage.class1","com.mypackage.class2").foreach(registerClass)
EDIT 2:
When I write com.mypackage.class1, it means any class defined in my source. So if I create a class
package com.mypackage.model
class Dummy(val ids:Seq[Int],val name:String)
I would provide com.mypackage.model.Dummy as input
So,
kryo.register(classOf[com.mypackage.model.Dummy])
Kryo is a Java Serialization library. The signature of the register class is
register(Class type)
You could do it like this:
def registerClass(cl:Class[_]) = kryo.register(cl)
And then call it like this:
registerClass(classOf[Int])
The type parameter to classOf needs to be known at compile time. Without knowing more about what you're trying to do, is there any reason you can't use:
def registerClass(cl:XXX) = kryo.register(cl.getClass)

HowTo: Custom Field in Lift-Record-Squeryl

I'm trying to make a EnumListField in Lift/Record/Squeryl, similar to MappedEnumList in LiftMapper. The storage type should be Long/BIGINT. I understand that if I define:
def classOfPersistentField = classOf[Long]
Then Squeryl will know it should create a BIGINT column. And I know it uses setFromAny() to set the value, passing in the Long. The one piece I don't get is:
How will it read the field's value? If it uses valueBox, it will get a Seq[Enum#Value], and it won't know how to turn that into a Long.
How do I tell Squeryl to convert my Seq[Enum#Value] to a Long, or define a "getter" that returns a Long, and that doesn't conflict with the "normal" getter(s)?
you are implementing your validation logic incorrectly. The correct way to validate a Record field is to override
def validations: List[ValidationFunction]
where ValidationFunction is a type alias
type ValidationFunction = ValueType => List[FieldError]
and in your case ValueType == String.
The next issue is your Domain trait. Because your call to validate is inlined into the class definition, it will be called when your field is constructed.