SlideShare a Scribd company logo
SCALA,
FUNCTIONAL PROGRAMMING AND
TEAM PRODUCTIVITY
INTRO
WHO WE ARE
▸ Pavel and Kai
▸ Septimal Mind, an Irish consultancy
▸ Engineer’s productivity is our primary concern
▸ Love Scala and pure FP
▸ Scala contributors
INTRO
WHAT WE DO
▸ We identify productivity issues in SDLC pipeline
▸ We build tools to address these issues
▸ How do we decide to write a new tool?
▸ Prototype should take one engineer at most two weeks
CASE STUDY
CASE STUDY: STARTING POINT (JAN/2018)
▸ Millions of users, +100K each month
▸ About 30 engineers
▸ Back-end: About 10 microservices, multirepo
▸ Front-end: mobile apps, web portal
▸ Scala as Java+ (akka-http, guice), C#, Go, Typescript
CASE STUDY
CASE STUDY: OUTCOME (JUN/2019)
Development costs cut by 50%
(management estimation)
CASE STUDY
WHAT WAS WRONG?
Late problem detection

Actual integration postponed to production
INTRO
WHAT WAS WRONG
▸ A lot of issues discovered in production
▸ Bugs
▸ Component incompatibilities
▸ Frontend incompatibilities
▸ Not enough insights to debug after failure
▸ Hard to just observe the product: 13 repositories
▸ Hard to get people on board
ISSUES
WHAT WAS WRONG?
No Real Continuous Integration
CASE STUDY
CASE STUDY: WHAT WE DID
The problems mentioned are fundamental...
... but we made things better...
...for this particular company
CASE STUDY
CASE STUDY: WHAT WE DID
▸ Formal interfaces: own IDL/DML/RPC compiler
▸ Better insights & metrics: own effort-free structured logging
▸ Convenient monorepo, better GIT flow
▸ Code quality: pure FP and Bifunctor Tagless Final
▸ Asynchronous stacktraces for ZIO
▸ Fast and reliable tests (including integration ones)
▸ "Flexible Monolith", multi-tenant applications
▸ Proper Continuous Integration
▸ Simplified onboarding
CASE STUDY
CASE STUDY: WHAT WE DID
Issue Solution
Late problem detection Early Integration

(IDL, Cheap Simulations, Dual tests, Bifunctor IO, Pure FP, TF)
Complicated onboarding
Better Observability

(Monorepo, Integration Checks, Dual Tests)
Lack of insights
Effortless insights

(Structural Logging, Async Stacktraces)
Code sharing
Observability, No Local Publishing

(Monorepo, Unified Stack, Unified Framework)
ISSUES
CASE STUDY: WHAT WE DID
Let's focus on
Tests and Microservices
ISSUES
WHAT WAS WRONG WITH TESTS
▸ Speed
▸ 600 tests
▸ 20 minutes total
▸ 17 for component startup and shutdown
▸ Interference
▸ Can’t run tests in parallel
▸ Slow External Dependencies
▸ Hard to wire Dummies (Guice)
ISSUES
WHAT WAS WRONG WITH MICROSERVICES
▸ Hard to share & reuse the code
▸ One shared Dev Env, hard to replicate locally
▸ Up to 70% of developer's time spent for retries and startups
▸ Automated Deployments & Orchestration
▸ Hard
▸ Fast, correct startup & shutdown are important...
▸ ...but hard to implement manually (order, variability)
GOALS
GOALS
▸ Improve development workflows
▸ Improve deployment workflows
▸ Continuously Integrate microservice fleet
▸ Improve team collaboration
▸ Simplify onboarding
GOALS
GOALS
How?


— Automatically Reconfigurable Applications
GOALS
GOALS
Product := Build(Components, Goals)
AUTOMATIC 

APPLICATION
COMPOSITION
GOALS
GOALS
▸ Test Business Logic without external dependencies
▸ Test Business Logic with real external dependencies too
▸ Correctly share (memoize) heavy resources between tests
▸ Let a new developer checkout & test immediately
▸ Let front-end engineers run isolated dev envs quickly & easily
DISTAGE FRAMEWORK
DIStage Framework
DISTAGE FRAMEWORK
AUTOMATED APPLICATION COMPOSITION: THE MODEL
object ServiceDemo {
trait Repository[F[_, _]]
class DummyRepository[F[_, _]] extends Repository[F]
class ProdRepository[F[_, _]] extends Repository[F]
class Service[F[_, _]](c: Repository[F]) extends
Repository[F]
class App[F[_, _]](s: Service[F]) {
def run: F[Throwable, Unit] = ???
}
}
DISTAGE FRAMEWORK
AUTOMATED APPLICATION COMPOSITION: DEFINITIONS
def definition[F[_, _]: TagKK] = new ModuleDef {
make[App[F]]
make[Service[F]]
make[Repository[F]].tagged(Repo.Dummy).from[DummyRepository[F]]
make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]]
}
DISTAGE FRAMEWORK
AUTOMATED APPLICATION COMPOSITION: STARTING THE APP
Injector(Activation(Repo -> Prod))
.produceRunF(definition[zio.IO]) {
app: App[zio.IO] =>
app.run
}
DISTAGE FRAMEWORK
AUTOMATED APPLICATION COMPOSITION: THE IDEA
distage app

