SlideShare une entreprise Scribd logo
1  sur  31
How Scala
promotes TDD
audience.filter(_.usesJava).foreach { member =>
         sayHi(member)
}


    How Scala allows you to write better and
              more testable code
À La Carte

Apéritif
  TDD and programing languages

Entrée
   A short overview of Scala’s features

Plat Principal
   • Better value objects using Case Classes
   • Determinism via immutability
À La Carte
Plat Principal (cont’d)
   • Better type safety, no nulls and less exception
      throwing
   • Better composition and cross-cutting concerns
      using Traits
   • Declarative asynchrony
Le Dessert
   • Specs2
   • ScalaTest
   • Plain old JUnit
   • Mocking
Apéritif
TDD and programing languages
There’s a set of programming language features that are
necessary in order to grow software using TDD. These
include referential transparency, well-defined types that
are easy to declare, the ability to separate concerns into
individual codes of block and, of course, providing the
means to write short, concise and clear tests.
Entrée
A short overview of Scala’s features

• A functional/OO programming language that runs on
  the JVM

• Everything is an object – no primitive types

• Functions are first-class members, every function is a
  value, including what is usually an operator

• Scala is statically-typed and supports type inference
A short overview of Scala’s features

• Lambda expressions, closures and currying naturally

• Pattern matching

• Multiple inheritance through Traits

• Scala is extensible, allowing you to write your own
  “language structures”
Plat Principal
Case Classes
Good software engineering makes use of value objects.
These need to encapsulate the way they represent their
state, to provide information hiding and to be easy to
maintain.

case class Cat(name: String, age: Int,
               kittens: Seq[Cat] = Nil)

val philip = Cat(name = “Philip”, age = 9)

val aKitten = Cat(age = 1, name = “Shraga”)
val withKittens = philip.copy(kittens = Seq(aKitten))
Determinism via Immutability
Scala encourages everything to be immutable by default:

• Variables (vals)

• Collections

• Value objects (using Case Classes)

• Composition of collaborators
Determinism via Immutability
As a result, we get rid of annoying problems such as
aliasing, concurrent modifications of collections and
objects that have an unknown state

case class Cat(kittens: Seq[Cat] = Nil,
               dirty: Boolean = true) extends Pet

