<<All the examples here are complete and are fully executable>>
This post is being written and published step-by-step. The theme of this entire post will be around why I want to use scala in my enterprise application. The features we will discuss include
- Functional paradigm of scala
- Traits and Mixin
- Concurrency
- Notable patterns in scala
For the programmers who just heard and thought enough about scala but did not get a chance or time to dig it in real - I encourage them to have a look into my initial post on scala Dive into Scala and get started with it in 10 minutes including downloading and installing - I don't guarantee it though if your internet connection is slow and you are using a windows box ;)
In one sentence why I picked up this language for my next one years primary language for enterprise applications goes like this - Scala beautifully combines object-oriented paradigm with functional paradigm while allowing me to access and leverage the richness of entire java world (true for JVM version of scala).
In the enterprise application development arena there is no right most language, we should be able to mix and match languages and technologies fluently. Since mainstream scala is a JVM language, it is tuned to that philosophy of mixing and matching with other JVM languages along with our good old Java. In near future I will write on how to use scala, groovy and java simultaneously without compromising on performance and complexity. In fact the intention of mixing and matching is not to have just mixture for sake of it but to use what is best at what. In mix and match our focus will be to improve expressiveness, performance, code compactness. Just 2 complexities are there in this approach; those are - 1) putting write thing at the right place - meaning choosing right language to do get right thing done 2) deep knowledge about multiple languages. Lets stop this philosophy here - lets see more what scala has to offer us.
Quoting directly from official website of scala http://www.scala-lang.org/. But.... but this is pretty "official" - just see what they say - but in this post lets talk about in our own language in our own feeling.
"Scala is a concise, elegant, type-safe programming language that integrates object-oriented and functional features.This is seen when you open http://www.scala-lang.org for the first time in the banner. It gets changed though :)
Scala is fully interoperable with Java."
A little lengthy quotation from scala-lang.org. You know what? even I did not have patience to read these much talked about features in "official" voice. But its good to read and tune in with their way of thinking to really get into it. For the time being read if you can otherwise just look at the bulleted points. We will anyway anyway discuss these in our own way.
"Scala is a modern multi-paradigm programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages.
- Scala is object-oriented: Scala is a pure object-oriented language in the sense that every value is an object. Types and behavior of objects are described by classes and traits. Class abstractions are extended by subclassing and a flexible mixin-based composition mechanism as a clean replacement for multiple inheritance.
- Scala is functional: Scala is also a functional language in the sense that every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. Scala's case classes and its built-in support for pattern matching model algebraic types used in many functional programming languages.
- Scala is statically typed: Scala is equipped with an expressive type system that enforces statically that abstractions are used in a safe and coherent manner.
- Scala is extensible: The design of Scala acknowledges the fact that in practice, the development of domain-specific applications often requires domain-specific language extensions. Scala provides a unique combination of language mechanisms that make it easy to smoothly add new language constructs in form of libraries:
A joint use of both features facilitates the definition of new statements without extending the syntax and without using macro-like meta-programming facilities.
- any method may be used as an infix or postfix operator, and
- closures are constructed automatically depending on the expected type (target typing).
- Scala interoperates with Java and .NET: Scala is designed to interoperate well with popular programming environments like the Java 2 Runtime Environment (JRE) and the .NET Framework (CLR). In particular, the interaction with mainstream object-oriented languages like Java and C# is as smooth as possible. Scala has the same compilation model (separate compilation, dynamic class loading) like Java and C# and allows access to thousands of high-quality libraries."
Now Lets see what really these means to us. We are going deeper. After discussing about the applicability of the language - thats the core philosophical essence, we will look into the advanced language features - such as useful, beautiful and fancy syntaxes, annotations, etc.
Now lets see what does "Scala is functional" mean. Lets see an example before we discuss theory.
object Sum {
def sumOfInts(a: Int, b: Int): Int =
if (a > b) 0 else a + sumOfInts(a + 1, b)
}
This is it. Run it using scala shell or as a scala file. We defined sum of integers between given two numbers in scala. Does not it look like pure algorithmic? Almost the same way we would right the algorithm for it. No unnecessary jugglery of temporary variables. This is the first step towards getting into the functional concept of scala. This is just the tip of the iceberg lets get into the deeper stuffs now.
To reiterate - Scala is functional - we saw a little bit of that now in the line of using it in closer way with the problem domain. Now we will strengthen again the statement "Scala is functional" by saying and showing the functions are objects too in scala. Functions are Objects in scala. Lets have a look into the following routine
object Repeater {
def onceInOneSec(cb: () => Unit) {
while (true) { cb(); Thread sleep 1000 }
}
def stringPrinter() {
println("print in in given frequency")
}
def main(args: Array[String]) {
onceInOneSec(stringPrinter)
}
}
We will do two things now. We will see how int he above example a function is treated as object and alongside we will also decode some of the seemingly cryptic syntaxes of scala. Lets go.
In the function main - the arguments in main is pretty similar to that of java - we have a method call onceInOneSec and we - very important - pass another method stringPrinter as argument. It is one of the reason why scala is called functional language. About syntax - I think they are mostly self describing with one special mention is () => Unit it means a function that takes no argument and return nothing. So when we say def onceInOneSec(cb: () => Unit) it means definition of a function that takes a function of type no-argument-nothing-returns as argument where cb is the identifier or the "object" of type function. Unit is nothing but same as void in C/C++/Java.
Lets modify the code we have written in the following way.
object Repeater {
def onceInOneSec(cb: () => Unit) {
while (true) { cb(); Thread sleep 1000 }
}
def main(args: Array[String]) {
onceInOneSec( () =>
println("print it in given freq"))
}
}
In the above example we have eliminated one method stringPrinter. Because it was being called only once. We defined it inline while calling the onceInOneSec function. This method has no name and is know as anonymous method. Cool.. we learned one more thing in scala.
We have seen really basic things so far, but I think these basics were required in the view that scala is pretty new kid to the bigger audience till now. One of my early blog readers commented that "whats deep in this" - he said it correct so far nothing deep, we are at surface and planning to dip deep. One of my favorite scala features is trait. Lets talk about now.
Trait: people, even the scala-lang.org guys compare it with interface with option to have some implementations into it, where code gets reused. But for me its more than that. It brings a new way of designing and organizing my application - much robust way. Lets see one example of trait before we talk about my philosophical understanding.
trait Flying {
def canFly(): Boolean = true
def fly() {
println("Flying.....")
}
def hasWings(): Boolean = true
def maximumFlyingSpeed(): Int
}
trait Walking {
def canWalk(): Boolean = true
def walk() {
println("Walking....")
}
def maximumWalkingSpeed(): Int
def hasLegs(): Boolean = true
def howManyLegs(): Int
}
class Dove extends Flying with Walking {
def maximumFlyingSpeed(): Int = 30
def howManyLegs(): Int = 2
def maximumWalkingSpeed(): Int = 5
}
We saw an example of trait now. Definitely it looks like abstract class but a class can inherit from multiple traits. So multiple inheritance is possible beyond interface. A good facility indeed, But the key conceptual difference lies somewhere else. The concept helps crispier modeling. Lets think carefully when we think about interface or abstract class we think about parent - we define something that has generic stuffs and then make specialization in concrete classes. The notion of the parent class is a generic real life object itself. This concept forces us to find and model a generic real life object to be parent to the specialized ones. In real life we may not find anything generic and useful together. Also there can be common characteristics in more generic objects unless we break that generic object further - that leads to deeper and complex inheritance tree. Trait at the other hand brings something different in this space - trait can be thought of as characteristics. In the above example instead of defining a generic bird object we defined flying and walking traits that constitutes the real life object Dove, allowing flying and walking to be used independently elsewhere - as you know flying and walking can be other objects characteristics other than a bird. Make sense? In a nutshell the concept of trait gives me more instruments towards making my favorite modeling choice - aggregation/composition over inheritance. It really makes a lot of senses to me.
Mixin: We will now see another powerful application of trait. That is mixin class composition. Very powerful and interesting feature. Lets look at one example.
abstract class AbstractService {
type T
def firewallCompatible: Boolean
def parameter: T
def result: T
}
trait Webservice extends AbstractService {
def constructIPMessage(f: T => Unit) { f(parameter) }
def firewallPingResult(f: T => Unit) {
if(firewallCompatible) f(result)
}
}
class RestfulService extends AbstractService {
type T = String
def firewallCompatible = true
def parameter = "ping the server in DMZ"
def result = "fake ping back OK from server in the DMZ"
}
object RSTest {
def main(args: Array[String]) {
class Service extends RestfulService with Webservice
val service = new Service
service constructIPMessage println
service firewallPingResult println
}
}
If you are using scala>
prompt just type scala>RSTest.main(null)
Lets understand this in our own way. If you look at the the code in RSTest we are composing a class that has type RestfulService and with the characteristics of Webservice. Note the the terms type and characteristics. Trait describes characteristics where as abstract class or interface describes type (super type). The example of class composition (Service) in the RSTest is called mixin-class composition. One thing to note - in my example there is a high potential of anti-pattern if not used carefully. The example here is very small and limited so the magnitude of the effect of anti-pattern (or whether it is anti-pattern here or not) is not clear enough. But if trait is tightly coupled with the supertype (abstract class here), the supertype has to be defined very carefully, otherwise the usefulness of the trait will go. Another (non-code) example - lets say we have (super) types like Animal, WildAnimal, DomesticAnimal and characteristics (traits) like Agility, Herbivore, Carnivore. Now If we associate (make dependent) these traits with WildAnimal (what is association? In our example WebService is associated with AbstractService. Do not get confused about association in UML, we are not talking about that) its wrong in the context (anti-pattern) as a trait like agility can well be the trait of a wild animal like cheetah and a domestic animal like horse. So this trait should better be associated with (super) type animal and not (super - next super type) type wild animal.
However trait can be completely independent of any type. Analogically it is like a range of wide and tele lenses. With wide angle lens your field of view (area of applicability in the case of trait) becomes wider and with tele lens your field of view becomes narrower. Be careful about how much field of view is appropriate for a particular scenario and then define the scope of a trait. Got this? Let me know if you understand otherwise.
==== Its a logical milestone but this post is under enhancement now, I am writing more. Stay tuned ====