=

set of formulas

Product := Recipe(Materials, ...)

+

set of "root" products

Set(Roots, ...)

+

configuration rules

Activation
DISTAGE FRAMEWORK
AUTOMATED APPLICATION COMPOSITION: THE DIFFERENCE
▸ Like Guice and other DIs, distage
▸ turns application wiring code into a set of declarations
▸ automatically orders wiring actions
DISTAGE FRAMEWORK
AUTOMATED APPLICATION COMPOSITION: THE DIFFERENCE
But not just that
DISTAGE FRAMEWORK
AUTOMATIC CONFIGURATIONS
make[Repository[F]].tagged(Repo.Dummy).from[DummyRepository[F]]
make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]]
DISTAGE FRAMEWORK
AUTOMATIC CONFIGURATIONS
Injector(Activation(Repo -> Repo.Prod))
make[Repository[F]].tagged(Repo.Dummy).from[DummyRepository[F]]
make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]]
DISTAGE FRAMEWORK
AUTOMATIC CONFIGURATIONS
Injector(Activation(Repo -> Repo.Prod))
make[Repository[F]].tagged(Repo.Dummy).from[DummyRepository[F]]
make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]]
DISTAGE FRAMEWORK
RESOURCES
trait DIResource[F[_], Resource] {
def acquire: F[Resource]
def release(resource: Resource): F[Unit]
}
▸ Functional description of lifecycle
▸ Initialisation without mutable state
DISTAGE FRAMEWORK
RESOURCES
// library ...
class DbDriver[F[_]] {
def shutdown: F[Unit]
}
def connectToDb[F[_]: Sync]: DbDriver[F]
// …
class ProdRepository[F[_]](db: DbDriver[F]) extends Repository
// definition ...
make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]]
make[DbDriver[F]].fromResource(DIResource.make(connectToDb)(_.shutdown))
// ...
▸ Graceful shutdown is always guaranteed, even in case of an exception
▸ Docker Containers may be expressed as resources
▸ Embedded replacement for docker-compose
DISTAGE FRAMEWORK
INTEGRATION CHECKS
▸ Check if an external service is available
▸ Tests will be skipped if checks fail
▸ The app will not start if checks fail
▸ Integration checks run before all initialisation
DISTAGE FRAMEWORK
INTEGRATION CHECKS
class DbCheck extends IntegrationCheck {
def resourcesAvailable(): ResourceCheck = {
if (checkPort()) ResourceCheck.Success()
else ResourceCheck.ResourceUnavailable("Can't connect to DB", None)
}
private def checkPort(): Boolean = ???
}
▸ Check if an external service is available
▸ Tests will be skipped if checks fail
▸ The app will not start if checks fail
▸ Integration checks run before all initialisation
DISTAGE FRAMEWORK
DUAL TEST TACTIC
▸ Helps draft business logic quickly
▸ Enforces SOLID design
▸ Does not prevent integration tests
▸ Speeds up onboarding
DISTAGE FRAMEWORK
DUAL TEST TACTIC: CODE
abstract class ServiceTest extends DistageBIOEnvSpecScalatest[ZIO] {
"our service" should {
"do something" in {
service: Service[zio.IO] => for {
// ...
} yield ()
}
}
}
trait DummyEnv extends DistageBIOEnvSpecScalatest[ZIO] {
override def config: TestConfig = super.config.copy(
activation = Activation(Repo -> Dummy))
}
trait ProdEnv extends DistageBIOEnvSpecScalatest[ZIO] {
override def config: TestConfig = super.config.copy(
activation = Activation(Repo -> Prod))
}
final class ServiceProdTest extends ServiceTest with ProdEnv
final class ServiceDummyTest extends ServiceTest with DummyEnv
DISTAGE FRAMEWORK
MEMOIZATION
abstract class DistageTestExample extends DistageBIOEnvSpecScalatest[ZIO] {
override def config: TestConfig = {
super.config.copy(memoizationRoots = Set(DIKey.get[DbDriver[zio.IO]]))
}
"our service" should {
"do something" in {
repository: Repository[zio.IO] =>
//...
}
"and do something else" in {
repository: Repository[zio.IO] =>
//...
}
}
}
DISTAGE FRAMEWORK
MEMOIZATION
▸ DbDriver will be shared across all the tests
▸ Without any singletons
▸ With graceful shutdown
▸ With separate contexts for different configurations
DISTAGE FRAMEWORK
AUTOMATED APPLICATION COMPOSITION: THE DIFFERENCE
▸ verifies correctness ahead of time
▸ supports resources and lifecycle
▸ provides a way to define configurable apps
▸ can perform integration checks ahead of time
▸ can perform graceful shutdown automatically
▸ can share components between multiple tests & entrypoints
DISTAGE:
ROLES
AS MEANS OF
CONTINUOUS INTEGRATION
Yes, Integration
DISTAGE FRAMEWORK
ROLES
class UsersRole extends RoleService[zio.Task] {
override def start(params: RawEntrypointParams, args: Vector[String]): DIResource[zio.Task, Unit] =
DIResource.make(acquire = {
// initialisation
})(release = {
_ =>
// shutdown
})
}
object UsersRole extends RoleDescriptor {
override final val id = "users"
}
# java -jar myapp.jar -u repo:prod -u transport:prod :users :accounts
# java -jar myapp.jar -u repo:dummy -u transport:vm :users :accounts
DISTAGE FRAMEWORK
ROLES
▸ Multiple "microservices" per process
▸ More flexibility for deployments
▸ Simulations
DISTAGE FRAMEWORK
ROLES
▸ Dev environment simulation in one process
▸ Even with in-memory mocks!
▸ Not a replacement for the dev env, but nice addition.
▸ Imperfect simulations are great anyway!
▸ Model imperfectness can be granularly adjusted
REAL CI
CONTINUOUS INTEGRATION
▸ A Microservice Fleet is a Distributed Application
▸ And that application is The Product
▸ Microservices are just components of our Product
▸ We should integrate them continuously too!
▸ But it's hard to start and test a distributed application
REAL CI
DISTRIBUTED APPLICATION SIMULATIONS
▸ Several "microservices" (roles) in one process
▸ Dummies for every Integration Point
▸ Easy configuration
▸ Cheap product models for Continuous Integration
▸ There is no need to fail in production
➡
DISTAGE FRAMEWORK
ROLES AND TEAMS
▸ Multi-tenant applications do not require a Monorepo
▸ It's possible to have a repository per role
▸ Each role repository may define individual role launcher
▸ And there may be one or more launcher repositories
▸ Drawback: unified framework is required
Thank you!
distage example:
https://github.com/7mind/distage-example
Pavel:
https://twitter.com/shirshovp
Kai:
https://twitter.com/kai_nyasha
Ad

