solid scala
DESCRIPTION
Solid principles with ScalaTRANSCRIPT
![Page 2: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/2.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/3.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/4.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/5.jpg)
![Page 6: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/6.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/7.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/8.jpg)
class task{ def downloadFile = {} def parseFile = {} def persistData = {}}
![Page 9: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/9.jpg)
for scala
srp applies to
functionsdata structures
packages/ modules of functions
![Page 10: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/10.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/11.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/12.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/13.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/14.jpg)
interface segregation principle - isp
many specific interfaces are better than one general purpose interface
Avoid side effects Increase re-usability
![Page 15: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/15.jpg)
trait DoorService{ def isOpen def open def close}
class Door extends DoorService{ def isOpen = {} def open = {} def close = {}}
![Page 16: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/16.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/17.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/18.jpg)
class TwitterProcessor { def processTweets = new Processor.process(List("1","2"))}
class Processor { def process(list:List[String]) = {}}
![Page 19: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/19.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/20.jpg)
for scala
becomes less relevant for Scala as we can pass higher order functions to achieve the same
behavior
![Page 21: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/21.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/22.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/23.jpg)
object client2 { def runTheDog(dog:DogBehavior) = {if (dog.isInstanceOf[ToyDog] ) dog.asInstanceOf[ToyDog].batteryPresent=true; dog.run}}
violates ocp now
![Page 24: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/24.jpg)
![Page 25: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/25.jpg)
![Page 26: Solid scala](https://reader034.vdocuments.net/reader034/viewer/2022052307/5564912fd8b42a73418b5384/html5/thumbnails/26.jpg)