Solid scala

26
S.O.L.I.D with Scala Oct 23' 2012 > Vikas Hazrati > [email protected] > @vhazrati

description

Solid principles with Scala

Transcript of Solid scala

Page 1: Solid scala

S.O.L.I.D with Scala

Oct 23' 2012 > Vikas Hazrati > [email protected] > @vhazrati

Page 2: Solid scala

what?

Five basic principles of object-oriented programming and design.

When applied together intend to make it more likely that a programmer will create a system that is easy to maintain and extend over time.

Page 3: Solid scala

problems

rigid – difficult to add new features

fragile – unable to identify the impact of the change

immobile – no reusability

viscous – going with the flow of bad practices already being present in the code.

Page 4: Solid scala

solutionsloosely coupled – shouldn’t be too much of

dependency between the modules, even if there is a dependency it should be via the interfaces and should be minimal.

cohesive code- The code has to be very specific in its operations.

context independent code- so that it can be reused.

DRY – Don't repeat yourself – Avoid copy-paste of code. Change in the code would have to be made in all the places where its been copied.

Page 5: Solid scala
Page 6: Solid scala

single responsibility principle - srp

a module should have only one reason to change

Avoid side effects Minimize code touch-points

Increase re-usability

Separate out different responsibilities into different code units

Page 7: Solid scala

package com.knolx

trait UserService { def changeEmail }

class SettingUpdateService extends UserService { def changeEmail ={ checkAccess match { case Some(x) => // do something case None => //do something else } } def checkAccess:Option[Any] = None

}

Page 8: Solid scala

class task{ def downloadFile = {} def parseFile = {} def persistData = {}}

Page 9: Solid scala

for scala

srp applies to

functionsdata structures

packages/ modules of functions

Page 10: Solid scala

open closed principle - ocp

A module should be open for extension but closed for modification

Avoid side effects Minimize code touch-points

Page 11: Solid scala

case class Check(id:Int, bankName:String, amount:Double)

class CheckProcessor { val checkList:List[Check] = List(new Check(1, "BoA", 200.0)) def checkProcessor = sendEmail def sendEmail = {}}

Page 12: Solid scala

case class Check(id:Int, bankName:String, amount:Double)

class CheckProcessor { val checkList:List[Check] = List(new Check(1, "BoA", 200.0), new Check(2, "Citi", 100.0)) def checkProcessor = for (check <-checkList) if (check.bankName == "BoA") sendEmail else sendFax def sendEmail = {} def sendFax = {}}

Page 13: Solid scala

trait BankProcess{ def processCheck}class BoABank(name:String) extends BankProcess{ def processCheck = sendEmail def sendEmail = {}}

class CitiBank(name:String) extends BankProcess{ def processCheck = sendFax def sendFax = {}}

case class Check(id:Int, bank:BankProcess, amount:Double)

class CheckProcessor { val checkList:List[Check] = List(new Check(1, new BoABank("BoA"), 200.0), new Check(2, new CitiBank("Citi"), 100.0)) def checkProcessor = for (check <-checkList) check.bank.processCheck}

Page 14: Solid scala

interface segregation principle - isp

many specific interfaces are better than one general purpose interface

Avoid side effects Increase re-usability

Page 15: Solid scala

trait DoorService{ def isOpen def open def close}

class Door extends DoorService{ def isOpen = {} def open = {} def close = {}}

Page 16: Solid scala

trait DoorService{ def isOpen def open def close}

trait TimerDoorService{ def closeAfterMinutes(duration:Int)}

class Door extends DoorService{ def isOpen = {} def open = {} def close = {}}

class TimerDoor extends DoorService with TimerDoorService{ def isOpen = {} def open = {} def close = {} def closeAfterMinutes(duration:Int) = {}}

Page 17: Solid scala

dependency inversion principle - dip

depend on abstractions, not on concretions

Avoid side effects reduced effort foradjusting to existing

code changes

Increase re-usability

Page 18: Solid scala

class TwitterProcessor { def processTweets = new Processor.process(List("1","2"))}

class Processor { def process(list:List[String]) = {}}

Page 19: Solid scala

trait ProcessorService { def process(list:List[String])}

class TwitterProcessor { val myProcessor:ProcessorService = new Processor def processTweets = myProcessor.process(List("1","2"))}

class Processor extends ProcessorService{ def process(list:List[String]) = process(list, true) def process(list:List[String], someCheck:Boolean) = {}}

Page 20: Solid scala

for scala

becomes less relevant for Scala as we can pass higher order functions to achieve the same

behavior

Page 21: Solid scala

liskov substitution principle - lsp

subclasses should be substitutable for their base classes

Avoid side effects

a derived class is substitutable for its base class if:

1. Its preconditions are no stronger than the base class method.2. Its postconditions are no weaker than the base class method.Or, in other words, derived methods should expect no more and provide no less

Page 22: Solid scala

trait DogBehavior{ def run}

class RealDog extends DogBehavior{ def run = {println("run")}}

class ToyDog extends DogBehavior{ val batteryPresent = true def run = { if (batteryPresent) println("run") }}

object client {def runTheDog(dog:DogBehavior) = {dog.run}}

Page 23: Solid scala

object client2 { def runTheDog(dog:DogBehavior) = {if (dog.isInstanceOf[ToyDog] ) dog.asInstanceOf[ToyDog].batteryPresent=true; dog.run}}

violates ocp now

Page 24: Solid scala
Page 25: Solid scala
Page 26: Solid scala