SlideShare a Scribd company logo
Implementation and testing DAO layer
with native DSL with using
the implicit classes mechanism in Scala
Speaker:
Hryhoriy Kravtsov, PhD.,
R&D Chief Officer,
VertaMedia LLC
DAO Pattern
Data Access Object Pattern [1] or DAO pattern is used to separate low level
data accessing API or operations from high level business services. Following
are the participants in Data Access Object Pattern.
Data Access Object Interface - This interface defines the standard operations
to be performed on a model object(s).
Data Access Object concrete class - This class implements above interface.
This class is responsible to get data from a data source which can be
database / xml or any other storage mechanism.
Model Object or Value Object - This object is simple POJO containing get/set
methods to store data retrieved using DAO class.
Repository Pattern
A Repository [2] mediates between the domain and data mapping
layers, acting like an in-memory domain object collection. Client
objects construct query specifications declaratively and submit them to
Repository for satisfaction. Objects can be added to and removed from
the Repository, as they can from a simple collection of objects, and the
mapping code encapsulated by the Repository will carry out the
appropriate operations behind the scenes.
Conceptually, a Repository encapsulates the set of objects persisted
in a data store and the operations performed over them, providing a
more object-oriented view of the persistence layer. Repository also
supports the objective of achieving a clean separation and one-way
dependency between the domain and data mapping layers.
Repository vs DAO
DAO pattern [3] offers only a loosely defined contract. It suffers from
getting potential misused and bloated implementations.
The repository pattern uses a metaphor of a Collection. This metaphor
gives the pattern a tight contract and make it easier to understand by your
fellow colleagues.
Repository and DAO [4], in conclusion, have similar intentions only that the
Repository is a higher level concept dealing directly with business/domain
objects, while DAO is more lower level, closer to the database/storage
dealing only with data. A (micro)ORM is a DAO that is used by a Repository.
For data-centric apps, a repository and DAO are interchangeable
because the ‘business’ objects are simple data.
Implicit classes
Scala 2.10 [5] introduced a new feature called implicit classes.
An implicit class is a class marked with the implicit keyword.
This keyword makes the class’ primary constructor available for
implicit conversions when the class is in scope.
object Helpers {
implicit class IntWithTimes(x: Int) {
def times[A](f: => A): Unit = {
def loop(current: Int): Unit =
if(current > 0) {
f
loop(current - 1)
}
loop(x)
}
}
}
scala> import Helpers._
import Helpers._
scala> 5 times println("HI")
HI
HI
HI
HI
HI
Restrictions
1. They must be defined inside of another
trait/class/object.
object Helpers {
implicit class RichInt(x: Int) // OK!
}
implicit class RichDouble(x: Double) // BAD!
2. They may only take one non-implicit argument in their constructor.
implicit class RichDate(date: java.util.Date) // OK!
implicit class Indexer[T](collecton: Seq[T], index: Int) // BAD!
implicit class Indexer[T](collecton: Seq[T])(implicit index: Index) // OK!
While it’s possible to create an implicit class with more than one
non-implicit argument, such classes aren’t used during implicit lookup.
3. There may not be any method,
member or object in scope with the same
name as the implicit class.
Note: This means an implicit class cannot
be a case class.
object Bar
implicit class Bar(x: Int) // BAD!
val x = 5
implicit class x(y: Int) // BAD!
implicit case class Baz(x: Int) // BAD!
Our DAO
package object dao {
import scala.concurrent.ExecutionContext.Implicits.global
abstract class AbstractDao[T](collection: BSONCollection)(implicit handler: BSONDocumentReader[T]
with BSONDocumentWriter[T] with BSONHandler[BSONDocument, T]) {
def dropCollection: Future[Unit] = collection.drop()
def insert(doc: T): Future[Boolean] = collection.insert[T](doc).map(_.writeErrors.isEmpty)
def count(): Future[Int] = collection.count()
def find(query: BSONDocument): Future[List[T]] = collection.find(query).cursor[T]().collect[List]()
def findOne(query: BSONDocument = BSONDocument()): Future[Option[T]] = collection.find(query).one[T]
def update(selector: BSONDocument, update: BSONDocument): Future[Boolean] = collection.update(selector, update)
.map(_.writeErrors.isEmpty)
def remove(query: BSONDocument): Future[Boolean] = collection.remove(query).map(_.writeErrors.isEmpty)
}
implicit class DefaultMongoWrapper(db: DefaultDB) {
implicit val partnerConfHandler = Macros.handler[PartnerConfig]
...
object partners extends AbstractDao[PartnerConfig](db(“partners”)) {
def getActivePartnerConfigs: Future[List[PartnerConfig]] = {
val query = BSONDocument("active" -> true)
find(query)
}
def byPartnerNameAndUrl(partnerName: String, url: String): Future[Option[PartnerConfig]] = {
val query = BSONDocument("name" -> partnerName, "url" -> url)
findOne(query)
}
}
...
}
}
DAO in Action
class AnalyzerActor(db: DefaultDB) extends NamedLoggingActor {
import scala.concurrent.ExecutionContext.Implicits.global
import com.vertamedia.<>.dao._
private def replaceSample(sample: Sample): Future[Boolean] = {
logger.debug("Replace old sample with new one.")
for {
diffRemoveResult <- db.diffSample.removeByPartnerNameAndUrl(sample.conf.name, sample.conf.url)
sampleRemoveResult <- db.sample.removeByPartnerNameAndUrl(sample.conf.name, sample.conf.url) if diffRemoveResult
insertResult <- db.sample.insert(sample) if sampleRemoveResult
} yield {
insertResult
}
}
override def receive: Receive = {
case sample: Sample =>
...
}
override val actorName: String = Actors.Analyzer.name
}
The Legend:
Code with using DAO pattern
Code with using
Repository pattern
Please, compare with info from the official site of MongoDB:
Embedded MongoDB
import de.flapdoodle.embed.mongo._
trait EmbeddedMongoTestFixture extends FunSpec with BeforeAndAfterAll {
private val host = MongoConnection.DefaultHost
private val version = Version.V3_0_5
private[this] lazy val port = { val socket = new ServerSocket(0); val port = socket.getLocalPort
socket.close(); port }
private[this] lazy val net = new Net(host, port, Network.localhostIsIPv6())
private[this] lazy val mongod: MongodProcess = {
val runtime = MongodStarter.getDefaultInstance
val mongodConfig = new MongodConfigBuilder().version(version).net(net).build()
runtime.prepare(mongodConfig).start()
}
private[this] lazy val _db = mongoDB(host, port, s"test-${UUID.randomUUID()}")
def mongoDB(host: String, port: Int, name: String): DefaultDB = {
import scala.concurrent.ExecutionContext.Implicits.global
val driver = new MongoDriver(); val connection: MongoConnection = driver.connection(List(s"$host:$port"))
connection(name)
}
def startMongo(): Unit = { val _mongod = mongod; db }
override def beforeAll() = { super.beforeAll(); startMongo() }
def shutDownMongo(): Unit = { _db.connection.close(); mongod.stop() }
override def afterAll() = { shutDownMongo(); super.afterAll()}
def db: DefaultDB = _db
}
DAO Testing in Action
class MongoDaoTest extends EmbeddedMongoTestFixture with BeforeAndAfterEach {
val timeOut = 5 seconds
import scala.concurrent.ExecutionContext.Implicits.global
val config = AppConfiguration(
analyzerPoolSize = 3, vastHttpTimeOut = Interval(5, "seconds"), objectHttpTimeOut = Interval(7, "seconds")
)
override def beforeEach() = {
...
Await.result(db.config.insert(config), timeOut)
...
}
override def afterEach() = {
Await.result( for {
_ <- db.partners.dropCollection()
...
} yield (), timeOut)
}
describe("Config DAO should") {
it("return exist config") {
val actual = Await.result(db.config.getConfig, timeOut)
assert(actual === config)
}
....
}
}
The Legend:
Code with using DAO pattern
Code with using
Repository pattern
Advantages and
Disadvantages
YES!
- easy code reading for DAO/compact Repository
- easy supporting for DAO/compact Repository
- familiar notation with MongoShell
- easy to test
NO!
- difficult reading of “reach” Repository
- difficult supporting “reach” Repository
- hate to the implicit conversation
To use or not to use?
For your decision!
References
1. http://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
2. http://martinfowler.com/eaaCatalog/repository.html
3. http://thinkinginobjects.com/2012/08/26/dont-use-dao-use-repository/
4. http://blog.sapiensworks.com/post/2012/11/01/Repository-vs-DAO.aspx
5. http://docs.scala-lang.org/overviews/core/implicit-classes.html
●
Thanks for attention!
Please, your questions...
Hryhoriy Kravtsov, PhD.,
R&D Chief Officer,
VertaMedia LLC,
h.kravtsov@vertamedia.com

