SlideShare a Scribd company logo
Patterns for Slick database
applications
Jan Christopher Vogt, EPFL
Slick Team

#scalax
Recap: What is Slick?
(for ( c <- coffees;
if c.sales > 999
) yield c.name).run

select "COF_NAME"
from
"COFFEES"
where "SALES" > 999
Agenda
• Query composition and re-use
• Getting rid of boiler plate in Slick 2.0
–
–
–

outer joins / auto joins
auto increment
code generation

• Dynamic Slick queries
Query composition and reuse
For-expression desugaring in Scala
for ( c <- coffees;
if c.sales > 999
) yield c.name

coffees
.withFilter(_.sales > 999)
.map(_.name)
Types in Slick
class Coffees(tag: Tag) extends Table[C](tag,"COFFEES”) {
def * = (name, supId, price, sales, total) <> ...
val name = column[String]("COF_NAME", O.PrimaryKey)
val supId = column[Int]("SUP_ID")
val price = column[BigDecimal]("PRICE")
val sales = column[Int]("SALES")
val total = column[Int]("TOTAL")
}
lazy val coffees = TableQuery[Coffees]

<: Query[Coffees,C]

coffees.map(c => c.name)
(coffees:TableQuery[Coffees,_]).map(
(coffees
).map(
(c:Coffees) => (c.name Column[String])
(c.name:
(c
)
)
): Query[Column[String],String]
)
Table extensions
class Coffees(tag: Tag) extends Table[C](tag,"COFFEES”) {
…
val price = column[BigDecimal]("PRICE")
val sales = column[Int]("SALES")
def

revenue = price.asColumnOf[Double] *
sales.asColumnOf[Double]

}