Recommended

Izumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala Stack
7mind
 
ScalaUA - distage: Staged Dependency Injection
ScalaUA - distage: Staged Dependency Injection
7mind
 
Hyper-pragmatic Pure FP testing with distage-testkit
Hyper-pragmatic Pure FP testing with distage-testkit
7mind
 
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
7mind
 
JavaFX8 TestFX - CDI
JavaFX8 TestFX - CDI
Sven Ruppert
 
Making React Native UI Components with Swift
Making React Native UI Components with Swift
Ray Deck
 
vJUG - The JavaFX Ecosystem
vJUG - The JavaFX Ecosystem
Andres Almiray
 
Js tacktalk team dev js testing performance
Js tacktalk team dev js testing performance
Артем Захарченко
 
Test Driven Development with JavaFX
Test Driven Development with JavaFX
Hendrik Ebbers
 
Testing Legacy Rails Apps
Testing Legacy Rails Apps
Rabble .
 
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Julian Robichaux
 
How to setup unit testing in Android Studio
How to setup unit testing in Android Studio
tobiaspreuss
 
Java 9 New Features
Java 9 New Features
Ali BAKAN
 
Introduction maven3 and gwt2.5 rc2 - Lesson 01
Introduction maven3 and gwt2.5 rc2 - Lesson 01
rhemsolutions
 
Efficient JavaScript Unit Testing, JavaOne China 2013
Efficient JavaScript Unit Testing, JavaOne China 2013
Hazem Saleh
 
[AnDevCon 2016] Mutation Testing for Android
[AnDevCon 2016] Mutation Testing for Android
Hazem Saleh
 
Load Testing with k6 framework
Load Testing with k6 framework
Svetlin Nakov
 
Unit Test Android Without Going Bald
Unit Test Android Without Going Bald
David Carver
 
Managed Beans: When, Why and How
Managed Beans: When, Why and How
Russell Maher
 
Unit testing - A&BP CC
Unit testing - A&BP CC
JWORKS powered by Ordina
 
Architecting your GWT applications with GWT-Platform - Lesson 02
Architecting your GWT applications with GWT-Platform - Lesson 02
rhemsolutions
 
Testing Your Application On Google App Engine
Testing Your Application On Google App Engine
IndicThreads
 
Sling IDE Tooling
Sling IDE Tooling
Robert Munteanu
 
PHP Unit Testing in Yii
PHP Unit Testing in Yii
IlPeach
 
Devoxx17 - Préparez-vous à la modularité selon Java 9
Devoxx17 - Préparez-vous à la modularité selon Java 9
Alexis Hassler
 
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
chrisb206 chrisb206
 
Супер быстрая автоматизация тестирования на iOS
Супер быстрая автоматизация тестирования на iOS
SQALab
 
Working Effectively With Legacy Code
Working Effectively With Legacy Code
scidept
 
Javaone - Gradle: Harder, Better, Stronger, Faster
Javaone - Gradle: Harder, Better, Stronger, Faster
Andres Almiray
 
Real-World DevOps — 20 Practical Developers Tips for Tightening Your Operatio...
Real-World DevOps — 20 Practical Developers Tips for Tightening Your Operatio...
VictorSzoltysek
 

More Related Content

What's hot (20)

Test Driven Development with JavaFX
Test Driven Development with JavaFX
Hendrik Ebbers
 