More Related Content

PDF
Scala jargon cheatsheet
Ruslan Shevchenko
 
PDF
Scala cheatsheet
Arduino Aficionado
 
PPTX
Class object method constructors in java
Raja Sekhar
 
KEY
Xbase - Implementing Domain-Specific Languages for Java
meysholdt
 
PPT
Basic Javascript
Bunlong Van
 
PDF
Few simple-type-tricks in scala
Ruslan Shevchenko
 
PDF
Introduction To Scala
Peter Maas
 
PDF
Javascript basic course
Tran Khoa
 
Scala jargon cheatsheet
Ruslan Shevchenko
 
Scala cheatsheet
Arduino Aficionado
 
Class object method constructors in java
Raja Sekhar
 
Xbase - Implementing Domain-Specific Languages for Java
meysholdt
 
Basic Javascript
Bunlong Van
 
Few simple-type-tricks in scala
Ruslan Shevchenko
 
Introduction To Scala
Peter Maas
 
Javascript basic course
Tran Khoa
 

What's hot (20)

PPT
Sax Dom Tutorial
vikram singh
 
PDF
javascript objects
Vijay Kalyan
 
PDF
Extending the Xbase Typesystem
Sebastian Zarnekow
 
PPTX
Linq Introduction
Neeraj Kaushik
 
