modular programming using object in scala

Download Modular programming Using Object in Scala

If you can't read please download the document

Upload: knoldus-software-llp

Post on 16-Apr-2017

3.916 views

Category:

Art & Photos


5 download

TRANSCRIPT

Ruchi Jindal Software Consultant Knoldus

Modular Programming Using Object in Scala

Scala's Strength

Agile, with lightweight syntax

Scala is a pure object-oriented language

Functional Programming

Safe and performant, with strong static typing

Functions are objects

Everything is an object(Numbers are objects)

1 + 2 * 3 / x ====> (1).+(((2).*(3))./(x))

Scala Says

If I were to pick a language to use today other than Java, it would beScala.

- James Gosling, creator of Java

Scala, it must be stated, is the current heir apparent to the Javathrone. No other language on the JVM seems as capable of being a"replacement for Java" as Scala, and the momentum behind Scala isnow unquestionable. While Scala is not a dynamic language, it hasmany of the characteristics of popular dynamic languages, through itsrich and flexible type system, its sparse and clean syntax, and itsmarriage of functional and object paradigms.

- Charles Nutter, creator of JRuby

I can honestly say if someone had shown me the Programming inScala book by Martin Odersky, Lex Spoon & Bill Venners back in 2003I'd probably have never created Groovy.

- James Strachan, creator of Groovy.

Why unify FP and OOP?

Both have complementary strengths for composition:

Functional programming: Object-oriented programming:

Makes it easy to build interesting Makes it easy to adapt and extendthings from simple parts, using complex systems, using higher-order functions, subtyping and inheritance, algebraic types and dynamic configurations, pattern matching, classes as partial abstractions. parametric polymorphism.

Modular programming

Also known as top down design and stepwise refinement.

A software design technique that increases the extent to which software is composed of separate, interchangeable components called modules by breaking down program functions into modules, each of which accomplishes one function and contains everything necessary to accomplish this.

Conceptually, modules represent a separation of concerns, and improve maintainability by enforcing logical boundaries between components.

Modules are typically incorporated into the program through interfaces.

Why Need Modular Approach

Scala is a scalable language because we can use the same techniques to construct small as well as large programs.

Programming in the large means organizing and assembling the smaller pieces into larger programs, applications, or systems.

While the division of programs into packages is already quite helpful, itis limited because it provides no way to abstract.

We cannot reconfigure a package two different ways within the same program, and you cannot inherit between packages.

A package always includes one precise list of contents, and that list is fixed until you change the code.

................................

Why we need Modular Approach.......

Firstly there should be a module construct that providesa good separation of interface and implementation.

Secondly, there should be a way to replace one module with another that has the same interface with out changing or recompiling the modules that depend on the replaced one.

Lastly, there should be a way to wire modules together. This wiring task can by thought of as configuring the system.

How To achieve Modular Approach

How to use Scalas object-oriented features to make a program more modular

How a simple singleton object can be used as a module

How to use traits and classes as abstractions over modules. These abstractions can be reconfigured into multiple modules, even multiple times within the same program.

How to use traits to divide a module across multiple files

To Build an enterprise web application you need the partition of the software into layers, including

a domain layer

an application layer

In the domain layer, we define domain objects, which will capture business concepts and rules and encapsulate state that will be persisted to an external relational database.

In the application layer, well provide an API organized in terms of the services ,the application offers to clients (including the user interface layer).

The application layer will implement these services by coordinating tasks and delegatingthe work to the objects of the domain layer.

Lets Start with an Example

An Enterprise web application that will allow users to manage recipes.

It will contains two entities that will be persisted in the database.

Food

Recipe

abstract class Food(val name: String) {override def toString = name}

class Recipe(val name: String,val ingredients: List[Food],val instructions: String) {override def toString = name}

Here are some singleton instances of Food and Recipe classes, which can be used when writing tests:

object Apple extends Food("Apple")object Orange extends Food("Orange")object Cream extends Food("Cream")object Sugar extends Food("Sugar")

object FruitSalad extends Recipe("fruit salad",List(Apple, Orange, Cream, Sugar),"Stir it all together.")

Scala uses objects for modules, so to modularize program we are making two singleton objects to serve as the mock implementations of the database and browser modules during testing.

object SimpleDatabase {def allFoods = List(Apple, Orange, Cream, Sugar)def foodNamed(name: String): Option[Food] =allFoods.find(_.name == name)def allRecipes: List[Recipe] = List(FruitSalad)}object SimpleBrowser {def recipesUsing(food: Food) =SimpleDatabase.allRecipes.filter(recipe =>recipe.ingredients.contains(food))}

You can use this database and browser as follows:

scala> val apple = SimpleDatabase.foodNamed("Apple").getapple: Food = Apple