Testing Legacy Rails Apps
Testing Legacy Rails Apps
Rabble .
 
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Julian Robichaux
 
How to setup unit testing in Android Studio
How to setup unit testing in Android Studio
tobiaspreuss
 
Java 9 New Features
Java 9 New Features
Ali BAKAN
 
Introduction maven3 and gwt2.5 rc2 - Lesson 01
Introduction maven3 and gwt2.5 rc2 - Lesson 01
rhemsolutions
 
Efficient JavaScript Unit Testing, JavaOne China 2013
Efficient JavaScript Unit Testing, JavaOne China 2013
Hazem Saleh
 
[AnDevCon 2016] Mutation Testing for Android
[AnDevCon 2016] Mutation Testing for Android
Hazem Saleh
 
Load Testing with k6 framework
Load Testing with k6 framework
Svetlin Nakov
 
Unit Test Android Without Going Bald
Unit Test Android Without Going Bald
David Carver
 
Managed Beans: When, Why and How
Managed Beans: When, Why and How
Russell Maher
 
Unit testing - A&BP CC
Unit testing - A&BP CC
JWORKS powered by Ordina
 
Architecting your GWT applications with GWT-Platform - Lesson 02
Architecting your GWT applications with GWT-Platform - Lesson 02
rhemsolutions
 
Testing Your Application On Google App Engine
Testing Your Application On Google App Engine
IndicThreads
 
Sling IDE Tooling
Sling IDE Tooling
Robert Munteanu
 
PHP Unit Testing in Yii
PHP Unit Testing in Yii
IlPeach
 
Devoxx17 - Préparez-vous à la modularité selon Java 9
Devoxx17 - Préparez-vous à la modularité selon Java 9
Alexis Hassler
 
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
chrisb206 chrisb206
 
Супер быстрая автоматизация тестирования на iOS
Супер быстрая автоматизация тестирования на iOS
SQALab
 
Working Effectively With Legacy Code
Working Effectively With Legacy Code
scidept
 
Test Driven Development with JavaFX
Test Driven Development with JavaFX
Hendrik Ebbers
 
Testing Legacy Rails Apps
Testing Legacy Rails Apps
Rabble .
 
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Julian Robichaux
 
How to setup unit testing in Android Studio
How to setup unit testing in Android Studio
tobiaspreuss
 
Java 9 New Features
Java 9 New Features
Ali BAKAN
 
Introduction maven3 and gwt2.5 rc2 - Lesson 01
Introduction maven3 and gwt2.5 rc2 - Lesson 01
rhemsolutions
 
Efficient JavaScript Unit Testing, JavaOne China 2013
Efficient JavaScript Unit Testing, JavaOne China 2013
Hazem Saleh
 
[AnDevCon 2016] Mutation Testing for Android
[AnDevCon 2016] Mutation Testing for Android
Hazem Saleh
 
Load Testing with k6 framework
Load Testing with k6 framework
Svetlin Nakov
 
Unit Test Android Without Going Bald
Unit Test Android Without Going Bald
David Carver
 
Managed Beans: When, Why and How
Managed Beans: When, Why and How
Russell Maher
 
Architecting your GWT applications with GWT-Platform - Lesson 02
Architecting your GWT applications with GWT-Platform - Lesson 02
rhemsolutions
 
Testing Your Application On Google App Engine
Testing Your Application On Google App Engine
IndicThreads
 
PHP Unit Testing in Yii
PHP Unit Testing in Yii
IlPeach
 
Devoxx17 - Préparez-vous à la modularité selon Java 9
Devoxx17 - Préparez-vous à la modularité selon Java 9
Alexis Hassler
 
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
chrisb206 chrisb206
 
Супер быстрая автоматизация тестирования на iOS
Супер быстрая автоматизация тестирования на iOS
SQALab
 
Working Effectively With Legacy Code
Working Effectively With Legacy Code
scidept
 

Similar to Scala, Functional Programming and Team Productivity (20)

Javaone - Gradle: Harder, Better, Stronger, Faster
Javaone - Gradle: Harder, Better, Stronger, Faster
Andres Almiray
 
Real-World DevOps — 20 Practical Developers Tips for Tightening Your Operatio...
Real-World DevOps — 20 Practical Developers Tips for Tightening Your Operatio...
VictorSzoltysek
 
Testing your application on Google App Engine
Testing your application on Google App Engine
Inphina Technologies
 
Intro to DevOps
Intro to DevOps
Ernest Mueller
 
React Native
React Native
Craig Jolicoeur
 
Testing Vue Apps with Cypress.io (STLJS Meetup April 2018)
Testing Vue Apps with Cypress.io (STLJS Meetup April 2018)
Christian Catalan
 
Spring boot introduction
Spring boot introduction
Rasheed Waraich
 
Rajiv Profile
Rajiv Profile
Rajiv Joseph
 
Real world Webapp
Real world Webapp
Things Lab
 
Anatomy of a Build Pipeline
Anatomy of a Build Pipeline
Samuel Brown
 
Microsoft SQL Server Testing Frameworks
Microsoft SQL Server Testing Frameworks
Mark Ginnebaugh
 