PPT
Java Tutorials
Woxa Technologies
 
PDF
Using Combine, SwiftUI and callAsFunction to build an experimental localizati...
Donny Wals
 
PPT
Ajax and JavaScript Bootcamp
AndreCharland
 
PDF
JavaScript - Chapter 4 - Types and Statements
WebStackAcademy
 
PDF
Object Oriented Programming in PHP
Lorna Mitchell
 
PPT
Intermediate JavaScript
☆ Milan Adamovsky ☆
 
PPTX
JavsScript OOP
LearningTech
 
PDF
JavaScript - Chapter 8 - Objects
WebStackAcademy
 
PPT
java training faridabad
Woxa Technologies
 
PPT
A Deeper look into Javascript Basics
Mindfire Solutions
 
PPT
Reversing JavaScript
Roberto Suggi Liverani
 
PPSX
Strings in Java
Hitesh-Java
 
PPT
JavaScript Basics
Mats Bryntse
 
PDF
JavaScript - Chapter 6 - Basic Functions
WebStackAcademy
 
PPTX
javascript
Kaya Ota
 
PDF
Automatically generating-json-from-java-objects-java-objects268
Ramamohan Chokkam
 
Sax Dom Tutorial
vikram singh
 
javascript objects
Vijay Kalyan
 
Extending the Xbase Typesystem
Sebastian Zarnekow
 
Linq Introduction
Neeraj Kaushik
 
Java Tutorials
Woxa Technologies
 
Using Combine, SwiftUI and callAsFunction to build an experimental localizati...
Donny Wals
 
Ajax and JavaScript Bootcamp
AndreCharland
 
JavaScript - Chapter 4 - Types and Statements
WebStackAcademy
 
Object Oriented Programming in PHP
Lorna Mitchell
 
Intermediate JavaScript
☆ Milan Adamovsky ☆
 
JavsScript OOP
LearningTech
 
JavaScript - Chapter 8 - Objects
WebStackAcademy
 
java training faridabad
Woxa Technologies
 
A Deeper look into Javascript Basics
Mindfire Solutions
 