scala> SimpleBrowser.recipesUsing(apple)res0: List[Recipe] = List(fruit salad)

To make things a little more interesting, suppose the database sorts foodsinto categories. To implement this, you can add a FoodCategory class and alist of all categories in the database.

eg. class FoodCategory(name: String, foods: List[Food])

object SimpleDatabase {

def allFoods = List(Apple, Orange, Cream, Sugar)

def foodNamed(name: String): Option[Food] =allFoods.find(_.name == name)

def allRecipes: List[Recipe] = List(FruitSalad)

case class FoodCategory(name: String, foods: List[Food])

private var categories = List(FoodCategory("fruits", List(Apple, Orange)),FoodCategory("misc", List(Cream, Sugar)))

def allCategories = categories}object SimpleBrowser {def recipesUsing(food: Food) =SimpleDatabase.allRecipes.filter(recipe =>recipe.ingredients.contains(food))def displayCategory(category: SimpleDatabase.FoodCategory) {println(category)}}

Abstraction

The SimpleBrowser module mentions the SimpleDatabase mod-ule by name, you wont be able to plug in a different implementation of thedatabase module without modifying and recompiling the browser module.In addition, although theres no hard link from the SimpleDatabase moduleto the SimpleBrowser module,theres no clear way to enable the user interface layer, for example, to be configured to use different implementations of the browser module.

abstract class Browser { val database: Database

def recipesUsing(food: Food) = database.allRecipes.filter(recipe => recipe.ingredients.contains(food))

def displayCategory(category: database.FoodCategory) { println(category) } }

abstract class Database { def allFoods: List[Food] def allRecipes: List[Recipe] def foodNamed(name: String) = allFoods.find(f => f.name == name) case class FoodCategory(name: String, foods: List[Food]) def allCategories: List[FoodCategory] }

object SimpleDatabase extends Database { def allFoods = List(Apple, Orange, Cream, Sugar)

def allRecipes: List[Recipe] = List(FruitSalad)

private var categories = List( FoodCategory("fruits", List(Apple, Orange)), FoodCategory("misc", List(Cream, Sugar)))

def allCategories = categories }

object SimpleBrowser extends Browser { val database = SimpleDatabase }

scala> val apple = SimpleDatabase.foodNamed("Apple").get apple: Food = Apple

scala> SimpleBrowser.recipesUsing(apple) res1: List[Recipe] = List(fruit salad)

Now we create a second mock database, and use the samebrowser class with it

object StudentDatabase extends Database { object FrozenFood extends Food("FrozenFood") object HeatItUp extends Recipe( "heat it up", List(FrozenFood), "Microwave the 'food' for 10 minutes.") def allFoods = List(FrozenFood) def allRecipes = List(HeatItUp) def allCategories = List( FoodCategory("edible", List(FrozenFood))) } object StudentBrowser extends Browser { val database = StudentDatabase }

Splitting modules into traits

Often a module is too large to fit comfortably into a single file. When thathappens, you can use traits to split a module into separate files. For example ,suppose you wanted to move categorization code out of the main Database file and into its own.

trait FoodCategories {case class FoodCategory(name: String, foods: List[Food])def allCategories: List[FoodCategory]}

Now class Database can mix in the FoodCategories trait instead of defin-ing FoodCategory and allCategories itselfabstract class Database extends FoodCategories {def allFoods: List[Food]def allRecipes: List[Recipe]def foodNamed(name: String) =allFoods.find(f => f.name == name)}

Continuing in this way, you might try and divide SimpleDatabase intotwo traits, one for foods and one for recipes.

object SimpleDatabase extends Databasewith SimpleFoods with SimpleRecipes

The SimpleFoods trait could look as :

trait SimpleFoods {object Pear extends Food("Pear")def allFoods = List(Apple, Pear)def allCategories = Nil}

Runtime linking

One final feature of Scala modules is worth emphasizing: they can be linkedtogether at runtime, and you can decide which modules will link to whichdepending on runtime computations.

object GotApples {def main(args: Array[String]) {val db: Database =if(args(0) == "student")StudentDatabaseelseSimpleDatabaseobject browser extends Browser {val database = db}val apple = SimpleDatabase.foodNamed("Apple").getfor(recipe val category = StudentDatabase.allCategories.headcategory: StudentDatabase.FoodCategory =FoodCategory(edible,List(FrozenFood))scala> SimpleBrowser.displayCategory(category):12: error: type mismatch;found: StudentDatabase.FoodCategoryrequired: SimpleBrowser.database.FoodCategorySimpleBrowser.displayCategory(category)If we want all FoodCategorys to be the same, we can accomplishthis by moving the definition of FoodCategory outside of any class or trait.