DevOps in Practice: When does "Practice" Become "Doing"?
DevOps in Practice: When does "Practice" Become "Doing"?
Michael Elder
 
Spring Native and Spring AOT
Spring Native and Spring AOT
VMware Tanzu
 
Scala, docker and testing, oh my! mario camou
Scala, docker and testing, oh my! mario camou
J On The Beach
 
Pyramid deployment
Pyramid deployment
Carlos de la Guardia
 
Make Your Build Great Again (DroidConSF 2017)
Make Your Build Great Again (DroidConSF 2017)
Jared Burrows
 
A Fabric/Puppet Build/Deploy System
A Fabric/Puppet Build/Deploy System
adrian_nye
 
Building JBoss AS 7 for Fedora
Building JBoss AS 7 for Fedora
wolfc71
 
Minimum Viable Docker: our journey towards orchestration
Minimum Viable Docker: our journey towards orchestration
Outlyer
 
The "Holy Grail" of Dev/Ops
The "Holy Grail" of Dev/Ops
Erik Osterman
 
Javaone - Gradle: Harder, Better, Stronger, Faster
Javaone - Gradle: Harder, Better, Stronger, Faster
Andres Almiray
 
Real-World DevOps — 20 Practical Developers Tips for Tightening Your Operatio...
Real-World DevOps — 20 Practical Developers Tips for Tightening Your Operatio...
VictorSzoltysek
 
Testing your application on Google App Engine
Testing your application on Google App Engine
Inphina Technologies
 
Testing Vue Apps with Cypress.io (STLJS Meetup April 2018)
Testing Vue Apps with Cypress.io (STLJS Meetup April 2018)
Christian Catalan
 
Spring boot introduction
Spring boot introduction
Rasheed Waraich
 
Real world Webapp
Real world Webapp
Things Lab
 
Anatomy of a Build Pipeline
Anatomy of a Build Pipeline
Samuel Brown
 
Microsoft SQL Server Testing Frameworks
Microsoft SQL Server Testing Frameworks
Mark Ginnebaugh
 
DevOps in Practice: When does "Practice" Become "Doing"?
DevOps in Practice: When does "Practice" Become "Doing"?
Michael Elder
 
Spring Native and Spring AOT
Spring Native and Spring AOT
VMware Tanzu
 
Scala, docker and testing, oh my! mario camou
Scala, docker and testing, oh my! mario camou
J On The Beach
 
Make Your Build Great Again (DroidConSF 2017)
Make Your Build Great Again (DroidConSF 2017)
Jared Burrows
 
A Fabric/Puppet Build/Deploy System
A Fabric/Puppet Build/Deploy System
adrian_nye
 
Building JBoss AS 7 for Fedora
Building JBoss AS 7 for Fedora
wolfc71
 
Minimum Viable Docker: our journey towards orchestration
Minimum Viable Docker: our journey towards orchestration
Outlyer
 
The "Holy Grail" of Dev/Ops
The "Holy Grail" of Dev/Ops
Erik Osterman
 
Ad

Recently uploaded (20)

IObit Driver Booster Pro 12 Crack Latest Version Download
IObit Driver Booster Pro 12 Crack Latest Version Download
pcprocore
 
Key Challenges in Troubleshooting Customer On-Premise Applications
Key Challenges in Troubleshooting Customer On-Premise Applications
Tier1 app
 
Advance Doctor Appointment Booking App With Online Payment
Advance Doctor Appointment Booking App With Online Payment
AxisTechnolabs
 
The Anti-Masterclass Live - Peak of Data & AI 2025
The Anti-Masterclass Live - Peak of Data & AI 2025
Safe Software
 
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
arabelatso
 
Best MLM Compensation Plans for Network Marketing Success in 2025
Best MLM Compensation Plans for Network Marketing Success in 2025
LETSCMS Pvt. Ltd.
 
Y - Recursion The Hard Way GopherCon EU 2025
Y - Recursion The Hard Way GopherCon EU 2025
Eleanor McHugh
 
ElectraSuite_Prsentation(online voting system).pptx
ElectraSuite_Prsentation(online voting system).pptx
mrsinankhan01
 
Complete WordPress Programming Guidance Book
Complete WordPress Programming Guidance Book
Shabista Imam
 
Simplify Task, Team, and Project Management with Orangescrum Work
Simplify Task, Team, and Project Management with Orangescrum Work
Orangescrum
 
Foundations of Marketo Engage - Programs, Campaigns & Beyond - June 2025
Foundations of Marketo Engage - Programs, Campaigns & Beyond - June 2025
BradBedford3
 
On-Device AI: Is It Time to Go All-In, or Do We Still Need the Cloud?
On-Device AI: Is It Time to Go All-In, or Do We Still Need the Cloud?
Hassan Abid
 
Introduction to Agile Frameworks for Product Managers.pdf
Introduction to Agile Frameworks for Product Managers.pdf
Ali Vahed
 
Which Hiring Management Tools Offer the Best ROI?
Which Hiring Management Tools Offer the Best ROI?
HireME
 