Reversing JavaScript
Roberto Suggi Liverani
 
Strings in Java
Hitesh-Java
 
JavaScript Basics
Mats Bryntse
 
JavaScript - Chapter 6 - Basic Functions
WebStackAcademy
 
javascript
Kaya Ota
 
Automatically generating-json-from-java-objects-java-objects268
Ramamohan Chokkam
 
Ad

Viewers also liked (13)

PDF
AI&BigData Lab 2016. Григорий Кравцов: Модель вычислений на классификациях
GeeksLab Odessa
 
PPTX
Java/Scala Lab 2016. Сергей Моренец: Способы повышения эффективности в Java 8.
GeeksLab Odessa
 
PPTX
AI&BigData Lab 2016. Константин Герасименко: MOLAP: Новые границы возможного.
GeeksLab Odessa
 
PPTX
Java/Scala Lab 2016. Владимир Гарбуз: Написание безопасного кода на Java.
GeeksLab Odessa
 
PDF
AI&BigData Lab 2016. Руденко Петр: Особенности обучения, настройки и использо...
GeeksLab Odessa
 
PDF
AI&BigData Lab 2016. Дмитрий Новицкий: cпайковые и бионические нейронные сети...
GeeksLab Odessa
 
PDF
AI&BigData Lab 2016. Анатолий Востряков: Перевод с "плохого" английского на "...
GeeksLab Odessa
 
PDF
AI&BigData Lab 2016. Сарапин Виктор: Размер имеет значение: анализ по требова...
GeeksLab Odessa
 
PDF
AI&BigData Lab 2016. Игорь Костюк: Как приручить музыкальную рекомендательную...
GeeksLab Odessa
 
PPTX
AI&BigData Lab 2016. Артем Чернодуб: Обучение глубоких, очень глубоких и реку...
GeeksLab Odessa
 
PDF
Java/Scala Lab 2016. Руслан Шевченко: Несколько трюков scala-разработки, приг...
GeeksLab Odessa
 
PDF
AI&BigData Lab 2016. Сергей Шельпук: Методология Data Science проектов
GeeksLab Odessa
 
PDF
AI&BigData Lab 2016. Александр Баев: Transfer learning - зачем, как и где.
GeeksLab Odessa
 
AI&BigData Lab 2016. Григорий Кравцов: Модель вычислений на классификациях
GeeksLab Odessa
 
Java/Scala Lab 2016. Сергей Моренец: Способы повышения эффективности в Java 8.
GeeksLab Odessa
 
AI&BigData Lab 2016. Константин Герасименко: MOLAP: Новые границы возможного.
GeeksLab Odessa
 
Java/Scala Lab 2016. Владимир Гарбуз: Написание безопасного кода на Java.
GeeksLab Odessa
 
AI&BigData Lab 2016. Руденко Петр: Особенности обучения, настройки и использо...
GeeksLab Odessa
 
AI&BigData Lab 2016. Дмитрий Новицкий: cпайковые и бионические нейронные сети...
GeeksLab Odessa
 
AI&BigData Lab 2016. Анатолий Востряков: Перевод с "плохого" английского на "...
GeeksLab Odessa
 
AI&BigData Lab 2016. Сарапин Виктор: Размер имеет значение: анализ по требова...
GeeksLab Odessa
 
AI&BigData Lab 2016. Игорь Костюк: Как приручить музыкальную рекомендательную...
GeeksLab Odessa
 
AI&BigData Lab 2016. Артем Чернодуб: Обучение глубоких, очень глубоких и реку...
GeeksLab Odessa
 
Java/Scala Lab 2016. Руслан Шевченко: Несколько трюков scala-разработки, приг...
GeeksLab Odessa
 
AI&BigData Lab 2016. Сергей Шельпук: Методология Data Science проектов
GeeksLab Odessa
 
AI&BigData Lab 2016. Александр Баев: Transfer learning - зачем, как и где.
GeeksLab Odessa
 
Ad

Similar to Java/Scala Lab 2016. Григорий Кравцов: Реализация и тестирование DAO слоя с нативным DSL с помощью неявных классов на примере взаимодействия с MongoDB через ReactiveMongo драйвер. (20)