class Clinic(val shower: PetShower) {
  def wash(cat: Cat): Cat = {
    val kittens = cat.kittens.map shower.wash
    shower.wash(cat.copy(kittens = kittens)
  }
}
Determinism via Immutability
Testing Clinic.wash() should prove quite simple
val shower = mock[PetShower]
val clinic = new Clinic(shower)

val kitten1 = Cat(dirty = true)
val kitten2 = Cat(dirty = true)
val mom = Cat(kittens = Seq(kitten1, kitten2)

clinic.wash(mom)

verify(shower).wash(kitten1)
verify(shower).wash(kitten2)
verify(shower).wash(mom)
Better type safety
• Scala is statically and strongly typed; type inference
  keeps the code lean and mean

• Stricter generics (in comparison to Java) provide better
  compile-time checks

• Advanced features include structural types and type
  aliases
No nulls
Scala urges us to declare a possible return value using the
Option[T] monad; an option can be either Some(value) or
None, and allows us to assume to it can never be null. We
can use collection semantics to consume an Option[T].

def foo: Option[Foo]

foo match {
  case Some(Foo(bar)) => println(bar)
  case _ => println(“No foo found”)
}

val barOrDefault = foo.map(_.bar).getOrElse(“no foo”)
Less exception throwing using Try[T]
• Try[T] is an abstract monad type with two concrete
  implementations, Success[T] and Failure[E]

• Represents the result of an operation which may fail

• Automatically translate an exception-throwing clause
  to a Try[T] using the Try() apply method
Less exception throwing
class SomeJavaObject {
  public Bar tryFoo() throws FooException {…}
}

val someJavaObject = new SomeJavaObject
val maybeBar = Try(someJavaObject.tryFoo())

maybeBar match {
  case Success(bar) => println(bar)
  case _ => reportFailureAndRetry()
}
Better composition using Traits
Scala provides the means for multiple inheritance using
Traits; this can be useful for separating related but
independent pieces of logic into separate units of code,
each with its own test suite.
class ComponentFactory extends ImageCreation
      with TextCreation with VideoCreation with … {

    def create(cd: ComponentDefinition) = cd match {
      case Image(url, dimensions) => makeImage(…)
      case Text(text, kind) => makeText(…)
      …
    }
}
Better composition using Traits
trait ImageCreation {
  def makeImage(url: String, dimensions: Dimensions)
    = {…}
}

class ImageCreationTest
      extends SpecificationWithJUnit {

    val creator = new ImageCreation {… // init code}

    “makeImage” should {
      “create an image” in {…}
      “fail gracefully” in {…}
    }
}
Cross-cutting concerns using Traits
In the Java world, AOP can be used to add cross-cutting
concerns to existing code without altering it, but has the
downside of being non-transparent or too implicit. This
makes it hard to figure out which aspects are applied at
runtime, and impossible to test that aspects are indeed
being applied properly.

Let’s look at an example using the canonical use case for
AOP – auditing.
Cross-cutting concerns using Traits
trait Auditing {
  def auditor: Auditor
  def audited(f: () => T): T = {
    auditor.before(…)
    val ret: T = f()
    auditor.after(…)
    ret
  }
}

class Foo(baz: Baz, val auditor: Auditor)
      extends Auditing {
  def bar() {
    audited {
      baz.doSomething()
    }
  }
}
Cross-cutting concerns using Traits
class   FooTest extends SpecificationWithJUnit {
  val   auditor = mock[Auditor]
  val   baz = mock[Baz]
  val   foo = new Foo(baz, auditor)

    “Foo” should {
      “call baz” in {
        foo.bar()
        got {
          one(baz).doSomething()
          one(auditor).audit(…)
        }
      }
    }
}
Declarative asynchrony
Scala 2.10 adds a top notch Promise/Future library with
support for composing and pipelining, using callback or
monadic semantics.

A Future[T] will never throw an exception, it will return a
Try[T].
Declarative asynchrony
trait CatVaccinator{
  def vaccinate(cat: Cat): Future[VaccinatedCat]
}

trait PetStore {
  def deliver(cats: Seq[VaccinatedCat]): Unit
}

class Vet(vaccinator: CatVaccinator, petStore: PetStore){
  def deliver(cats: Seq[Cat]) {
    Future.sequence(cats.map vaccinator.vaccinate)
      .onSuccess { vaccinatedCats: Seq[VaccinatedCat] =>
        petStore.deliver(vaccinatedCats)
      }
      .onFailure { exception =>
        reportAndRetry(cats) // some retry logic
      }
  }
}
Declarative asynchrony
// SameThreadExecutor or DeterministicExecutor
val executorService: ExecutorService = …
val vaccinator = mock[CatVaccinator]
val petStore = mock[PetStore]
val vet = new Vet(vaccinator, petStore)

“Vet” should {
  “call deliver” in {
    vaccinator.vaccinate(cat1) returns Future(vcat1)
    vaccinator.vaccinate(cat2) returns Future(vcat2)

        vet.deliver(Seq(cat1, cat2))

        got {
          one(petStore).deliver(Seq(vcat1, vcat2))
        }
    }
}
Le Dessert
Specs2
• Is somewhat of a de-facto standard in the Scala
  community

• Github, active community, frequent releases

• Support for RSpec-style and BDD-style test code

• Rich matcher library

• Mediocre documentation

• Built-in Hamcrest integration
ScalaTest
• Somewhat behind Specs2 in terms of adoption

• Supports a myriad of test formats (RSpec, BDD, XUnit,
  etc)

• Rich and reliable documentation

• Poor matcher library

• No built-in Hamcrest integration
Plain-old JUnit
• Lots of boilerplate

• Hamcrest doesn’t play well with Scala (for instance, for
  matching collections)

• Less magic in comparison with Specs2 and ScalaTest

• No namespace collisions and easier to debug if
  something weird happens
Mocking
• ScalaTest supports ScalaMock, Mockito, JMock and
  EasyMock

• Specs2 only supports Mockito out of the box but
  writing your own sugar using Mixin traits is easy

• ScalaMock is a native Scala mock objects library. Worth
  adopting if you don’t already rely heavily on another
  library
Questions?




       shaiy@wix.com

http://shaiyallin.wix.com/about

Contenu connexe

Tendances

Refactoring to Scala DSLs and LiftOff 2009 Recap
Refactoring to Scala DSLs and LiftOff 2009 RecapRefactoring to Scala DSLs and LiftOff 2009 Recap
Refactoring to Scala DSLs and LiftOff 2009 RecapDave Orme
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scalapramode_ce
 
Stepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to ScalaStepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to ScalaDerek Chen-Becker
 
Scala at HUJI PL Seminar 2008
Scala at HUJI PL Seminar 2008Scala at HUJI PL Seminar 2008
Scala at HUJI PL Seminar 2008Yardena Meymann
 
A Tour Of Scala
A Tour Of ScalaA Tour Of Scala
A Tour Of Scalafanf42
 
Java best practices
Java best practicesJava best practices
Java best practicesRay Toal
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and ClosuresSandip Kumar
 
A Brief, but Dense, Intro to Scala
A Brief, but Dense, Intro to ScalaA Brief, but Dense, Intro to Scala
A Brief, but Dense, Intro to ScalaDerek Chen-Becker
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to ScalaRahul Jain
 
A Brief Intro to Scala
A Brief Intro to ScalaA Brief Intro to Scala
A Brief Intro to ScalaTim Underwood
 
Scala : language of the future
Scala : language of the futureScala : language of the future
Scala : language of the futureAnsviaLab
 

Tendances (19)

Refactoring to Scala DSLs and LiftOff 2009 Recap
Refactoring to Scala DSLs and LiftOff 2009 RecapRefactoring to Scala DSLs and LiftOff 2009 Recap
Refactoring to Scala DSLs and LiftOff 2009 Recap
 
Scale up your thinking
Scale up your thinkingScale up your thinking
Scale up your thinking
 
Scala Intro
Scala IntroScala Intro
Scala Intro
 
Scala in a nutshell by venkat
Scala in a nutshell by venkatScala in a nutshell by venkat
Scala in a nutshell by venkat
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
Stepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to ScalaStepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to Scala
 
Scalax
ScalaxScalax
Scalax
 
Scala at HUJI PL Seminar 2008
Scala at HUJI PL Seminar 2008Scala at HUJI PL Seminar 2008
Scala at HUJI PL Seminar 2008
 
A Tour Of Scala
A Tour Of ScalaA Tour Of Scala
A Tour Of Scala
 
Java best practices
Java best practicesJava best practices
Java best practices
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
 
A Brief, but Dense, Intro to Scala
A Brief, but Dense, Intro to ScalaA Brief, but Dense, Intro to Scala
A Brief, but Dense, Intro to Scala
 
Core java
Core javaCore java
Core java
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
A Brief Intro to Scala
A Brief Intro to ScalaA Brief Intro to Scala
A Brief Intro to Scala
 
Java SE 8 best practices
Java SE 8 best practicesJava SE 8 best practices
Java SE 8 best practices
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Scala : language of the future
Scala : language of the futureScala : language of the future
Scala : language of the future
 
camel-scala.pdf
camel-scala.pdfcamel-scala.pdf
camel-scala.pdf
 

Similaire à How Scala promotes TDD

Qcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scalaQcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scalaMichael Stal
 
Spring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffSpring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffJAX London
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scalashinolajla
 
Scala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian DragosScala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian Dragos3Pillar Global
 
Just Do It! ColdBox Integration Testing
Just Do It! ColdBox Integration TestingJust Do It! ColdBox Integration Testing
Just Do It! ColdBox Integration TestingOrtus Solutions, Corp
 
Testing in Scala. Adform Research
Testing in Scala. Adform ResearchTesting in Scala. Adform Research
Testing in Scala. Adform ResearchVasil Remeniuk
 
Testing in Scala by Adform research
Testing in Scala by Adform researchTesting in Scala by Adform research
Testing in Scala by Adform researchVasil Remeniuk
 
The Scala Programming Language
The Scala Programming LanguageThe Scala Programming Language
The Scala Programming Languageleague
 
Scala, Play 2.0 & Cloud Foundry
Scala, Play 2.0 & Cloud FoundryScala, Play 2.0 & Cloud Foundry
Scala, Play 2.0 & Cloud FoundryPray Desai
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Mario Camou Riveroll
 
Scala final ppt vinay
Scala final ppt vinayScala final ppt vinay
Scala final ppt vinayViplav Jain
 
Testing Kafka components with Kafka for JUnit
Testing Kafka components with Kafka for JUnitTesting Kafka components with Kafka for JUnit
Testing Kafka components with Kafka for JUnitMarkus Günther
 
Introduction to scala for a c programmer
Introduction to scala for a c programmerIntroduction to scala for a c programmer
Introduction to scala for a c programmerGirish Kumar A L
 

Similaire à How Scala promotes TDD (20)

Qcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scalaQcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scala
 
Spring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffSpring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard Wolff
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
 
Scala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian DragosScala: Object-Oriented Meets Functional, by Iulian Dragos
Scala: Object-Oriented Meets Functional, by Iulian Dragos
 
Scala - core features
Scala - core featuresScala - core features
Scala - core features
 
Just Do It! ColdBox Integration Testing
Just Do It! ColdBox Integration TestingJust Do It! ColdBox Integration Testing
Just Do It! ColdBox Integration Testing
 
Testing in Scala. Adform Research
Testing in Scala. Adform ResearchTesting in Scala. Adform Research
Testing in Scala. Adform Research
 
Testing in Scala by Adform research
Testing in Scala by Adform researchTesting in Scala by Adform research
Testing in Scala by Adform research
 
The Scala Programming Language
The Scala Programming LanguageThe Scala Programming Language
The Scala Programming Language
 
Scala presentationjune112011
Scala presentationjune112011Scala presentationjune112011
Scala presentationjune112011
 
Scala Days NYC 2016
Scala Days NYC 2016Scala Days NYC 2016
Scala Days NYC 2016
 
Scala, Play 2.0 & Cloud Foundry
Scala, Play 2.0 & Cloud FoundryScala, Play 2.0 & Cloud Foundry
Scala, Play 2.0 & Cloud Foundry
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?
 
Scala final ppt vinay
Scala final ppt vinayScala final ppt vinay
Scala final ppt vinay
 
Scala test
Scala testScala test
Scala test
 
Intro to Scala
 Intro to Scala Intro to Scala
Intro to Scala
 
Testing Kafka components with Kafka for JUnit
Testing Kafka components with Kafka for JUnitTesting Kafka components with Kafka for JUnit
Testing Kafka components with Kafka for JUnit
 
Scala and Spring
Scala and SpringScala and Spring
Scala and Spring
 
Devoxx
DevoxxDevoxx
Devoxx
 
Introduction to scala for a c programmer
Introduction to scala for a c programmerIntroduction to scala for a c programmer
Introduction to scala for a c programmer
 

Dernier

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Bhuvaneswari Subramani
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 

Dernier (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 

How Scala promotes TDD

  • 1. How Scala promotes TDD audience.filter(_.usesJava).foreach { member => sayHi(member) } How Scala allows you to write better and more testable code
  • 2. À La Carte Apéritif TDD and programing languages Entrée A short overview of Scala’s features Plat Principal • Better value objects using Case Classes • Determinism via immutability
  • 3. À La Carte Plat Principal (cont’d) • Better type safety, no nulls and less exception throwing • Better composition and cross-cutting concerns using Traits • Declarative asynchrony Le Dessert • Specs2 • ScalaTest • Plain old JUnit • Mocking
  • 5. TDD and programing languages There’s a set of programming language features that are necessary in order to grow software using TDD. These include referential transparency, well-defined types that are easy to declare, the ability to separate concerns into individual codes of block and, of course, providing the means to write short, concise and clear tests.
  • 7. A short overview of Scala’s features • A functional/OO programming language that runs on the JVM • Everything is an object – no primitive types • Functions are first-class members, every function is a value, including what is usually an operator • Scala is statically-typed and supports type inference
  • 8. A short overview of Scala’s features • Lambda expressions, closures and currying naturally • Pattern matching • Multiple inheritance through Traits • Scala is extensible, allowing you to write your own “language structures”
  • 10. Case Classes Good software engineering makes use of value objects. These need to encapsulate the way they represent their state, to provide information hiding and to be easy to maintain. case class Cat(name: String, age: Int, kittens: Seq[Cat] = Nil) val philip = Cat(name = “Philip”, age = 9) val aKitten = Cat(age = 1, name = “Shraga”) val withKittens = philip.copy(kittens = Seq(aKitten))
  • 11. Determinism via Immutability Scala encourages everything to be immutable by default: • Variables (vals) • Collections • Value objects (using Case Classes) • Composition of collaborators
  • 12. Determinism via Immutability As a result, we get rid of annoying problems such as aliasing, concurrent modifications of collections and objects that have an unknown state case class Cat(kittens: Seq[Cat] = Nil, dirty: Boolean = true) extends Pet class Clinic(val shower: PetShower) { def wash(cat: Cat): Cat = { val kittens = cat.kittens.map shower.wash shower.wash(cat.copy(kittens = kittens) } }
  • 13. Determinism via Immutability Testing Clinic.wash() should prove quite simple val shower = mock[PetShower] val clinic = new Clinic(shower) val kitten1 = Cat(dirty = true) val kitten2 = Cat(dirty = true) val mom = Cat(kittens = Seq(kitten1, kitten2) clinic.wash(mom) verify(shower).wash(kitten1) verify(shower).wash(kitten2) verify(shower).wash(mom)
  • 14. Better type safety • Scala is statically and strongly typed; type inference keeps the code lean and mean • Stricter generics (in comparison to Java) provide better compile-time checks • Advanced features include structural types and type aliases
  • 15. No nulls Scala urges us to declare a possible return value using the Option[T] monad; an option can be either Some(value) or None, and allows us to assume to it can never be null. We can use collection semantics to consume an Option[T]. def foo: Option[Foo] foo match { case Some(Foo(bar)) => println(bar) case _ => println(“No foo found”) } val barOrDefault = foo.map(_.bar).getOrElse(“no foo”)
  • 16. Less exception throwing using Try[T] • Try[T] is an abstract monad type with two concrete implementations, Success[T] and Failure[E] • Represents the result of an operation which may fail • Automatically translate an exception-throwing clause to a Try[T] using the Try() apply method
  • 17. Less exception throwing class SomeJavaObject { public Bar tryFoo() throws FooException {…} } val someJavaObject = new SomeJavaObject val maybeBar = Try(someJavaObject.tryFoo()) maybeBar match { case Success(bar) => println(bar) case _ => reportFailureAndRetry() }
  • 18. Better composition using Traits Scala provides the means for multiple inheritance using Traits; this can be useful for separating related but independent pieces of logic into separate units of code, each with its own test suite. class ComponentFactory extends ImageCreation with TextCreation with VideoCreation with … { def create(cd: ComponentDefinition) = cd match { case Image(url, dimensions) => makeImage(…) case Text(text, kind) => makeText(…) … } }
  • 19. Better composition using Traits trait ImageCreation { def makeImage(url: String, dimensions: Dimensions) = {…} } class ImageCreationTest extends SpecificationWithJUnit { val creator = new ImageCreation {… // init code} “makeImage” should { “create an image” in {…} “fail gracefully” in {…} } }
  • 20. Cross-cutting concerns using Traits In the Java world, AOP can be used to add cross-cutting concerns to existing code without altering it, but has the downside of being non-transparent or too implicit. This makes it hard to figure out which aspects are applied at runtime, and impossible to test that aspects are indeed being applied properly. Let’s look at an example using the canonical use case for AOP – auditing.
  • 21. Cross-cutting concerns using Traits trait Auditing { def auditor: Auditor def audited(f: () => T): T = { auditor.before(…) val ret: T = f() auditor.after(…) ret } } class Foo(baz: Baz, val auditor: Auditor) extends Auditing { def bar() { audited { baz.doSomething() } } }
  • 22. Cross-cutting concerns using Traits class FooTest extends SpecificationWithJUnit { val auditor = mock[Auditor] val baz = mock[Baz] val foo = new Foo(baz, auditor) “Foo” should { “call baz” in { foo.bar() got { one(baz).doSomething() one(auditor).audit(…) } } } }
  • 23. Declarative asynchrony Scala 2.10 adds a top notch Promise/Future library with support for composing and pipelining, using callback or monadic semantics. A Future[T] will never throw an exception, it will return a Try[T].
  • 24. Declarative asynchrony trait CatVaccinator{ def vaccinate(cat: Cat): Future[VaccinatedCat] } trait PetStore { def deliver(cats: Seq[VaccinatedCat]): Unit } class Vet(vaccinator: CatVaccinator, petStore: PetStore){ def deliver(cats: Seq[Cat]) { Future.sequence(cats.map vaccinator.vaccinate) .onSuccess { vaccinatedCats: Seq[VaccinatedCat] => petStore.deliver(vaccinatedCats) } .onFailure { exception => reportAndRetry(cats) // some retry logic } } }
  • 25. Declarative asynchrony // SameThreadExecutor or DeterministicExecutor val executorService: ExecutorService = … val vaccinator = mock[CatVaccinator] val petStore = mock[PetStore] val vet = new Vet(vaccinator, petStore) “Vet” should { “call deliver” in { vaccinator.vaccinate(cat1) returns Future(vcat1) vaccinator.vaccinate(cat2) returns Future(vcat2) vet.deliver(Seq(cat1, cat2)) got { one(petStore).deliver(Seq(vcat1, vcat2)) } } }
  • 27. Specs2 • Is somewhat of a de-facto standard in the Scala community • Github, active community, frequent releases • Support for RSpec-style and BDD-style test code • Rich matcher library • Mediocre documentation • Built-in Hamcrest integration
  • 28. ScalaTest • Somewhat behind Specs2 in terms of adoption • Supports a myriad of test formats (RSpec, BDD, XUnit, etc) • Rich and reliable documentation • Poor matcher library • No built-in Hamcrest integration
  • 29. Plain-old JUnit • Lots of boilerplate • Hamcrest doesn’t play well with Scala (for instance, for matching collections) • Less magic in comparison with Specs2 and ScalaTest • No namespace collisions and easier to debug if something weird happens
  • 30. Mocking • ScalaTest supports ScalaMock, Mockito, JMock and EasyMock • Specs2 only supports Mockito out of the box but writing your own sugar using Mixin traits is easy • ScalaMock is a native Scala mock objects library. Worth adopting if you don’t already rely heavily on another library
  • 31. Questions? shaiy@wix.com http://shaiyallin.wix.com/about

Notes de l'éditeur

  1. This is not a talk about TDD. This is a talk about the language features in Scala that correspond with better software engineering, as required in order to grow software using TDD.
  2. Functional + immutability gives us referential transparency
  3. Extensibility allows us to write our custom, embedded DSLs, and consume DSLs from 3rd party languages. Specs2 is a good example for such DSL for semantic XDD
  4. A case class automatically makes its constructor arguments into vals. It also provides automatic equals, hashCode, toString methods and a very useful copy method which makes use of Scala’s named arguments (with defaults) feature.We also see that case classes with proper default argument values are essentially test object builders, which saves us tons of code for test setup
  5. It's very easy to do this wrong in Java; a Scala object that can't be initialized without its collaborators is the default way you write classes inScala
  6. Shower.wash returns a new instance of the input cat, presumably setting some “isDirty” flag to false. Note how we pass it with a new instance of the cat that gets a new sequence of its kittens, now washed.Note how kittens gets a default value of Nil, meaning an empty list. This means that our unit test will never have to test a case where kittens is nullScala doesn’t need a return statement; the return value of shower.wash is the return value of clinic.wash.
  7. Statically typed – types are checked in compile time verses runtimeStrongly typed - each variable must have a concrete typeYou get the best of both worlds – lean code like in dynamic languages and compile-time checking of adherence to structureType inference can slow down compilation – use with careStructural types – the canonical example is closeable
  8. Tony Hoare, who invented the null reference publicly apologized for it http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+Mistake
  9. Try retains the type safety of checked exceptions (that is missing from Scala) while reducing boilerplate such as cascading throws statementsThis does not directly aid in testing, but decluttering the interfaces makes the resulting product less verbose and easier to understand. Also, eliminating cascaded throws statements simplifies the test cases
  10. The diamond problem is solved by defining an order of precedence calculated by the order of trait declarationConsider, for instance, a ComponentFactory. From the point of view of its consumer, there should be a single entry point through which components need to be created. However, creating a text component and creating an image component have nothing in common. The solution – separate the creation of different component types to different traits, each with its own suite of tests.
  11. Note how it seems like we added a new language construct named audited. This appearance is aided by the fact that a code block surrounded by curly braces is treated as a function with no parameter list, and that a function that takes a single parameter can be called without parentheses.
  12. Test needs to be clearer
  13. Who knows what a Future is?For Scala 2.9.x, you can use Twitter’s util.core package which provides a wonderful alternative for 2.10’s Futures
  14. This code passes a collection of Baz objects to the Foo.bar method, getting a Bar for each instance of Baz. We do this in parallel. After we’re done, we pass the collection of Bars to our listener. Upon failure, we call some method that reports failure and retries, presumably by calling deliver() againUnit is a void
  15. This is a simplistic, sunny-day only test. A proper test would also simulate failure and check that the retry method is calledThe executor service is either a same-thread executor (which guarantees that the call to deliver() will not return until all calls to vaccinator have returned) or an instance of deterministic scheduler (which will need some massage between the call to deliver() and the verification logic)
  16. Has Hamcrest integration in form of a mixin trait that provides implicit conversion from Hamcrest matcher to Specs2 matcher. However, using built-in hamcrest matchers proves difficult due to namespace collision with Specs2’s own matcher library.Composing Specs2’s matcher library is possible the the syntax is so obscure that you’ll probably won’t be able to read your own code 5 minutes after completing it
  17. It’s fairly easy to create a Hamcrest -> ScalaTest matcher adapter, but none is provided built-in. Composing ScalaTest matcher lies between hard and impossible.
  18. I won’t tell you what to use, your millage may vary. If adopting Scala into an existing project with lots of JUnit tests, you may want to stick with what works. For a new project, try to decide between Specs2 and ScalaTest based on documentation and ease of use. Ask your colleagues, experiment with both and decide.