Folding Cheat Sheet # 9 - List Unfolding 𝑢𝑛𝑓𝑜𝑙𝑑 as the Computational Dual of ...
Folding Cheat Sheet # 9 - List Unfolding 𝑢𝑛𝑓𝑜𝑙𝑑 as the Computational Dual of ...
Philip Schwarz
 
Zoneranker’s Digital marketing solutions
Zoneranker’s Digital marketing solutions
reenashriee
 
OpenChain Webinar - AboutCode - Practical Compliance in One Stack – Licensing...
OpenChain Webinar - AboutCode - Practical Compliance in One Stack – Licensing...
Shane Coughlan
 
arctitecture application system design os dsa
arctitecture application system design os dsa
za241967
 
Digital Transformation: Automating the Placement of Medical Interns
Digital Transformation: Automating the Placement of Medical Interns
Safe Software
 
Best Practice for LLM Serving in the Cloud
Best Practice for LLM Serving in the Cloud
Alluxio, Inc.
 
IObit Driver Booster Pro 12 Crack Latest Version Download
IObit Driver Booster Pro 12 Crack Latest Version Download
pcprocore
 
Key Challenges in Troubleshooting Customer On-Premise Applications
Key Challenges in Troubleshooting Customer On-Premise Applications
Tier1 app
 
Advance Doctor Appointment Booking App With Online Payment
Advance Doctor Appointment Booking App With Online Payment
AxisTechnolabs
 
The Anti-Masterclass Live - Peak of Data & AI 2025
The Anti-Masterclass Live - Peak of Data & AI 2025
Safe Software
 
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
arabelatso
 
Best MLM Compensation Plans for Network Marketing Success in 2025
Best MLM Compensation Plans for Network Marketing Success in 2025
LETSCMS Pvt. Ltd.
 
Y - Recursion The Hard Way GopherCon EU 2025
Y - Recursion The Hard Way GopherCon EU 2025
Eleanor McHugh
 
ElectraSuite_Prsentation(online voting system).pptx
ElectraSuite_Prsentation(online voting system).pptx
mrsinankhan01
 
Complete WordPress Programming Guidance Book
Complete WordPress Programming Guidance Book
Shabista Imam
 
Simplify Task, Team, and Project Management with Orangescrum Work
Simplify Task, Team, and Project Management with Orangescrum Work
Orangescrum
 
Foundations of Marketo Engage - Programs, Campaigns & Beyond - June 2025
Foundations of Marketo Engage - Programs, Campaigns & Beyond - June 2025
BradBedford3
 
On-Device AI: Is It Time to Go All-In, or Do We Still Need the Cloud?
On-Device AI: Is It Time to Go All-In, or Do We Still Need the Cloud?
Hassan Abid
 
Introduction to Agile Frameworks for Product Managers.pdf
Introduction to Agile Frameworks for Product Managers.pdf
Ali Vahed
 
Which Hiring Management Tools Offer the Best ROI?
Which Hiring Management Tools Offer the Best ROI?
HireME
 
Folding Cheat Sheet # 9 - List Unfolding 𝑢𝑛𝑓𝑜𝑙𝑑 as the Computational Dual of ...
Folding Cheat Sheet # 9 - List Unfolding 𝑢𝑛𝑓𝑜𝑙𝑑 as the Computational Dual of ...
Philip Schwarz
 
Zoneranker’s Digital marketing solutions
Zoneranker’s Digital marketing solutions
reenashriee
 
OpenChain Webinar - AboutCode - Practical Compliance in One Stack – Licensing...
OpenChain Webinar - AboutCode - Practical Compliance in One Stack – Licensing...
Shane Coughlan
 
arctitecture application system design os dsa
arctitecture application system design os dsa
za241967
 
Digital Transformation: Automating the Placement of Medical Interns
Digital Transformation: Automating the Placement of Medical Interns
Safe Software
 
Best Practice for LLM Serving in the Cloud
Best Practice for LLM Serving in the Cloud
Alluxio, Inc.
 
Ad