PPT
Scala Talk at FOSDEM 2009
Martin Odersky
 
PPT
Zend framework 03 - singleton factory data mapper caching logging
Tricode (part of Dept)
 
PDF
Dao pattern
ciriako
 
PPSX
ADO.NET
Farzad Wadia
 
PDF
Data access
Joshua Yoon
 
PDF
ptu3-harvey-m-deitel-paul-j-deitel-tem-r-nieto-contributor-paul-j-deitel.pdf
jorgeulises3
 
PPT
Ado.net
Iblesoft
 
PDF
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
lennartkats
 
PDF
A Scala tutorial
Dima Statz
 
PDF
JavaScript Miller Columns
Jonathan Fine
 
PDF
Ch23 xml processing_with_java
ardnetij
 
PDF
Ch23
preetamju
 
PPTX
Structural pattern 3
Naga Muruga
 
PDF
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Bill Buchan
 
PPTX
Java se7 features
Kumaraswamy M
 
PPTX
Interview preparation for programming.pptx
BilalHussainShah5
 
PPTX
Unit No. 1 Introduction to Java.pptx
DrYogeshDeshmukh1
 
PPTX
Introduction to Fundamental of Class.pptx
DawitTekie1
 
PPT
Ado.net &amp; data persistence frameworks
Luis Goldster
 
Scala Talk at FOSDEM 2009
Martin Odersky
 
Zend framework 03 - singleton factory data mapper caching logging
Tricode (part of Dept)
 
Dao pattern
ciriako
 
ADO.NET
Farzad Wadia
 
Data access
Joshua Yoon
 
ptu3-harvey-m-deitel-paul-j-deitel-tem-r-nieto-contributor-paul-j-deitel.pdf
jorgeulises3
 
Ado.net
Iblesoft
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
lennartkats
 
A Scala tutorial
Dima Statz
 
JavaScript Miller Columns
Jonathan Fine
 
Ch23 xml processing_with_java
ardnetij
 
Ch23
preetamju
 
Structural pattern 3
Naga Muruga
 
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Bill Buchan
 
Java se7 features
Kumaraswamy M
 
Interview preparation for programming.pptx
BilalHussainShah5
 
Unit No. 1 Introduction to Java.pptx
DrYogeshDeshmukh1
 
Introduction to Fundamental of Class.pptx
DawitTekie1
 
Ado.net &amp; data persistence frameworks
Luis Goldster
 

More from GeeksLab Odessa (20)

PDF
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
GeeksLab Odessa
 
PDF
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
GeeksLab Odessa
 
PDF
DataScience Lab 2017_Блиц-доклад_Турский Виктор
GeeksLab Odessa
 
PDF
DataScience Lab 2017_Обзор методов детекции лиц на изображение
GeeksLab Odessa
 
PDF
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
GeeksLab Odessa
 
PDF
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
PDF
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
PDF
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
PDF
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
GeeksLab Odessa
 
PDF
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
GeeksLab Odessa
 
PDF
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
GeeksLab Odessa
 
PDF
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
GeeksLab Odessa
 
PDF
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
GeeksLab Odessa
 
PDF
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
GeeksLab Odessa
 
PDF
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
GeeksLab Odessa
 
PDF
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
GeeksLab Odessa
 
PDF
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
GeeksLab Odessa
 
PDF
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
GeeksLab Odessa
 
PDF
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
GeeksLab Odessa
 
PPTX
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
GeeksLab Odessa
 
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
GeeksLab Odessa
 
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
GeeksLab Odessa
 
DataScience Lab 2017_Блиц-доклад_Турский Виктор
GeeksLab Odessa
 
DataScience Lab 2017_Обзор методов детекции лиц на изображение
GeeksLab Odessa
 
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
GeeksLab Odessa
 
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
GeeksLab Odessa
 
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
GeeksLab Odessa
 
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
GeeksLab Odessa
 
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
GeeksLab Odessa
 
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
GeeksLab Odessa
 
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
GeeksLab Odessa
 
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
GeeksLab Odessa
 
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
GeeksLab Odessa
 
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
GeeksLab Odessa
 
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
GeeksLab Odessa
 
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
GeeksLab Odessa
 