coffees.map(c => c.revenue)
Query extensions
implicit class QueryExtensions[T,E]
( val q: Query[T,E] ){
def page(no: Int, pageSize: Int = 10)
: Query[T,E]
= q.drop( (no-1)*pageSize ).take(pageSize)
}
suppliers.page(5)
coffees.sortBy(_.name).page(5)
Query extensions by Table
implicit class CoffeesExtensions
( val q: Query[Coffees,C] ){
def byName( name: Column[String] )
: Query[Coffees,C]
= q.filter(_.name === name).sortBy(_.name)
}
coffees.byName("ColumbianDecaf").page(5)
Query extensions for joins
implicit class CoffeesExtensions2( val q: Query[Coffees,C] ){
def withSuppliers
(s: Query[Suppliers,S] = Tables.suppliers)
: Query[(Coffees,Suppliers),(C,S)]
= q.join(s).on(_.supId===_.id)
def suppliers
(s: Query[Suppliers, S] = Tables.suppliers)
: Query[Suppliers, S]
= q.withSuppliers(s).map(_._2)
}
coffees.withSuppliers() : Query[(Coffees,Suppliers),(C,S)
coffees.withSuppliers( suppliers.filter(_.city === "Henderson") )
// buyable coffees
coffeeShops.coffees().suppliers().withCoffees()
Query extensions by Interface
trait HasSuppliers{ def supId: Column[Int] }
class Coffees(…)
extends Table... with HasSuppliers {…}
class CofInventory(…) extends Table... with HasSuppliers {…}
implicit class HasSuppliersExtensions[T <: HasSupplier,E]
( val q: Query[T,E] ){
def bySupId(id: Column[Int]): Query[T,E]
= q.filter( _.supId === id )
def withSuppliers
(s: Query[Suppliers,S] = Tables.suppliers)
: Query[(T,Suppliers),(E,S)]
= q.join(s).on(_.supId===_.id)
def suppliers ...
}
// available quantities of coffees
cofInventory.withSuppliers()
.map{ case (i,s) =>
i.quantity.asColumnOf[String] ++ " of " ++ i.cofName ++ " at " ++ s.name
}
Query extensions summary
• Mindshift required!
Think code, not monolithic query strings.
• Stay completely lazy!
Keep Query[…]s as long as you can.
• Re-use!
Write query functions or extensions
methods for shorter, better and DRY code.
Getting rid of boilerplate
Auto joins
Auto joins
implicit class QueryExtensions2[T,E]
( val q: Query[T,E] ){
def autoJoin[T2,E2]
( q2:Query[T2,E2] )
( implicit condition: (T,T2) => Column[Boolean] )
: Query[(T,T2),(E,E2)]
= q.join(q2).on(condition)
}
implicit def joinCondition1
= (c:Coffees,s:Suppliers) => c.supId === s.id
coffees.autoJoin( suppliers ) : Query[(Coffees,Suppliers),(C,S)]
coffees.autoJoin( suppliers ).map(_._2).autoJoin(cofInventory)
Auto incrementing inserts
Auto incrementing inserts
val supplier
= Supplier( 0, "Arabian Coffees Inc.", ... )
// now ignores auto-increment column
suppliers.insert( supplier )
// includes auto-increment column
suppliers.forceInsert( supplier )
Code generatION
Code generator for Slick code
// runner for default config
import scala.slick.meta.codegen.SourceCodeGenerator
SourceCodeGenerator.main(
Array(
"scala.slick.driver.H2Driver",
"org.h2.Driver",
"jdbc:h2:mem:test",
"src/main/scala/", // base src folder
"demo" // package
)
)
Generated code
package demo
object Tables extends {
val profile = scala.slick.driver.H2Driver
} with Tables
trait Tables {
val profile: scala.slick.driver.JdbcProfile
import profile.simple._
case class CoffeeRow(name: String, supId: Int, ...)
implicit def GetCoffees
= GetResult{r => CoffeeRow.tupled((r.<<, ... )) }
class Coffees(tag: Tag) extends Table[CoffeeRow](…){…}
...
OUTER JOINS
Outer join limitation in Slick
suppliers.leftJoin(coffees)
.on(_.id === _.supId)
.run // SlickException: Read NULL value ...
id

name

name

supId

1

Superior Coffee

NULL

NULL

2

Acme, Inc.

Colombian

2

2

Acme, Inc.

French_Roast

2

LEFT JOIN
id

name

name

supId

1

Superior Coffee

Colombian

2

2

Acme, Inc.

French_Roast

2
Outer join pattern
suppliers.leftJoin(coffees)
.on(_.id === _.supId)
.map{ case(s,c) => (s,(c.name.?,c.supId.?,…)) }
.run
.map{ case (s,c) =>
(s,c._1.map(_ => Coffee(c._1.get,c._2.get,…))) }
// Generated outer join helper
suppliers.leftJoin(coffees)
.on(_.id === _.supId)
.map{ case(s,c) => (s,c.?) }
.run
CUSTOMIZABLE Code
generatION
Using code generator as a library
val metaModel = db.withSession{ implicit session =>
profile.metaModel // e.g. H2Driver.metaModel
}
import scala.slick.meta.codegen.SourceCodeGenerator
val codegen = new SourceCodeGenerator(metaModel){
// <- customize here
}
codegen.writeToFile(
profile = "scala.slick.driver.H2Driver”,
folder = "src/main/scala/",
pkg = "demo",
container = "Tables",
fileName="Tables.scala" )
Adjust name mapping
import scala.slick.util.StringExtensions._
val codegen =
new SourceCodeGenerator(metaModel){
override def tableName
= _.toLowerCase.toCamelCase
override def entityName
= tableName(_).dropRight(1)
}
Generate auto-join conditions 1
class CustomizedCodeGenerator(metaModel: Model)
extends SourceCodeGenerator(metaModel){
override def code = {
super.code + "nn" + s"""
/** implicit join conditions for auto joins */
object AutoJoins{
${indent(joins.mkString("n"))}
}
""".trim()
}
…
Generate auto-join conditions 2
…
val joins = tables.flatMap( _.foreignKeys.map{ foreignKey =>
import foreignKey._
val fkt = referencingTable.tableClassName
val pkt = referencedTable.tableClassName
val columns = referencingColumns.map(_.name) zip
referencedColumns.map(_.name)
s"implicit def autojoin${name.capitalize} "+
" = (left:${fkt},right:${pkt}) => " +
columns.map{
case (lcol,rcol) =>
"left."+lcol + " === " + "right."+rcol
}.mkString(" && ")
}
Other uses of Slick code generation
• Glue code (Play, etc.)
• n-n join code
• Migrating databases (warning: types
change)
(generate from MySQL, create in
Postgres)
• Generate repetitive regarding data model
(aka model driven software engineering)
• Generate DDL for external model
Use code generation wisely
• Don’t loose language-level abstraction
• Add your generator and data model to
version control
• Complete but new and therefor
experimental in Slick
Dynamic Queries
Common use case for web apps
Dynamically decide
• displayed columns
• filter conditions
• sort columns / order
Dynamic column
class Coffees(tag: Tag)
extends Table[CoffeeRow](…){
val name = column[String]("COF_NAME",…)
}

coffees.map(c => c.name)
coffees.map(c =>
c.column[String]("COF_NAME")
)

Be careful about security!
Example: sortDynamic

suppliers.sortDynamic("street.desc,city.desc")
sortDynamic 1
implicit class QueryExtensions3[E,T<: Table[E]]
( val query: Query[T,E] ){
def sortDynamic(sortString: String) : Query[T,E] = {
// split string into useful pieces
val sortKeys = sortString.split(',').toList.map(
_.split('.').map(_.toUpperCase).toList )
sortDynamicImpl(sortKeys)
}
private def sortDynamicImpl(sortKeys: List[Seq[String]]) = ???
}

suppliers.sortDynamic("street.desc,city.desc")
sortDynamic 2
...
private def sortDynamicImpl(sortKeys: List[Seq[String]]) : Query[T,E] = {
sortKeys match {
case key :: tail =>
sortDynamicImpl( tail ).sortBy( table =>
key match {
case name :: Nil =>
table.column[String](name).asc
case name :: "ASC" :: Nil => table.column[String](name).asc
case name :: "DESC" :: Nil => table.column[String](name).desc
case o => throw new Exception("invalid sorting key: "+o)
}
)
case Nil => query
}
}
}
suppliers.sortDynamic("street.desc,city.desc")
Summary
• Query composition and re-use
• Getting rid of boiler plate in Slick 2.0
–
–
–

outer joins / auto joins
auto increment
code generation

• Dynamic Slick queries
Thank you

#scalax
slick.typesafe.com
@cvogt
http://slick.typesafe.com/talks/
https://github.com/cvogt/slick-presentation/tree/scala-exchange-2013
filterDynamic
coffees.filterDynamic("COF_NAME like Decaf")
Ad

More Related Content

What's hot (20)

Fun with Network Interfaces
Fun with Network InterfacesFun with Network Interfaces
Fun with Network Interfaces
Kernel TLV
 
LXC入門 - Osc2011 nagoya
LXC入門 - Osc2011 nagoyaLXC入門 - Osc2011 nagoya
LXC入門 - Osc2011 nagoya
Masahide Yamamoto
 
これからLDAPを始めるなら 「389-ds」を使ってみよう
これからLDAPを始めるなら 「389-ds」を使ってみようこれからLDAPを始めるなら 「389-ds」を使ってみよう
これからLDAPを始めるなら 「389-ds」を使ってみよう
Nobuyuki Sasaki
 
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScaleThe Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
Colin Charles
 
Open Policy Agent (OPA) 入門
Open Policy Agent (OPA) 入門Open Policy Agent (OPA) 入門
Open Policy Agent (OPA) 入門
Motonori Shindo
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
kwatch
 
Linux女子部 iptables復習編
Linux女子部 iptables復習編Linux女子部 iptables復習編
Linux女子部 iptables復習編
Etsuji Nakai
 
Continuous Integration and Kamailio
Continuous Integration and KamailioContinuous Integration and Kamailio
Continuous Integration and Kamailio
Giacomo Vacca
 
OpenStack概要 ~仮想ネットワーク~
OpenStack概要 ~仮想ネットワーク~OpenStack概要 ~仮想ネットワーク~
OpenStack概要 ~仮想ネットワーク~
Masaya Aoyama
 
イマドキ!ユースケース別に見るAWS IoT への接続パターン
イマドキ!ユースケース別に見るAWS IoT への接続パターンイマドキ!ユースケース別に見るAWS IoT への接続パターン
イマドキ!ユースケース別に見るAWS IoT への接続パターン
seiichi arai
 
Palo alto networks NAT flow logic
Palo alto networks NAT flow logicPalo alto networks NAT flow logic
Palo alto networks NAT flow logic
Alberto Rivai
 
Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm
Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm
Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm
NATS
 
AvailabilityZoneとHostAggregate
AvailabilityZoneとHostAggregateAvailabilityZoneとHostAggregate
AvailabilityZoneとHostAggregate
Hiroki Ishikawa
 
Parser combinatorってなんなのさ
Parser combinatorってなんなのさParser combinatorってなんなのさ
Parser combinatorってなんなのさ
cct-inc
 
High Availability PostgreSQL with Zalando Patroni
High Availability PostgreSQL with Zalando PatroniHigh Availability PostgreSQL with Zalando Patroni
High Availability PostgreSQL with Zalando Patroni
Zalando Technology
 
import dpkt したよ #ssmjp 2014/02/28
import dpkt したよ #ssmjp 2014/02/28import dpkt したよ #ssmjp 2014/02/28
import dpkt したよ #ssmjp 2014/02/28
th0x0472
 
Configuración y Documentación de ACL y Firewall ASA
Configuración y Documentación de ACL y Firewall ASAConfiguración y Documentación de ACL y Firewall ASA
Configuración y Documentación de ACL y Firewall ASA
Yimy Pérez Medina
 
第20回 OpenStack勉強会 Neutron Deep Dive - DVR
第20回 OpenStack勉強会 Neutron Deep Dive - DVR第20回 OpenStack勉強会 Neutron Deep Dive - DVR
第20回 OpenStack勉強会 Neutron Deep Dive - DVR
Toru Makabe
 
MariaDBとMroongaで作る全言語対応超高速全文検索システム
MariaDBとMroongaで作る全言語対応超高速全文検索システムMariaDBとMroongaで作る全言語対応超高速全文検索システム
MariaDBとMroongaで作る全言語対応超高速全文検索システム
Kouhei Sutou
 
L2 over l3 ecnaspsulations (english)
L2 over l3 ecnaspsulations (english)L2 over l3 ecnaspsulations (english)
L2 over l3 ecnaspsulations (english)
Motonori Shindo
 
Fun with Network Interfaces
Fun with Network InterfacesFun with Network Interfaces
Fun with Network Interfaces
Kernel TLV
 
これからLDAPを始めるなら 「389-ds」を使ってみよう
これからLDAPを始めるなら 「389-ds」を使ってみようこれからLDAPを始めるなら 「389-ds」を使ってみよう
これからLDAPを始めるなら 「389-ds」を使ってみよう
Nobuyuki Sasaki
 
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScaleThe Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
The Proxy Wars - MySQL Router, ProxySQL, MariaDB MaxScale
Colin Charles
 
Open Policy Agent (OPA) 入門
Open Policy Agent (OPA) 入門Open Policy Agent (OPA) 入門
Open Policy Agent (OPA) 入門
Motonori Shindo
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
kwatch
 
Linux女子部 iptables復習編
Linux女子部 iptables復習編Linux女子部 iptables復習編
Linux女子部 iptables復習編
Etsuji Nakai
 
Continuous Integration and Kamailio
Continuous Integration and KamailioContinuous Integration and Kamailio
Continuous Integration and Kamailio
Giacomo Vacca
 
OpenStack概要 ~仮想ネットワーク~
OpenStack概要 ~仮想ネットワーク~OpenStack概要 ~仮想ネットワーク~
OpenStack概要 ~仮想ネットワーク~
Masaya Aoyama
 
イマドキ!ユースケース別に見るAWS IoT への接続パターン
イマドキ!ユースケース別に見るAWS IoT への接続パターンイマドキ!ユースケース別に見るAWS IoT への接続パターン
イマドキ!ユースケース別に見るAWS IoT への接続パターン
seiichi arai
 
Palo alto networks NAT flow logic
Palo alto networks NAT flow logicPalo alto networks NAT flow logic
Palo alto networks NAT flow logic
Alberto Rivai
 
Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm
Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm
Simple and Scalable Microservices: Using NATS with Docker Compose and Swarm
NATS
 
AvailabilityZoneとHostAggregate
AvailabilityZoneとHostAggregateAvailabilityZoneとHostAggregate
AvailabilityZoneとHostAggregate
Hiroki Ishikawa
 
Parser combinatorってなんなのさ
Parser combinatorってなんなのさParser combinatorってなんなのさ
Parser combinatorってなんなのさ
cct-inc
 
High Availability PostgreSQL with Zalando Patroni
High Availability PostgreSQL with Zalando PatroniHigh Availability PostgreSQL with Zalando Patroni
High Availability PostgreSQL with Zalando Patroni
Zalando Technology
 
import dpkt したよ #ssmjp 2014/02/28
import dpkt したよ #ssmjp 2014/02/28import dpkt したよ #ssmjp 2014/02/28
import dpkt したよ #ssmjp 2014/02/28
th0x0472
 
Configuración y Documentación de ACL y Firewall ASA
Configuración y Documentación de ACL y Firewall ASAConfiguración y Documentación de ACL y Firewall ASA
Configuración y Documentación de ACL y Firewall ASA
Yimy Pérez Medina
 
第20回 OpenStack勉強会 Neutron Deep Dive - DVR
第20回 OpenStack勉強会 Neutron Deep Dive - DVR第20回 OpenStack勉強会 Neutron Deep Dive - DVR
第20回 OpenStack勉強会 Neutron Deep Dive - DVR
Toru Makabe
 
MariaDBとMroongaで作る全言語対応超高速全文検索システム
MariaDBとMroongaで作る全言語対応超高速全文検索システムMariaDBとMroongaで作る全言語対応超高速全文検索システム
MariaDBとMroongaで作る全言語対応超高速全文検索システム
Kouhei Sutou
 
L2 over l3 ecnaspsulations (english)
L2 over l3 ecnaspsulations (english)L2 over l3 ecnaspsulations (english)
L2 over l3 ecnaspsulations (english)
Motonori Shindo
 

Viewers also liked (16)

Slick: Bringing Scala’s Powerful Features to Your Database Access
Slick: Bringing Scala’s Powerful Features to Your Database Access Slick: Bringing Scala’s Powerful Features to Your Database Access
Slick: Bringing Scala’s Powerful Features to Your Database Access
Rebecca Grenier
 
Slick 3.0 functional programming and db side effects
Slick 3.0   functional programming and db side effectsSlick 3.0   functional programming and db side effects
Slick 3.0 functional programming and db side effects
Joost de Vries
 
Reactive Database Access With Slick 3
Reactive Database Access With Slick 3Reactive Database Access With Slick 3
Reactive Database Access With Slick 3
Igor Mielientiev
 
Slick: A control plane for middleboxes
Slick: A control plane for middleboxesSlick: A control plane for middleboxes
Slick: A control plane for middleboxes
Open Networking Summits
 
Building Scalable, Distributed Job Queues with Redis and Redis::Client
Building Scalable, Distributed Job Queues with Redis and Redis::ClientBuilding Scalable, Distributed Job Queues with Redis and Redis::Client
Building Scalable, Distributed Job Queues with Redis and Redis::Client
Mike Friedman
 
Domain Driven Design Experience Report
Domain Driven Design Experience ReportDomain Driven Design Experience Report
Domain Driven Design Experience Report
Skills Matter
 
Slick – the modern way to access your Data
Slick – the modern way to access your DataSlick – the modern way to access your Data
Slick – the modern way to access your Data
Jochen Huelss
 
実戦Scala
実戦Scala実戦Scala
実戦Scala
Yuto Suzuki
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with Slick
Hermann Hueck
 
Slick - The Structured Way
Slick - The Structured WaySlick - The Structured Way
Slick - The Structured Way
Yennick Trevels
 
CQRS and what it means for your architecture
CQRS and what it means for your architectureCQRS and what it means for your architecture
CQRS and what it means for your architecture
Richard Banks
 
Reactive database access with Slick3
Reactive database access with Slick3Reactive database access with Slick3
Reactive database access with Slick3
takezoe
 
Spark Hands-on
Spark Hands-onSpark Hands-on
Spark Hands-on
Gaspar Muñoz Soria
 
Architecting Microservices in .Net
Architecting Microservices in .NetArchitecting Microservices in .Net
Architecting Microservices in .Net
Richard Banks
 
Akka in Practice: Designing Actor-based Applications
Akka in Practice: Designing Actor-based ApplicationsAkka in Practice: Designing Actor-based Applications
Akka in Practice: Designing Actor-based Applications
NLJUG
 
Modern SQL in Open Source and Commercial Databases
Modern SQL in Open Source and Commercial DatabasesModern SQL in Open Source and Commercial Databases
Modern SQL in Open Source and Commercial Databases
Markus Winand
 
Slick: Bringing Scala’s Powerful Features to Your Database Access
Slick: Bringing Scala’s Powerful Features to Your Database Access Slick: Bringing Scala’s Powerful Features to Your Database Access
Slick: Bringing Scala’s Powerful Features to Your Database Access
Rebecca Grenier
 
Slick 3.0 functional programming and db side effects
Slick 3.0   functional programming and db side effectsSlick 3.0   functional programming and db side effects
Slick 3.0 functional programming and db side effects
Joost de Vries
 
Reactive Database Access With Slick 3
Reactive Database Access With Slick 3Reactive Database Access With Slick 3
Reactive Database Access With Slick 3
Igor Mielientiev
 
Building Scalable, Distributed Job Queues with Redis and Redis::Client
Building Scalable, Distributed Job Queues with Redis and Redis::ClientBuilding Scalable, Distributed Job Queues with Redis and Redis::Client
Building Scalable, Distributed Job Queues with Redis and Redis::Client
Mike Friedman
 
Domain Driven Design Experience Report
Domain Driven Design Experience ReportDomain Driven Design Experience Report
Domain Driven Design Experience Report
Skills Matter
 
Slick – the modern way to access your Data
Slick – the modern way to access your DataSlick – the modern way to access your Data
Slick – the modern way to access your Data
Jochen Huelss
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with Slick
Hermann Hueck
 
Slick - The Structured Way
Slick - The Structured WaySlick - The Structured Way
Slick - The Structured Way
Yennick Trevels
 
CQRS and what it means for your architecture
CQRS and what it means for your architectureCQRS and what it means for your architecture
CQRS and what it means for your architecture
Richard Banks
 
Reactive database access with Slick3
Reactive database access with Slick3Reactive database access with Slick3
Reactive database access with Slick3
takezoe
 
Architecting Microservices in .Net
Architecting Microservices in .NetArchitecting Microservices in .Net
Architecting Microservices in .Net
Richard Banks
 
Akka in Practice: Designing Actor-based Applications
Akka in Practice: Designing Actor-based ApplicationsAkka in Practice: Designing Actor-based Applications
Akka in Practice: Designing Actor-based Applications
NLJUG
 
Modern SQL in Open Source and Commercial Databases
Modern SQL in Open Source and Commercial DatabasesModern SQL in Open Source and Commercial Databases
Modern SQL in Open Source and Commercial Databases
Markus Winand
 
Ad

Similar to Patterns for slick database applications (20)

The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31
Mahmoud Samir Fayed
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196
Mahmoud Samir Fayed
 
Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”
Platonov Sergey
 
Mock Hell PyCon DE and PyData Berlin 2019
Mock Hell PyCon DE and PyData Berlin 2019Mock Hell PyCon DE and PyData Berlin 2019
Mock Hell PyCon DE and PyData Berlin 2019
Edwin Jung
 
The Ring programming language version 1.5.2 book - Part 29 of 181
The Ring programming language version 1.5.2 book - Part 29 of 181The Ring programming language version 1.5.2 book - Part 29 of 181
The Ring programming language version 1.5.2 book - Part 29 of 181
Mahmoud Samir Fayed
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 54 of 184
The Ring programming language version 1.5.3 book - Part 54 of 184The Ring programming language version 1.5.3 book - Part 54 of 184
The Ring programming language version 1.5.3 book - Part 54 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 44 of 184
The Ring programming language version 1.5.3 book - Part 44 of 184The Ring programming language version 1.5.3 book - Part 44 of 184
The Ring programming language version 1.5.3 book - Part 44 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31
Mahmoud Samir Fayed
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
Michael Pirnat
 
The Ring programming language version 1.8 book - Part 50 of 202
The Ring programming language version 1.8 book - Part 50 of 202The Ring programming language version 1.8 book - Part 50 of 202
The Ring programming language version 1.8 book - Part 50 of 202
Mahmoud Samir Fayed
 
The Ring programming language version 1.4 book - Part 8 of 30
The Ring programming language version 1.4 book - Part 8 of 30The Ring programming language version 1.4 book - Part 8 of 30
The Ring programming language version 1.4 book - Part 8 of 30
Mahmoud Samir Fayed
 
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210
Mahmoud Samir Fayed
 
R programming language
R programming languageR programming language
R programming language
Alberto Minetti
 
The Ring programming language version 1.5.3 book - Part 40 of 184
The Ring programming language version 1.5.3 book - Part 40 of 184The Ring programming language version 1.5.3 book - Part 40 of 184
The Ring programming language version 1.5.3 book - Part 40 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 43 of 180
The Ring programming language version 1.5.1 book - Part 43 of 180The Ring programming language version 1.5.1 book - Part 43 of 180
The Ring programming language version 1.5.1 book - Part 43 of 180
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 28 of 180
The Ring programming language version 1.5.1 book - Part 28 of 180The Ring programming language version 1.5.1 book - Part 28 of 180
The Ring programming language version 1.5.1 book - Part 28 of 180
Mahmoud Samir Fayed
 
The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84
Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
Mahmoud Samir Fayed
 
The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31
Mahmoud Samir Fayed
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196
Mahmoud Samir Fayed
 
Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”
Platonov Sergey
 
Mock Hell PyCon DE and PyData Berlin 2019
Mock Hell PyCon DE and PyData Berlin 2019Mock Hell PyCon DE and PyData Berlin 2019
Mock Hell PyCon DE and PyData Berlin 2019
Edwin Jung
 
The Ring programming language version 1.5.2 book - Part 29 of 181
The Ring programming language version 1.5.2 book - Part 29 of 181The Ring programming language version 1.5.2 book - Part 29 of 181
The Ring programming language version 1.5.2 book - Part 29 of 181
Mahmoud Samir Fayed
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 54 of 184
The Ring programming language version 1.5.3 book - Part 54 of 184The Ring programming language version 1.5.3 book - Part 54 of 184
The Ring programming language version 1.5.3 book - Part 54 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 44 of 184
The Ring programming language version 1.5.3 book - Part 44 of 184The Ring programming language version 1.5.3 book - Part 44 of 184
The Ring programming language version 1.5.3 book - Part 44 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31
Mahmoud Samir Fayed
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
Michael Pirnat
 
The Ring programming language version 1.8 book - Part 50 of 202
The Ring programming language version 1.8 book - Part 50 of 202The Ring programming language version 1.8 book - Part 50 of 202
The Ring programming language version 1.8 book - Part 50 of 202
Mahmoud Samir Fayed
 
The Ring programming language version 1.4 book - Part 8 of 30
The Ring programming language version 1.4 book - Part 8 of 30The Ring programming language version 1.4 book - Part 8 of 30
The Ring programming language version 1.4 book - Part 8 of 30
Mahmoud Samir Fayed
 
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 40 of 184
The Ring programming language version 1.5.3 book - Part 40 of 184The Ring programming language version 1.5.3 book - Part 40 of 184
The Ring programming language version 1.5.3 book - Part 40 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 43 of 180
The Ring programming language version 1.5.1 book - Part 43 of 180The Ring programming language version 1.5.1 book - Part 43 of 180
The Ring programming language version 1.5.1 book - Part 43 of 180
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 28 of 180
The Ring programming language version 1.5.1 book - Part 28 of 180The Ring programming language version 1.5.1 book - Part 28 of 180
The Ring programming language version 1.5.1 book - Part 28 of 180
Mahmoud Samir Fayed
 
The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84
Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
Mahmoud Samir Fayed
 
Ad

More from Skills Matter (20)

5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence
Skills Matter
 
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvmScala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Skills Matter
 
Oscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheimOscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheim
Skills Matter
 
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Skills Matter
 
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberlCukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Skills Matter
 
Cukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.jsCukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.js
Skills Matter
 
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Skills Matter
 
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Skills Matter
 
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source worldProgressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Skills Matter
 
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Skills Matter
 
Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#
Skills Matter
 
A poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testingA poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testing
Skills Matter
 
Russ miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-diveRuss miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-dive
Skills Matter
 
Serendipity-neo4j
Serendipity-neo4jSerendipity-neo4j
Serendipity-neo4j
Skills Matter
 
Simon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelismSimon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelism
Skills Matter
 
Plug 20110217
Plug   20110217Plug   20110217
Plug 20110217
Skills Matter
 
Lug presentation
Lug presentationLug presentation
Lug presentation
Skills Matter
 
I went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_tI went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_t
Skills Matter
 
Plug saiku
Plug   saikuPlug   saiku
Plug saiku
Skills Matter
 
Huguk lily
Huguk lilyHuguk lily
Huguk lily
Skills Matter
 
5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence
Skills Matter
 
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvmScala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Skills Matter
 
Oscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheimOscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheim
Skills Matter
 
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Skills Matter
 
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberlCukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Skills Matter
 
Cukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.jsCukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.js
Skills Matter
 
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Skills Matter
 
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Skills Matter
 
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source worldProgressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Skills Matter
 
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Skills Matter
 
Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#
Skills Matter
 
A poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testingA poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testing
Skills Matter
 
Russ miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-diveRuss miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-dive
Skills Matter
 
Simon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelismSimon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelism
Skills Matter
 
I went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_tI went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_t
Skills Matter
 

Recently uploaded (20)

Learn the Basics of Agile Development: Your Step-by-Step Guide
Learn the Basics of Agile Development: Your Step-by-Step GuideLearn the Basics of Agile Development: Your Step-by-Step Guide
Learn the Basics of Agile Development: Your Step-by-Step Guide
Marcel David
 
Network Security. Different aspects of Network Security.
Network Security. Different aspects of Network Security.Network Security. Different aspects of Network Security.
Network Security. Different aspects of Network Security.
gregtap1
 
Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025
Splunk
 
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptxDevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
Justin Reock
 
#AdminHour presents: Hour of Code2018 slide deck from 12/6/2018
#AdminHour presents: Hour of Code2018 slide deck from 12/6/2018#AdminHour presents: Hour of Code2018 slide deck from 12/6/2018
#AdminHour presents: Hour of Code2018 slide deck from 12/6/2018
Lynda Kane
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Mobile App Development Company in Saudi Arabia
Mobile App Development Company in Saudi ArabiaMobile App Development Company in Saudi Arabia
Mobile App Development Company in Saudi Arabia
Steve Jonas
 
Semantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AISemantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AI
artmondano
 
Leading AI Innovation As A Product Manager - Michael Jidael
Leading AI Innovation As A Product Manager - Michael JidaelLeading AI Innovation As A Product Manager - Michael Jidael
Leading AI Innovation As A Product Manager - Michael Jidael
Michael Jidael
 
Datastucture-Unit 4-Linked List Presentation.pptx
Datastucture-Unit 4-Linked List Presentation.pptxDatastucture-Unit 4-Linked List Presentation.pptx
Datastucture-Unit 4-Linked List Presentation.pptx
kaleeswaric3
 
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
SOFTTECHHUB
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
"PHP and MySQL CRUD Operations for Student Management System"
"PHP and MySQL CRUD Operations for Student Management System""PHP and MySQL CRUD Operations for Student Management System"
"PHP and MySQL CRUD Operations for Student Management System"
Jainul Musani
 
Enhancing ICU Intelligence: How Our Functional Testing Enabled a Healthcare I...
Enhancing ICU Intelligence: How Our Functional Testing Enabled a Healthcare I...Enhancing ICU Intelligence: How Our Functional Testing Enabled a Healthcare I...
Enhancing ICU Intelligence: How Our Functional Testing Enabled a Healthcare I...
Impelsys Inc.
 
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdfThe Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
Abi john
 
Automation Dreamin' 2022: Sharing Some Gratitude with Your Users
Automation Dreamin' 2022: Sharing Some Gratitude with Your UsersAutomation Dreamin' 2022: Sharing Some Gratitude with Your Users
Automation Dreamin' 2022: Sharing Some Gratitude with Your Users
Lynda Kane
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In FranceManifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
chb3
 
Rock, Paper, Scissors: An Apex Map Learning Journey
Rock, Paper, Scissors: An Apex Map Learning JourneyRock, Paper, Scissors: An Apex Map Learning Journey
Rock, Paper, Scissors: An Apex Map Learning Journey
Lynda Kane
 
Learn the Basics of Agile Development: Your Step-by-Step Guide
Learn the Basics of Agile Development: Your Step-by-Step GuideLearn the Basics of Agile Development: Your Step-by-Step Guide
Learn the Basics of Agile Development: Your Step-by-Step Guide
Marcel David
 
Network Security. Different aspects of Network Security.
Network Security. Different aspects of Network Security.Network Security. Different aspects of Network Security.
Network Security. Different aspects of Network Security.
gregtap1
 
Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025
Splunk
 
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptxDevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
Justin Reock
 
#AdminHour presents: Hour of Code2018 slide deck from 12/6/2018
#AdminHour presents: Hour of Code2018 slide deck from 12/6/2018#AdminHour presents: Hour of Code2018 slide deck from 12/6/2018
#AdminHour presents: Hour of Code2018 slide deck from 12/6/2018
Lynda Kane
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Mobile App Development Company in Saudi Arabia
Mobile App Development Company in Saudi ArabiaMobile App Development Company in Saudi Arabia
Mobile App Development Company in Saudi Arabia
Steve Jonas
 
Semantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AISemantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AI
artmondano
 
Leading AI Innovation As A Product Manager - Michael Jidael
Leading AI Innovation As A Product Manager - Michael JidaelLeading AI Innovation As A Product Manager - Michael Jidael
Leading AI Innovation As A Product Manager - Michael Jidael
Michael Jidael
 
Datastucture-Unit 4-Linked List Presentation.pptx
Datastucture-Unit 4-Linked List Presentation.pptxDatastucture-Unit 4-Linked List Presentation.pptx
Datastucture-Unit 4-Linked List Presentation.pptx
kaleeswaric3
 
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
SOFTTECHHUB
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
"PHP and MySQL CRUD Operations for Student Management System"
"PHP and MySQL CRUD Operations for Student Management System""PHP and MySQL CRUD Operations for Student Management System"
"PHP and MySQL CRUD Operations for Student Management System"
Jainul Musani
 
Enhancing ICU Intelligence: How Our Functional Testing Enabled a Healthcare I...
Enhancing ICU Intelligence: How Our Functional Testing Enabled a Healthcare I...Enhancing ICU Intelligence: How Our Functional Testing Enabled a Healthcare I...
Enhancing ICU Intelligence: How Our Functional Testing Enabled a Healthcare I...
Impelsys Inc.
 
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdfThe Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
Abi john
 
Automation Dreamin' 2022: Sharing Some Gratitude with Your Users
Automation Dreamin' 2022: Sharing Some Gratitude with Your UsersAutomation Dreamin' 2022: Sharing Some Gratitude with Your Users
Automation Dreamin' 2022: Sharing Some Gratitude with Your Users
Lynda Kane
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In FranceManifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
chb3
 
Rock, Paper, Scissors: An Apex Map Learning Journey
Rock, Paper, Scissors: An Apex Map Learning JourneyRock, Paper, Scissors: An Apex Map Learning Journey
Rock, Paper, Scissors: An Apex Map Learning Journey
Lynda Kane
 

Patterns for slick database applications

  • 1. Patterns for Slick database applications Jan Christopher Vogt, EPFL Slick Team #scalax
  • 2. Recap: What is Slick? (for ( c <- coffees; if c.sales > 999 ) yield c.name).run select "COF_NAME" from "COFFEES" where "SALES" > 999
  • 3. Agenda • Query composition and re-use • Getting rid of boiler plate in Slick 2.0 – – – outer joins / auto joins auto increment code generation • Dynamic Slick queries
  • 5. For-expression desugaring in Scala for ( c <- coffees; if c.sales > 999 ) yield c.name coffees .withFilter(_.sales > 999) .map(_.name)
  • 6. Types in Slick class Coffees(tag: Tag) extends Table[C](tag,"COFFEES”) { def * = (name, supId, price, sales, total) <> ... val name = column[String]("COF_NAME", O.PrimaryKey) val supId = column[Int]("SUP_ID") val price = column[BigDecimal]("PRICE") val sales = column[Int]("SALES") val total = column[Int]("TOTAL") } lazy val coffees = TableQuery[Coffees] <: Query[Coffees,C] coffees.map(c => c.name) (coffees:TableQuery[Coffees,_]).map( (coffees ).map( (c:Coffees) => (c.name Column[String]) (c.name: (c ) ) ): Query[Column[String],String] )
  • 7. Table extensions class Coffees(tag: Tag) extends Table[C](tag,"COFFEES”) { … val price = column[BigDecimal]("PRICE") val sales = column[Int]("SALES") def revenue = price.asColumnOf[Double] * sales.asColumnOf[Double] } coffees.map(c => c.revenue)
  • 8. Query extensions implicit class QueryExtensions[T,E] ( val q: Query[T,E] ){ def page(no: Int, pageSize: Int = 10) : Query[T,E] = q.drop( (no-1)*pageSize ).take(pageSize) } suppliers.page(5) coffees.sortBy(_.name).page(5)
  • 9. Query extensions by Table implicit class CoffeesExtensions ( val q: Query[Coffees,C] ){ def byName( name: Column[String] ) : Query[Coffees,C] = q.filter(_.name === name).sortBy(_.name) } coffees.byName("ColumbianDecaf").page(5)
  • 10. Query extensions for joins implicit class CoffeesExtensions2( val q: Query[Coffees,C] ){ def withSuppliers (s: Query[Suppliers,S] = Tables.suppliers) : Query[(Coffees,Suppliers),(C,S)] = q.join(s).on(_.supId===_.id) def suppliers (s: Query[Suppliers, S] = Tables.suppliers) : Query[Suppliers, S] = q.withSuppliers(s).map(_._2) } coffees.withSuppliers() : Query[(Coffees,Suppliers),(C,S) coffees.withSuppliers( suppliers.filter(_.city === "Henderson") ) // buyable coffees coffeeShops.coffees().suppliers().withCoffees()
  • 11. Query extensions by Interface trait HasSuppliers{ def supId: Column[Int] } class Coffees(…) extends Table... with HasSuppliers {…} class CofInventory(…) extends Table... with HasSuppliers {…} implicit class HasSuppliersExtensions[T <: HasSupplier,E] ( val q: Query[T,E] ){ def bySupId(id: Column[Int]): Query[T,E] = q.filter( _.supId === id ) def withSuppliers (s: Query[Suppliers,S] = Tables.suppliers) : Query[(T,Suppliers),(E,S)] = q.join(s).on(_.supId===_.id) def suppliers ... } // available quantities of coffees cofInventory.withSuppliers() .map{ case (i,s) => i.quantity.asColumnOf[String] ++ " of " ++ i.cofName ++ " at " ++ s.name }
  • 12. Query extensions summary • Mindshift required! Think code, not monolithic query strings. • Stay completely lazy! Keep Query[…]s as long as you can. • Re-use! Write query functions or extensions methods for shorter, better and DRY code.
  • 13. Getting rid of boilerplate
  • 15. Auto joins implicit class QueryExtensions2[T,E] ( val q: Query[T,E] ){ def autoJoin[T2,E2] ( q2:Query[T2,E2] ) ( implicit condition: (T,T2) => Column[Boolean] ) : Query[(T,T2),(E,E2)] = q.join(q2).on(condition) } implicit def joinCondition1 = (c:Coffees,s:Suppliers) => c.supId === s.id coffees.autoJoin( suppliers ) : Query[(Coffees,Suppliers),(C,S)] coffees.autoJoin( suppliers ).map(_._2).autoJoin(cofInventory)
  • 17. Auto incrementing inserts val supplier = Supplier( 0, "Arabian Coffees Inc.", ... ) // now ignores auto-increment column suppliers.insert( supplier ) // includes auto-increment column suppliers.forceInsert( supplier )
  • 19. Code generator for Slick code // runner for default config import scala.slick.meta.codegen.SourceCodeGenerator SourceCodeGenerator.main( Array( "scala.slick.driver.H2Driver", "org.h2.Driver", "jdbc:h2:mem:test", "src/main/scala/", // base src folder "demo" // package ) )
  • 20. Generated code package demo object Tables extends { val profile = scala.slick.driver.H2Driver } with Tables trait Tables { val profile: scala.slick.driver.JdbcProfile import profile.simple._ case class CoffeeRow(name: String, supId: Int, ...) implicit def GetCoffees = GetResult{r => CoffeeRow.tupled((r.<<, ... )) } class Coffees(tag: Tag) extends Table[CoffeeRow](…){…} ...
  • 22. Outer join limitation in Slick suppliers.leftJoin(coffees) .on(_.id === _.supId) .run // SlickException: Read NULL value ... id name name supId 1 Superior Coffee NULL NULL 2 Acme, Inc. Colombian 2 2 Acme, Inc. French_Roast 2 LEFT JOIN id name name supId 1 Superior Coffee Colombian 2 2 Acme, Inc. French_Roast 2
  • 23. Outer join pattern suppliers.leftJoin(coffees) .on(_.id === _.supId) .map{ case(s,c) => (s,(c.name.?,c.supId.?,…)) } .run .map{ case (s,c) => (s,c._1.map(_ => Coffee(c._1.get,c._2.get,…))) } // Generated outer join helper suppliers.leftJoin(coffees) .on(_.id === _.supId) .map{ case(s,c) => (s,c.?) } .run
  • 25. Using code generator as a library val metaModel = db.withSession{ implicit session => profile.metaModel // e.g. H2Driver.metaModel } import scala.slick.meta.codegen.SourceCodeGenerator val codegen = new SourceCodeGenerator(metaModel){ // <- customize here } codegen.writeToFile( profile = "scala.slick.driver.H2Driver”, folder = "src/main/scala/", pkg = "demo", container = "Tables", fileName="Tables.scala" )
  • 26. Adjust name mapping import scala.slick.util.StringExtensions._ val codegen = new SourceCodeGenerator(metaModel){ override def tableName = _.toLowerCase.toCamelCase override def entityName = tableName(_).dropRight(1) }
  • 27. Generate auto-join conditions 1 class CustomizedCodeGenerator(metaModel: Model) extends SourceCodeGenerator(metaModel){ override def code = { super.code + "nn" + s""" /** implicit join conditions for auto joins */ object AutoJoins{ ${indent(joins.mkString("n"))} } """.trim() } …
  • 28. Generate auto-join conditions 2 … val joins = tables.flatMap( _.foreignKeys.map{ foreignKey => import foreignKey._ val fkt = referencingTable.tableClassName val pkt = referencedTable.tableClassName val columns = referencingColumns.map(_.name) zip referencedColumns.map(_.name) s"implicit def autojoin${name.capitalize} "+ " = (left:${fkt},right:${pkt}) => " + columns.map{ case (lcol,rcol) => "left."+lcol + " === " + "right."+rcol }.mkString(" && ") }
  • 29. Other uses of Slick code generation • Glue code (Play, etc.) • n-n join code • Migrating databases (warning: types change) (generate from MySQL, create in Postgres) • Generate repetitive regarding data model (aka model driven software engineering) • Generate DDL for external model
  • 30. Use code generation wisely • Don’t loose language-level abstraction • Add your generator and data model to version control • Complete but new and therefor experimental in Slick
  • 32. Common use case for web apps Dynamically decide • displayed columns • filter conditions • sort columns / order
  • 33. Dynamic column class Coffees(tag: Tag) extends Table[CoffeeRow](…){ val name = column[String]("COF_NAME",…) } coffees.map(c => c.name) coffees.map(c => c.column[String]("COF_NAME") ) Be careful about security!
  • 35. sortDynamic 1 implicit class QueryExtensions3[E,T<: Table[E]] ( val query: Query[T,E] ){ def sortDynamic(sortString: String) : Query[T,E] = { // split string into useful pieces val sortKeys = sortString.split(',').toList.map( _.split('.').map(_.toUpperCase).toList ) sortDynamicImpl(sortKeys) } private def sortDynamicImpl(sortKeys: List[Seq[String]]) = ??? } suppliers.sortDynamic("street.desc,city.desc")
  • 36. sortDynamic 2 ... private def sortDynamicImpl(sortKeys: List[Seq[String]]) : Query[T,E] = { sortKeys match { case key :: tail => sortDynamicImpl( tail ).sortBy( table => key match { case name :: Nil => table.column[String](name).asc case name :: "ASC" :: Nil => table.column[String](name).asc case name :: "DESC" :: Nil => table.column[String](name).desc case o => throw new Exception("invalid sorting key: "+o) } ) case Nil => query } } } suppliers.sortDynamic("street.desc,city.desc")
  • 37. Summary • Query composition and re-use • Getting rid of boiler plate in Slick 2.0 – – – outer joins / auto joins auto increment code generation • Dynamic Slick queries

Editor's Notes

  • #2: Not an introductory talk, but with some Scala knowledge you should be able to follow even if you don’t know Slick &lt;number&gt;
  • #3: underlines -&gt; implicit conversions lazy query builder, explicit execution &lt;number&gt;
  • #4: &lt;number&gt;
  • #5: Embrace! Slick’s single coolest features! &lt;number&gt;
  • #7: C is element type alias, can be tuple or case class Table is row prototype &lt;number&gt;
  • #8: asColumn &lt;number&gt;
  • #10: C is element type of Coffees here, can be Coffee case class or Tuple &lt;number&gt;
  • #11: that’s the way to do association in slick, because it is lazy, composes val can put into method &lt;number&gt;
  • #13: string computed server side, which means still lazy and composable &lt;number&gt;
  • #14: none of what we have seen actually executed the query. just composed. call .run for ONE roundtrip &lt;number&gt;
  • #21: Run from shell or sbt as sourceGenerator or using separate &lt;number&gt;
  • #22: // not tied to a driver // entity class // table class // GetResult // Slick Hlists for &gt; 22 columns. &lt;number&gt;
  • #25: not big problem, when select exact &lt;number&gt;
  • #27: needs staged sbt build or manual execution &lt;number&gt;
  • #32: interfaces still useful &lt;number&gt;
  • #38: Limitations: - type is string - using db name Can use reflection instead &lt;number&gt;
  • #39: &lt;number&gt;
  • #40: https://github.com/cvogt/slick-presentation/tree/scala-exchange-2013 &lt;number&gt;