Scala, Functional Programming and Team Productivity

  • 2. INTRO WHO WE ARE ▸ Pavel and Kai ▸ Septimal Mind, an Irish consultancy ▸ Engineer’s productivity is our primary concern ▸ Love Scala and pure FP ▸ Scala contributors
  • 3. INTRO WHAT WE DO ▸ We identify productivity issues in SDLC pipeline ▸ We build tools to address these issues ▸ How do we decide to write a new tool? ▸ Prototype should take one engineer at most two weeks
  • 4. CASE STUDY CASE STUDY: STARTING POINT (JAN/2018) ▸ Millions of users, +100K each month ▸ About 30 engineers ▸ Back-end: About 10 microservices, multirepo ▸ Front-end: mobile apps, web portal ▸ Scala as Java+ (akka-http, guice), C#, Go, Typescript
  • 5. CASE STUDY CASE STUDY: OUTCOME (JUN/2019) Development costs cut by 50% (management estimation)
  • 6. CASE STUDY WHAT WAS WRONG? Late problem detection
 Actual integration postponed to production
  • 7. INTRO WHAT WAS WRONG ▸ A lot of issues discovered in production ▸ Bugs ▸ Component incompatibilities ▸ Frontend incompatibilities ▸ Not enough insights to debug after failure ▸ Hard to just observe the product: 13 repositories ▸ Hard to get people on board
  • 8. ISSUES WHAT WAS WRONG? No Real Continuous Integration
  • 9. CASE STUDY CASE STUDY: WHAT WE DID The problems mentioned are fundamental... ... but we made things better... ...for this particular company
  • 10. CASE STUDY CASE STUDY: WHAT WE DID ▸ Formal interfaces: own IDL/DML/RPC compiler ▸ Better insights & metrics: own effort-free structured logging ▸ Convenient monorepo, better GIT flow ▸ Code quality: pure FP and Bifunctor Tagless Final ▸ Asynchronous stacktraces for ZIO ▸ Fast and reliable tests (including integration ones) ▸ "Flexible Monolith", multi-tenant applications ▸ Proper Continuous Integration ▸ Simplified onboarding
  • 11. CASE STUDY CASE STUDY: WHAT WE DID Issue Solution Late problem detection Early Integration
 (IDL, Cheap Simulations, Dual tests, Bifunctor IO, Pure FP, TF) Complicated onboarding Better Observability
 (Monorepo, Integration Checks, Dual Tests) Lack of insights Effortless insights
 (Structural Logging, Async Stacktraces) Code sharing Observability, No Local Publishing
 (Monorepo, Unified Stack, Unified Framework)
  • 12. ISSUES CASE STUDY: WHAT WE DID Let's focus on Tests and Microservices
  • 13. ISSUES WHAT WAS WRONG WITH TESTS ▸ Speed ▸ 600 tests ▸ 20 minutes total ▸ 17 for component startup and shutdown ▸ Interference ▸ Can’t run tests in parallel ▸ Slow External Dependencies ▸ Hard to wire Dummies (Guice)
  • 14. ISSUES WHAT WAS WRONG WITH MICROSERVICES ▸ Hard to share & reuse the code ▸ One shared Dev Env, hard to replicate locally ▸ Up to 70% of developer's time spent for retries and startups ▸ Automated Deployments & Orchestration ▸ Hard ▸ Fast, correct startup & shutdown are important... ▸ ...but hard to implement manually (order, variability)
  • 15. GOALS GOALS ▸ Improve development workflows ▸ Improve deployment workflows ▸ Continuously Integrate microservice fleet ▸ Improve team collaboration ▸ Simplify onboarding
  • 19. GOALS GOALS ▸ Test Business Logic without external dependencies ▸ Test Business Logic with real external dependencies too ▸ Correctly share (memoize) heavy resources between tests ▸ Let a new developer checkout & test immediately ▸ Let front-end engineers run isolated dev envs quickly & easily
  • 21. DISTAGE FRAMEWORK AUTOMATED APPLICATION COMPOSITION: THE MODEL object ServiceDemo { trait Repository[F[_, _]] class DummyRepository[F[_, _]] extends Repository[F] class ProdRepository[F[_, _]] extends Repository[F] class Service[F[_, _]](c: Repository[F]) extends Repository[F] class App[F[_, _]](s: Service[F]) { def run: F[Throwable, Unit] = ??? } }
  • 22. DISTAGE FRAMEWORK AUTOMATED APPLICATION COMPOSITION: DEFINITIONS def definition[F[_, _]: TagKK] = new ModuleDef { make[App[F]] make[Service[F]] make[Repository[F]].tagged(Repo.Dummy).from[DummyRepository[F]] make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]] }
  • 23. DISTAGE FRAMEWORK AUTOMATED APPLICATION COMPOSITION: STARTING THE APP Injector(Activation(Repo -> Prod)) .produceRunF(definition[zio.IO]) { app: App[zio.IO] => app.run }
  • 24. DISTAGE FRAMEWORK AUTOMATED APPLICATION COMPOSITION: THE IDEA distage app
 =
 set of formulas
 Product := Recipe(Materials, ...)
 +
 set of "root" products
 Set(Roots, ...)
 +
 configuration rules
 Activation
  • 25. DISTAGE FRAMEWORK AUTOMATED APPLICATION COMPOSITION: THE DIFFERENCE ▸ Like Guice and other DIs, distage ▸ turns application wiring code into a set of declarations ▸ automatically orders wiring actions
  • 26. DISTAGE FRAMEWORK AUTOMATED APPLICATION COMPOSITION: THE DIFFERENCE But not just that
  • 28. DISTAGE FRAMEWORK AUTOMATIC CONFIGURATIONS Injector(Activation(Repo -> Repo.Prod)) make[Repository[F]].tagged(Repo.Dummy).from[DummyRepository[F]] make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]]
  • 29. DISTAGE FRAMEWORK AUTOMATIC CONFIGURATIONS Injector(Activation(Repo -> Repo.Prod)) make[Repository[F]].tagged(Repo.Dummy).from[DummyRepository[F]] make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]]
  • 30. DISTAGE FRAMEWORK RESOURCES trait DIResource[F[_], Resource] { def acquire: F[Resource] def release(resource: Resource): F[Unit] } ▸ Functional description of lifecycle ▸ Initialisation without mutable state
  • 31. DISTAGE FRAMEWORK RESOURCES // library ... class DbDriver[F[_]] { def shutdown: F[Unit] } def connectToDb[F[_]: Sync]: DbDriver[F] // … class ProdRepository[F[_]](db: DbDriver[F]) extends Repository // definition ... make[Repository[F]].tagged(Repo.Prod).from[ProdRepository[F]] make[DbDriver[F]].fromResource(DIResource.make(connectToDb)(_.shutdown)) // ... ▸ Graceful shutdown is always guaranteed, even in case of an exception ▸ Docker Containers may be expressed as resources ▸ Embedded replacement for docker-compose
  • 32. DISTAGE FRAMEWORK INTEGRATION CHECKS ▸ Check if an external service is available ▸ Tests will be skipped if checks fail ▸ The app will not start if checks fail ▸ Integration checks run before all initialisation
  • 33. DISTAGE FRAMEWORK INTEGRATION CHECKS class DbCheck extends IntegrationCheck { def resourcesAvailable(): ResourceCheck = { if (checkPort()) ResourceCheck.Success() else ResourceCheck.ResourceUnavailable("Can't connect to DB", None) } private def checkPort(): Boolean = ??? } ▸ Check if an external service is available ▸ Tests will be skipped if checks fail ▸ The app will not start if checks fail ▸ Integration checks run before all initialisation
  • 34. DISTAGE FRAMEWORK DUAL TEST TACTIC ▸ Helps draft business logic quickly ▸ Enforces SOLID design ▸ Does not prevent integration tests ▸ Speeds up onboarding
  • 35. DISTAGE FRAMEWORK DUAL TEST TACTIC: CODE abstract class ServiceTest extends DistageBIOEnvSpecScalatest[ZIO] { "our service" should { "do something" in { service: Service[zio.IO] => for { // ... } yield () } } } trait DummyEnv extends DistageBIOEnvSpecScalatest[ZIO] { override def config: TestConfig = super.config.copy( activation = Activation(Repo -> Dummy)) } trait ProdEnv extends DistageBIOEnvSpecScalatest[ZIO] { override def config: TestConfig = super.config.copy( activation = Activation(Repo -> Prod)) } final class ServiceProdTest extends ServiceTest with ProdEnv final class ServiceDummyTest extends ServiceTest with DummyEnv
  • 36. DISTAGE FRAMEWORK MEMOIZATION abstract class DistageTestExample extends DistageBIOEnvSpecScalatest[ZIO] { override def config: TestConfig = { super.config.copy(memoizationRoots = Set(DIKey.get[DbDriver[zio.IO]])) } "our service" should { "do something" in { repository: Repository[zio.IO] => //... } "and do something else" in { repository: Repository[zio.IO] => //... } } }
  • 37. DISTAGE FRAMEWORK MEMOIZATION ▸ DbDriver will be shared across all the tests ▸ Without any singletons ▸ With graceful shutdown ▸ With separate contexts for different configurations
  • 38. DISTAGE FRAMEWORK AUTOMATED APPLICATION COMPOSITION: THE DIFFERENCE ▸ verifies correctness ahead of time ▸ supports resources and lifecycle ▸ provides a way to define configurable apps ▸ can perform integration checks ahead of time ▸ can perform graceful shutdown automatically ▸ can share components between multiple tests & entrypoints DISTAGE:
  • 39. ROLES AS MEANS OF CONTINUOUS INTEGRATION Yes, Integration
  • 40. DISTAGE FRAMEWORK ROLES class UsersRole extends RoleService[zio.Task] { override def start(params: RawEntrypointParams, args: Vector[String]): DIResource[zio.Task, Unit] = DIResource.make(acquire = { // initialisation })(release = { _ => // shutdown }) } object UsersRole extends RoleDescriptor { override final val id = "users" } # java -jar myapp.jar -u repo:prod -u transport:prod :users :accounts # java -jar myapp.jar -u repo:dummy -u transport:vm :users :accounts
  • 41. DISTAGE FRAMEWORK ROLES ▸ Multiple "microservices" per process ▸ More flexibility for deployments ▸ Simulations
  • 42. DISTAGE FRAMEWORK ROLES ▸ Dev environment simulation in one process ▸ Even with in-memory mocks! ▸ Not a replacement for the dev env, but nice addition. ▸ Imperfect simulations are great anyway! ▸ Model imperfectness can be granularly adjusted
  • 43. REAL CI CONTINUOUS INTEGRATION ▸ A Microservice Fleet is a Distributed Application ▸ And that application is The Product ▸ Microservices are just components of our Product ▸ We should integrate them continuously too! ▸ But it's hard to start and test a distributed application
  • 44. REAL CI DISTRIBUTED APPLICATION SIMULATIONS ▸ Several "microservices" (roles) in one process ▸ Dummies for every Integration Point ▸ Easy configuration ▸ Cheap product models for Continuous Integration ▸ There is no need to fail in production ➡
  • 45. DISTAGE FRAMEWORK ROLES AND TEAMS ▸ Multi-tenant applications do not require a Monorepo ▸ It's possible to have a repository per role ▸ Each role repository may define individual role launcher ▸ And there may be one or more launcher repositories ▸ Drawback: unified framework is required