Recently uploaded (20)

PPTX
Visualising Data with Scatterplots in IBM SPSS Statistics.pptx
Version 1 Analytics
 
PDF
Multi-factor Authentication (MFA) requirement for Microsoft 365 Admin Center_...
Q-Advise
 
PDF
Become an Agentblazer Champion Challenge
Dele Amefo
 
PPTX
Hire Expert Blazor Developers | Scalable Solutions by OnestopDA
OnestopDA
 
PDF
Jenkins: An open-source automation server powering CI/CD Automation
SaikatBasu37
 
PPTX
Odoo Integration Services by Candidroot Solutions
CandidRoot Solutions Private Limited
 
PDF
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
Hironori Washizaki
 
PPTX
AIRLINE PRICE API | FLIGHT API COST |
philipnathen82
 
PPTX
Services offered by Dynamic Solutions in Pakistan
DaniyaalAdeemShibli1
 
PDF
Micromaid: A simple Mermaid-like chart generator for Pharo
ESUG
 
PDF
A REACT POMODORO TIMER WEB APPLICATION.pdf
Michael624841
 
PDF
Become an Agentblazer Champion Challenge Kickoff
Dele Amefo
 
PPT
FALLSEM2025-26_ISWE304L_TH_VL2025260102786_2025-07-10_Reference-Material-II.ppt
AKSHAYA255427
 
PPTX
What to Capture When It Breaks: 16 Artifacts That Reveal Root Causes
Tier1 app
 
PDF
What to consider before purchasing Microsoft 365 Business Premium_PDF.pdf
Q-Advise
 
PPTX
Presentation of Computer CLASS 2 .pptx
darshilchaudhary558
 
PPTX
Why Use Open Source Reporting Tools for Business Intelligence.pptx
Varsha Nayak
 
PPTX
Benefits of DCCM for Genesys Contact Center
pointel ivr
 
PDF
Emergency Mustering solutions – A Brief overview
Personnel Tracking
 
PPTX
Materi-Enum-and-Record-Data-Type (1).pptx
RanuFajar1
 
Visualising Data with Scatterplots in IBM SPSS Statistics.pptx
Version 1 Analytics
 
Multi-factor Authentication (MFA) requirement for Microsoft 365 Admin Center_...
Q-Advise
 
Become an Agentblazer Champion Challenge
Dele Amefo
 
Hire Expert Blazor Developers | Scalable Solutions by OnestopDA
OnestopDA
 
Jenkins: An open-source automation server powering CI/CD Automation
SaikatBasu37
 
Odoo Integration Services by Candidroot Solutions
CandidRoot Solutions Private Limited
 
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
Hironori Washizaki
 
AIRLINE PRICE API | FLIGHT API COST |
philipnathen82
 
Services offered by Dynamic Solutions in Pakistan
DaniyaalAdeemShibli1
 
Micromaid: A simple Mermaid-like chart generator for Pharo
ESUG
 
A REACT POMODORO TIMER WEB APPLICATION.pdf
Michael624841
 
Become an Agentblazer Champion Challenge Kickoff
Dele Amefo
 
FALLSEM2025-26_ISWE304L_TH_VL2025260102786_2025-07-10_Reference-Material-II.ppt
AKSHAYA255427
 
What to Capture When It Breaks: 16 Artifacts That Reveal Root Causes
Tier1 app
 
What to consider before purchasing Microsoft 365 Business Premium_PDF.pdf
Q-Advise
 
Presentation of Computer CLASS 2 .pptx
darshilchaudhary558
 
Why Use Open Source Reporting Tools for Business Intelligence.pptx
Varsha Nayak
 
Benefits of DCCM for Genesys Contact Center
pointel ivr
 
Emergency Mustering solutions – A Brief overview
Personnel Tracking
 
Materi-Enum-and-Record-Data-Type (1).pptx
RanuFajar1
 

Java/Scala Lab 2016. Григорий Кравцов: Реализация и тестирование DAO слоя с нативным DSL с помощью неявных классов на примере взаимодействия с MongoDB через ReactiveMongo драйвер.

  • 1. Implementation and testing DAO layer with native DSL with using the implicit classes mechanism in Scala Speaker: Hryhoriy Kravtsov, PhD., R&D Chief Officer, VertaMedia LLC
  • 2. DAO Pattern Data Access Object Pattern [1] or DAO pattern is used to separate low level data accessing API or operations from high level business services. Following are the participants in Data Access Object Pattern. Data Access Object Interface - This interface defines the standard operations to be performed on a model object(s). Data Access Object concrete class - This class implements above interface. This class is responsible to get data from a data source which can be database / xml or any other storage mechanism. Model Object or Value Object - This object is simple POJO containing get/set methods to store data retrieved using DAO class.
  • 3. Repository Pattern A Repository [2] mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
  • 4. Repository vs DAO DAO pattern [3] offers only a loosely defined contract. It suffers from getting potential misused and bloated implementations. The repository pattern uses a metaphor of a Collection. This metaphor gives the pattern a tight contract and make it easier to understand by your fellow colleagues. Repository and DAO [4], in conclusion, have similar intentions only that the Repository is a higher level concept dealing directly with business/domain objects, while DAO is more lower level, closer to the database/storage dealing only with data. A (micro)ORM is a DAO that is used by a Repository. For data-centric apps, a repository and DAO are interchangeable because the ‘business’ objects are simple data.
  • 5. Implicit classes Scala 2.10 [5] introduced a new feature called implicit classes. An implicit class is a class marked with the implicit keyword. This keyword makes the class’ primary constructor available for implicit conversions when the class is in scope. object Helpers { implicit class IntWithTimes(x: Int) { def times[A](f: => A): Unit = { def loop(current: Int): Unit = if(current > 0) { f loop(current - 1) } loop(x) } } } scala> import Helpers._ import Helpers._ scala> 5 times println("HI") HI HI HI HI HI
  • 6. Restrictions 1. They must be defined inside of another trait/class/object. object Helpers { implicit class RichInt(x: Int) // OK! } implicit class RichDouble(x: Double) // BAD! 2. They may only take one non-implicit argument in their constructor. implicit class RichDate(date: java.util.Date) // OK! implicit class Indexer[T](collecton: Seq[T], index: Int) // BAD! implicit class Indexer[T](collecton: Seq[T])(implicit index: Index) // OK! While it’s possible to create an implicit class with more than one non-implicit argument, such classes aren’t used during implicit lookup. 3. There may not be any method, member or object in scope with the same name as the implicit class. Note: This means an implicit class cannot be a case class. object Bar implicit class Bar(x: Int) // BAD! val x = 5 implicit class x(y: Int) // BAD! implicit case class Baz(x: Int) // BAD!
  • 7. Our DAO package object dao { import scala.concurrent.ExecutionContext.Implicits.global abstract class AbstractDao[T](collection: BSONCollection)(implicit handler: BSONDocumentReader[T] with BSONDocumentWriter[T] with BSONHandler[BSONDocument, T]) { def dropCollection: Future[Unit] = collection.drop() def insert(doc: T): Future[Boolean] = collection.insert[T](doc).map(_.writeErrors.isEmpty) def count(): Future[Int] = collection.count() def find(query: BSONDocument): Future[List[T]] = collection.find(query).cursor[T]().collect[List]() def findOne(query: BSONDocument = BSONDocument()): Future[Option[T]] = collection.find(query).one[T] def update(selector: BSONDocument, update: BSONDocument): Future[Boolean] = collection.update(selector, update) .map(_.writeErrors.isEmpty) def remove(query: BSONDocument): Future[Boolean] = collection.remove(query).map(_.writeErrors.isEmpty) } implicit class DefaultMongoWrapper(db: DefaultDB) { implicit val partnerConfHandler = Macros.handler[PartnerConfig] ... object partners extends AbstractDao[PartnerConfig](db(“partners”)) { def getActivePartnerConfigs: Future[List[PartnerConfig]] = { val query = BSONDocument("active" -> true) find(query) } def byPartnerNameAndUrl(partnerName: String, url: String): Future[Option[PartnerConfig]] = { val query = BSONDocument("name" -> partnerName, "url" -> url) findOne(query) } } ... } }
  • 8. DAO in Action class AnalyzerActor(db: DefaultDB) extends NamedLoggingActor { import scala.concurrent.ExecutionContext.Implicits.global import com.vertamedia.<>.dao._ private def replaceSample(sample: Sample): Future[Boolean] = { logger.debug("Replace old sample with new one.") for { diffRemoveResult <- db.diffSample.removeByPartnerNameAndUrl(sample.conf.name, sample.conf.url) sampleRemoveResult <- db.sample.removeByPartnerNameAndUrl(sample.conf.name, sample.conf.url) if diffRemoveResult insertResult <- db.sample.insert(sample) if sampleRemoveResult } yield { insertResult } } override def receive: Receive = { case sample: Sample => ... } override val actorName: String = Actors.Analyzer.name } The Legend: Code with using DAO pattern Code with using Repository pattern Please, compare with info from the official site of MongoDB:
  • 9. Embedded MongoDB import de.flapdoodle.embed.mongo._ trait EmbeddedMongoTestFixture extends FunSpec with BeforeAndAfterAll { private val host = MongoConnection.DefaultHost private val version = Version.V3_0_5 private[this] lazy val port = { val socket = new ServerSocket(0); val port = socket.getLocalPort socket.close(); port } private[this] lazy val net = new Net(host, port, Network.localhostIsIPv6()) private[this] lazy val mongod: MongodProcess = { val runtime = MongodStarter.getDefaultInstance val mongodConfig = new MongodConfigBuilder().version(version).net(net).build() runtime.prepare(mongodConfig).start() } private[this] lazy val _db = mongoDB(host, port, s"test-${UUID.randomUUID()}") def mongoDB(host: String, port: Int, name: String): DefaultDB = { import scala.concurrent.ExecutionContext.Implicits.global val driver = new MongoDriver(); val connection: MongoConnection = driver.connection(List(s"$host:$port")) connection(name) } def startMongo(): Unit = { val _mongod = mongod; db } override def beforeAll() = { super.beforeAll(); startMongo() } def shutDownMongo(): Unit = { _db.connection.close(); mongod.stop() } override def afterAll() = { shutDownMongo(); super.afterAll()} def db: DefaultDB = _db }
  • 10. DAO Testing in Action class MongoDaoTest extends EmbeddedMongoTestFixture with BeforeAndAfterEach { val timeOut = 5 seconds import scala.concurrent.ExecutionContext.Implicits.global val config = AppConfiguration( analyzerPoolSize = 3, vastHttpTimeOut = Interval(5, "seconds"), objectHttpTimeOut = Interval(7, "seconds") ) override def beforeEach() = { ... Await.result(db.config.insert(config), timeOut) ... } override def afterEach() = { Await.result( for { _ <- db.partners.dropCollection() ... } yield (), timeOut) } describe("Config DAO should") { it("return exist config") { val actual = Await.result(db.config.getConfig, timeOut) assert(actual === config) } .... } } The Legend: Code with using DAO pattern Code with using Repository pattern
  • 11. Advantages and Disadvantages YES! - easy code reading for DAO/compact Repository - easy supporting for DAO/compact Repository - familiar notation with MongoShell - easy to test NO! - difficult reading of “reach” Repository - difficult supporting “reach” Repository - hate to the implicit conversation To use or not to use? For your decision!
  • 12. References 1. http://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm 2. http://martinfowler.com/eaaCatalog/repository.html 3. http://thinkinginobjects.com/2012/08/26/dont-use-dao-use-repository/ 4. http://blog.sapiensworks.com/post/2012/11/01/Repository-vs-DAO.aspx 5. http://docs.scala-lang.org/overviews/core/implicit-classes.html ●
  • 13. Thanks for attention! Please, your questions... Hryhoriy Kravtsov, PhD., R&D Chief Officer, VertaMedia LLC, [email protected]