SlideShare a Scribd company logo
1 of 99
Download to read offline
Responsible DI
(Ditch the frameworks!)
@KenScambler
MYOB
Spring / Guice / Dagger 2
Problems with DI frameworks
• Cognitive overheard, confusing semantics
• Smear application-level responsibility everywhere
• Makes it too easy to not think about responsibilities
• Makes it harder to reason about code in isolation
• Throws tech at a problem that shouldn’t exist
What problems do DI frameworks solve
• “Factories aren’t fun”
• “Think of Guice’s @Inject
as the new new”
Guice Dagger 2
• “App assembly can be 100KLOC”
• ”Replace FactoryFactory classes”
• “Swapping dependencies for
testing”
Spring
• “Initialisation ordering”
ApplicationContext,
BeanFactory, container,
beans, configuration
metadata,
BeanDefinitionReader,
autowiring
Spring Guice
@Inject, module, AbstractModule,
injector, scopes, providers, linked
bindings, instance bindings, provider
bindings, constructor bindings,
untargetted bindings, built-in bindings,
scopes, injection points
Dagger 2
module, provider, @Inject,
@Provides, bindings,
component, Lazy, injector,
builder, code gen, qualifier,
component provision methods,
@Reusable scope
Actual problem
Need to pass arguments to things
Actual solution
Pass arguments to things
More constructively:
Actual problem
• Of the arguments we need to pass, some are selected once for the application
and never changed. It would be bad to select them over and over again
Actual solution
• Only one place should know that it is in an ”application”
• Wire up the things that never change here
• Use good software engineering to reduce the number of things
1.
Dependencies
from scratch
Case study – Video Rental API
Video Search
Controller
Payment
Controller
Video
Searcher
Payments
Payments
Gateway
Rental
Controller
Rentals
Video Repo
Video DB
Analytics
Logging
3rd Party
What if there were no objects?
handleVideoSearch
Request
handlePayment
Request
findByName
findSimilar
charge
transferFrom
Account
handleRental
Request
rentVideo
runVideoQuery
record
Debug,
warn,
error
public class Rentals {
public static
Receipt rentVideo(Video v, VideoStore store, Customer c) {
store.decrementStock(vid);
Payments.charge(c.getCreditCard(), v.getPrice());
List<Movie> recommendations =
VideoSearcher.findSimilar(v);
Logger.debug(LogMessages.VIDEO_RENTED);
return new Receipt(v.getId(), c.getId(), recommendations);
}
}
public class Rentals {
public static
Receipt rentVideo(Video v, VideoStore store, Customer c) {
store.decrementStock(vid);
Payments.charge(c.getCreditCard(), v.getPrice());
List<Movie> recommendations =
VideoSearcher.findSimilar(v);
Logger.debug(LogMessages.VIDEO_RENTED);
return new Receipt(v.getId(), c.getId(), recommendations);
}
}
handleVideoSearch
Request
handlePayment
Request
findByName
charge
transferFrom
Account
handleRental
Request
rentVideo
runVideoQuery(DB)
record
Debug,
warn,
error
findSimilar
I need a DB!
handleVideoSearch
Request
handlePayment
Request
charge
transferFrom
Account
handleRental
Request
rentVideo
runVideoQuery(DB)
record
Debug,
warn,
error
findByName
(DB)
findSimilar
(DB)
handlePayment
Request
charge
handleRental
Request
runVideoQuery(DB)
record
Debug,
warn,
error
findByName
(DB)
findSimilar
(DB)
handleVideoSearch
Request (DB)
rentVideo
(DB)
transferFrom
Account
handlePayment
Request
charge
transferFrom
Account
runVideoQuery(DB)
record
Debug,
warn,
error
findByName
(DB)
findSimilar
(DB)
handleVideoSearch
Request (DB)
rentVideo
(DB)
handleRental
Request (DB)
handlePayment
Request
charge
runVideoQuery(DB)
record
Debug,
warn,
error
findByName
(DB)
findSimilar
(DB)
handleVideoSearch
Request (DB)
rentVideo
(DB)
handleRental
Request (DB)
transferFrom
Account(PG)
I need a
payment
gateway!
handlePayment
Request
charge(PG)
runVideoQuery(DB)
record
Debug,
warn,
error
findByName
(DB)
findSimilar
(DB)
handleVideoSearch
Request (DB)
rentVideo
(DB)
handleRental
Request (DB)
transferFrom
Account(PG)
charge(PG)
runVideoQuery(DB)
record
Debug,
warn,
error
findByName
(DB)
findSimilar
(DB)
handleVideoSearch
Request (DB)
rentVideo
(DB, PG)
handleRental
Request (DB)
transferFrom
Account(PG)
handlePayment
Request (PG)
handleVideoSearch
Request (DB)
handlePayment
Request (PG)
findByName
(DB)
charge(PG)
transferFrom
Account(PG)
handleRental
Request (DB, PG)
rentVideo
(DB, PG)
runVideoQuery(DB)
record
Debug,
warn,
error
findSimilar
(DB)
Trickling up is very, very bad
1. Punches through abstraction layers
2. Changes ripple
3. Same arguments must be supplied many times to many places, but
for only one reason
Objects = 1
handleVideoSearch
Request
handlePayment
Request
charge
transferFrom
Account
handleRental
Request
rentVideo
record
Debug,
warn,
error
Video Repo
Video DB
findByName findSimilar
Objects = 2
handleVideoSearch
Request
handlePayment
Request
charge
transferFrom
Account
handleRental
Request
rentVideo
record
Debug,
warn,
error
Video Repo
Video DB
Video
Searcher
Objects = 4
handlePayment
Request
charge
transferFrom
Account
handleRental
Request
record
Debug,
warn,
error
Video Repo
Video DB
Video
Searcher
Rentals
Video Search
Controller
Objects = 5
handlePayment
Request
charge
transferFrom
Account
record
Debug,
warn,
error
Video Repo
Video DB
Video
Searcher
Rentals
Video Search
Controller
Rental
Controller
Objects = 7
handlePayment
Request
charge
transferFrom
Account
Video Repo
Video DB
Video
Searcher
Rentals
Video Search
Controller
Rental
Controller
Analytics
Logging
Objects = 8
handlePayment
Request
charge
Video Repo
Video DB
Video
Searcher
Rentals
Video Search
Controller
Rental
Controller
Analytics
Logging
Payments
Gateway
3rd Party
Objects = 9
handlePayment
Request
Video Repo
Video DB
Video
Searcher
Rentals
Video Search
Controller
Rental
Controller
Analytics
Logging
Payments
Gateway
3rd Party
Payments
Objects = 10
Video Repo
Video DB
Video
Searcher
Rentals
Video Search
Controller
Rental
Controller
Analytics
Logging
Payments
Gateway
3rd Party
Payments
Payment
Controller
Object creep is real!
…but isn’t that ok?
We’re writing OO software,
after all
Video
Searcher
Rentals
Logging
Payments
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
// Obvious constructor
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
store.decrementStock(vid);
p.charge(c.getCreditCard(), v.getPrice());
List<Movie> recommendations = search.findSimilar(v);
log.debug(LogMessages.VIDEO_RENTED);
return new Receipt(v.getId(), c.getId(), recommendations);
}
}
Rentals
- rentVideo
“Coathanger object”: just exists to
hang the functionality on
Rentals
- rentVideo
VideoSearcher
Payments
Logger
Rentals
- rentVideo
Payments
Logger
VideoSearcher
VideoRepo
- findSimilar
• Hiding functionality in objects isn’t free
• Inhibits composition & reuse
• Can we reduce the number of objects we
use?
2.
Bleeding
responsibilities
The place where the wiring happens
var logger = LoggingFramework.newLogger();
var analytics = MediaBubbleMonkeyAnalytics.create();
var conn = new SpecificDatabaseConnection(connString);
var videoRepo = new VideoRepo(conn);
var videoSearcher = new VideoSearcher(videoRepo);
var gateway = new PaymentsGateway(url);
var payments = new Payments(gateway);
var rentals = new Rentals(videoSearcher, payments);
var videoSearchController = new
VideoSearchController(videoSearcher);
var rentalSearchController = new
RentalSearchController(rentals);
var paymentsController = new PaymentsController(payments);
Some people say “yeah, I
can manage it myself”… but
in an Android application,
we had 3000 LOC. In a large
server-side app, it flushes
out to about 100k LOC.
Greg Kick, Dagger 2 author
(Google)
“I know I am in an application, and what it is for”
var logger = LoggingFramework.newLogger();
var analytics = MediaBubbleMonkeyAnalytics.create();
var conn = new SpecificDatabaseConnection(connString);
var videoRepo = new VideoRepo(conn);
var videoSearcher = new VideoSearcher(videoRepo);
var gateway = new PaymentsGateway(url);
var payments = new Payments(gateway);
var rentals = new Rentals(videoSearcher, payments);
var videoSearchController = new
VideoSearchController(videoSearcher);
var rentalSearchController = new
RentalSearchController(rentals);
var paymentsController = new PaymentsController(payments);
DI frameworks help reduce code in that one spot
….but:
“I know I’m in an application” is smooshed
everywhere
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
public Rentals(VideoSearcher search, Payments p, Logger log) {
this.search = search;
this.p = p;
this.log = log;
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
...
}
}
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
public Rentals(VideoSearcher search, Payments p, Logger log) {
this.search = search;
this.p = p;
this.log = log;
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
...
}
}
Who am I? What do I
exist for?
What is the problem
that makes me say
“Aha! I’ll use Rentals
to solve it”
*** MOST IMPORTANT SLIDE IN THE WHOLE TALK ***
Programmer
public class Rentals {
...
public Receipt rentVideo(Video v, VideoStore store,
Customer c) {
...
}
}
Use me if you want
to rent a video.
public class Rentals {
...
public Receipt rentVideo(Video v, VideoStore store,
Customer c) {
...
}
}
What’s that you say,
I’m in an “app”? I
have no idea what
this means
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
public Rentals(VideoSearcher search, Payments p, Logger log) {
this.search = search;
this.p = p;
this.log = log;
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
...
}
}
I don’t care in the
slightest which
VideoSearcher,
Payments or Logger
we use
@Component(“Bob”)
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
@Autowired
public Rentals(VideoSearcher search, Payments p, Logger log) {
this.search = search;
this.p = p;
this.log = log;
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
...
}
}
But…
@Component(“Bob”)
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
@Autowired
public Rentals(VideoSearcher search, Payments p, Logger log) {
this.search = search;
this.p = p;
this.log = log;
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
...
}
}
There’s only one true
Rentals. Create THE
Rentals for the whole app
to use. They can call it
“Bob”.
@Component(“Bob”)
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
@Autowired
public Rentals(VideoSearcher search, Payments p, Logger log) {
this.search = search;
this.p = p;
this.log = log;
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
...
}
}
I want THE VideoSearcher, THE
Payments, and THE Log
defined for the app.
interface
VideoSearcher
class
LocalDbSearcher
class
InternetSearcher
interface
Payments
class
CreditCardPayments
class
BankPayments
class
HashMapSearcher
@Component(“Bob”)
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
@Autowired
public Rentals(@Qualifier(“internetSearch”) VideoSearcher search,
@Qualifier(“creditPayments”) Payments p,
@Qualifier(“log4J”) Logger log) {
this.search = search;
this.p = p;
this.log = log;
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
...
}
}
I want a really really specific
VideoSearcher, Payments, and
Log that we get from a global
register somewhere.
I don’t care in the
slightest which
VideoSearcher,
Payments or Logger
we use
?????
public class Rentals {
public Receipt rentVideo(Video v, VideoStore store,
Customer c) {
store.decrementStock(vid);
p.charge(c.getCreditCard(), v.getRentalPrice());
List<Movie> recommendations = search.findSimilar(v);
log.debug(LogMessages.VIDEO_RENTED);
return new Receipt(v.getId(), c.getId(),
recommendations);
}
}
Use me if you
want to rent a
video.
THEREFORE:
1.
2.
3.
4.
Test that we can rent a video:
For some valid VideoSearcher, Payments, and Logger
1. Check the VideoStore got decremented
2. Check the Payments was charged
3. Check the logger received a LogMessages.VIDEO_RENTED message
4. Check our receipt has the expected data, including the expected
recommended videos
ALIGNS WITH OUR PURPOSE
public class RentalsTest {
VideoSearcher search = new FixedResultsSearcher(...);
Payments p = new InMemoryPayments();
InMemoryLogger log = new InMemoryLogger();
@Test
public void stockGetsDecremented() {
var rentals = new Rentals(search, p, log);
var store = new InMemoryVideoStore();
var video = new Video(“Weekend at Bernies”, Price.cents(250));
rentals.rentVideo(video, store.put(video,2), new Customer(...));
assertEquals(1, store.count(video));
}
...
}
public class Rentals {
private final StuffThatHappensFirst firstStuff;
...
@Autowired
public Rentals(@Qualifier(“decrementAndPayStuff”) StuffThatHappensFirst
firstStuff,
VideoSearcher search, Logger log) {
...
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
firstStuff.doIt(store);
List<Movie> recommendations = search.findSimilar(v);
log.debug(“Video rented!”);
return new Receipt(v.getId(), c.getId(), recommendations);
}
}
Class responsibility has bled into the app!!!
3.
How to make less things
that need wiring?
There is nothing wrong with “new”
1 + 4 * 5
1.add(4.mult(5))
new Adder().add(1,
new Multiplier().mult(4,5))
class Multiplier {
private final
Adder adder = new Adder();
public int mult(int a, int b) {
int tot = 0;
for (int i = 0; i < a; i++)
tot = adder.add(tot,b);
return tot;
}
}
class Multiplier {
private final Adder adder;
public Multiplier(Adder a) {
adder = a;
}
public int mult(int a, int b) {
...
}
}
class Multiplier {
private final
Adder adder = new Adder();
public int mult(int a, int b) {
...
}
}
Who am I? What do I
exist for?
class Multiplier {
private final
Adder adder = new Adder();
public int mult(int a, int b) {
...
}
}
The point is:
Multiply 2 ints
into a resulting
int
Tool that
helps us do
our job
class Multiplier {
private final Adder adder;
public Multiplier(Adder a) {
adder = a;
}
public int mult(int a, int b) {
...
}
}
We do not care in
the slightest how
the ints get
combined
class Multiplier {
private final Adder adder;
public Multiplier(Adder a) {
adder = a;
}
public int mult(int a, int b) {
...
}
}
I exist to …
perform an action
on ints a given
number of times?
class GstPrice {
private final Price untaxed;
private final GstPolicy policy =
new GstPolicy();
public GstPrice(Price untaxed) {
this.untaxed = untaxed;
}
... // arithmetic, rounding, display, etc
}
class GstPrice {
private final Price untaxed;
private final GstPolicy policy =
new GstPolicy();
public GstPrice(Price untaxed) {
this.untaxed = untaxed;
}
... // arithmetic, rounding, display, etc
}
I exist to provide a
price that has
provably had GST
applied
class GstPrice {
private final Price untaxed;
private final GstPolicy policy =
new GstPolicy();
public GstPrice(Price untaxed) {
this.untaxed = untaxed;
}
... // arithmetic, rounding, display, etc
}
This is a tool I
need to do the
job. GST is the
point
class GstPrice {
private final Price untaxed;
private final GstPolicy policy =
new GstPolicy();
public GstPrice(Price untaxed) {
this.untaxed = untaxed;
}
... // arithmetic, rounding, display, etc
}
I do not care in
the slightest
which untaxed
price I am dealing
with
class TaxedPrice {
private final Price untaxed;
private final TaxPolicy policy;
public TaxedPrice(Price untaxed,
TaxPolicy policy) {
this.untaxed = untaxed;
}
... // arithmetic, rounding, display, etc
}
I do not care in
the slightest
which untaxed
price or tax policy
I am dealing with
// Mostly we don’t want to vary the policy,
so...
class TaxedPriceFactory {
private final TaxPolicy policy;
// ...Obvious constructor
public
TaxedPrice newTaxedPrice(Price untaxed) {
return new TaxedPrice(untaxed, policy);
}
}
• Don’t lazily turn every field into a
dependency; it increases
complexity and object creep.
• Think hard about responsibilities.
• Use new if it supports our reason
for existing.
4.
Dependencies
ain’t free
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
@Autowired
public Rentals(VideoSearcher search, Payments p, Logger log) {
...
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
... // Uses search, p & log
}
}
public class Rentals {
private final VideoSearcher search;
private final Payments p;
private final Logger log;
private final PopcornMachine p;
@Autowired
public Rentals(VideoSearcher search, Payments p, Logger log, PopcornMachine p) {
...
}
public Receipt rentVideo(Video v, VideoStore store, Customer c) {
... // Uses search, p & log
}
public Receipt rentVideoWithPopcornDeal(Video v, VideoStore store, Customer c) { ... }
}
rentVideo
rentVideo
rentVideoWithPopcornDeal
Getters and setters
• This is how a codebase goes to
hell
• Each dependency makes reuse,
extension, reasoning & testing
harder
• Frameworks make it too easy to
pretend it’s free
5.
“Setter injection”
is malpractice
public class Rentals {
private VideoSearcher search;
private Payments p;
private Logger log;
public Rentals() {}
public void setVideoSearcher(VideoSearcher v) {...}
public void setPayments(Payments p) {...}
public void setLogger(Logger log) {...}
public Receipt rentVideo(Video v, VideoStore store,
Customer c) {... }
}
Programmer
UsageConstruction
- setVideoSearcher
- setPayments
- setLogger
- rentVideo
Totally different concerns!
Buy stuffSupply
Programmer
Usage
- rentVideointerface Rentals {
Receipt rentVideo(...)
}
• “Setter injection” is a bad idea
• Public interfaces confuses usage & creation
concerns
• Nobody ever wants all that at once
• Mutable, uncertain – what order did things
happen in?
• Frameworks make “setter injection” too easy &
practical
6.
Making
coathanger
objects
disappear
public class Payments {
private final Gateway gateway;
public Payments(Gateway gateway) {...}
public Receipt charge(Price price) {...}
}
public class Payments {
public static
Receipt charge(Price price, Gateway gateway) {
...
}
}
public class Payments {
public static
Function<Gateway, Receipt> charge(Price price) {
...
}
}
public class Payments {
public static
NeedsGateway<Receipt> charge(Price price) {
...
}
}
Required flexibility is now
built in to return type; no
coathanger object required
charge(Price.cents(250)).flatMap(
price -> doSomethingElse(price).map(
result -> result.toString()));
• “If only I had a Price, this is what I would totally
do with it"
• “Monadic style”
• Popular with functional programmers
• Maybe not so practical in Java
NeedsGateway<FinalResult> program;
FinalResult result =
program.actuallyRun(actualGateway);
Objects = 4 (just the IO points)
handleVideoSearch
Request
handlePayment
Request
charge
handleRental
Request
rentVideo
Video Repo
Video DB
findByName findSimilar
Gateway
Analytics
Logging
The problem has
vanished! There’s almost
nothing left to wire
Conclusion
• Passing arguments to things is not very hard
• Wiring together applications is not very hard
• Having a central “I am the application” place and thinking hard about
responsibilities gives you what you want
• DI frameworks are too complex, not necessary, and lead programmers
and teams toward sloppy design habits.

More Related Content

What's hot

Rise of the Machines: PHP and IoT - ZendCon 2017
Rise of the Machines: PHP and IoT - ZendCon 2017Rise of the Machines: PHP and IoT - ZendCon 2017
Rise of the Machines: PHP and IoT - ZendCon 2017Colin O'Dell
 
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014Matthias Noback
 
A reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webWallace Reis
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principlesPerl Careers
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applicationsRuslan Shevchenko
 
An Introduction to Windows PowerShell
An Introduction to Windows PowerShellAn Introduction to Windows PowerShell
An Introduction to Windows PowerShellDale Lane
 
HTTP Middlewares in PHP by Eugene Dounar
HTTP Middlewares in PHP by Eugene DounarHTTP Middlewares in PHP by Eugene Dounar
HTTP Middlewares in PHP by Eugene DounarMinsk PHP User Group
 
SPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo Omura
SPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo OmuraSPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo Omura
SPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo OmuraPreferred Networks
 
A cool, clear drink of Ruby object persistence
A cool, clear drink of  Ruby object persistenceA cool, clear drink of  Ruby object persistence
A cool, clear drink of Ruby object persistencebaccigalupi
 
Conscious Decoupling - Lone Star PHP
Conscious Decoupling - Lone Star PHPConscious Decoupling - Lone Star PHP
Conscious Decoupling - Lone Star PHPCiaranMcNulty
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersMarcin Chwedziak
 

What's hot (11)

Rise of the Machines: PHP and IoT - ZendCon 2017
Rise of the Machines: PHP and IoT - ZendCon 2017Rise of the Machines: PHP and IoT - ZendCon 2017
Rise of the Machines: PHP and IoT - ZendCon 2017
 
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
 
A reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento web
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applications
 
An Introduction to Windows PowerShell
An Introduction to Windows PowerShellAn Introduction to Windows PowerShell
An Introduction to Windows PowerShell
 
HTTP Middlewares in PHP by Eugene Dounar
HTTP Middlewares in PHP by Eugene DounarHTTP Middlewares in PHP by Eugene Dounar
HTTP Middlewares in PHP by Eugene Dounar
 
SPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo Omura
SPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo OmuraSPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo Omura
SPIFFE Meetup Tokyo #2 - Attestation Internals in SPIRE - Shingo Omura
 
A cool, clear drink of Ruby object persistence
A cool, clear drink of  Ruby object persistenceA cool, clear drink of  Ruby object persistence
A cool, clear drink of Ruby object persistence
 
Conscious Decoupling - Lone Star PHP
Conscious Decoupling - Lone Star PHPConscious Decoupling - Lone Star PHP
Conscious Decoupling - Lone Star PHP
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 Developers
 

Similar to Responsible DI: Ditch the Frameworks

Developing applications with Hyperledger Fabric SDK
Developing applications with Hyperledger Fabric SDKDeveloping applications with Hyperledger Fabric SDK
Developing applications with Hyperledger Fabric SDKHorea Porutiu
 
Acercándonos a la Programación Funcional a través de la Arquitectura Hexag...
Acercándonos a la Programación Funcional a través de la Arquitectura Hexag...Acercándonos a la Programación Funcional a través de la Arquitectura Hexag...
Acercándonos a la Programación Funcional a través de la Arquitectura Hexag...CodelyTV
 
Pyruvate, a reasonably fast, non-blocking, multithreaded WSGI server
Pyruvate, a reasonably fast, non-blocking, multithreaded WSGI serverPyruvate, a reasonably fast, non-blocking, multithreaded WSGI server
Pyruvate, a reasonably fast, non-blocking, multithreaded WSGI serverPloneFoundation
 
Dropwizard with MongoDB and Google Cloud
Dropwizard with MongoDB and Google CloudDropwizard with MongoDB and Google Cloud
Dropwizard with MongoDB and Google CloudYun Zhi Lin
 
Getting More Out of the Node.js, PHP, and Python Agents - AppSphere16
Getting More Out of the Node.js, PHP, and Python Agents - AppSphere16Getting More Out of the Node.js, PHP, and Python Agents - AppSphere16
Getting More Out of the Node.js, PHP, and Python Agents - AppSphere16AppDynamics
 
springtraning-7024840-phpapp01.pdf
springtraning-7024840-phpapp01.pdfspringtraning-7024840-phpapp01.pdf
springtraning-7024840-phpapp01.pdfBruceLee275640
 
Rapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
Rapid Prototyping Chatter with a PHP/Hack Canvas App on HerokuRapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
Rapid Prototyping Chatter with a PHP/Hack Canvas App on HerokuSalesforce Developers
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great JusticeDomenic Denicola
 
Comet from JavaOne 2008
Comet from JavaOne 2008Comet from JavaOne 2008
Comet from JavaOne 2008Joe Walker
 
Jenkins vs. AWS CodePipeline
Jenkins vs. AWS CodePipelineJenkins vs. AWS CodePipeline
Jenkins vs. AWS CodePipelineSteffen Gebert
 
Orchestrating the execution of workflows for media streaming service and even...
Orchestrating the execution of workflows for media streaming service and even...Orchestrating the execution of workflows for media streaming service and even...
Orchestrating the execution of workflows for media streaming service and even...Shuen-Huei Guan
 
Behat internals for advanced usage. Symfony Camp 2016
Behat internals for advanced usage. Symfony Camp 2016Behat internals for advanced usage. Symfony Camp 2016
Behat internals for advanced usage. Symfony Camp 2016Sergey Polischook
 
Seeding a Tree in a Gherkin
Seeding a Tree in a GherkinSeeding a Tree in a Gherkin
Seeding a Tree in a GherkinPaul Rohorzka
 
BlackHat EU 2012 - Zhenhua Liu - Breeding Sandworms: How To Fuzz Your Way Out...
BlackHat EU 2012 - Zhenhua Liu - Breeding Sandworms: How To Fuzz Your Way Out...BlackHat EU 2012 - Zhenhua Liu - Breeding Sandworms: How To Fuzz Your Way Out...
BlackHat EU 2012 - Zhenhua Liu - Breeding Sandworms: How To Fuzz Your Way Out...MindShare_kk
 
Creating Scalable JVM/Java Apps on Heroku
Creating Scalable JVM/Java Apps on HerokuCreating Scalable JVM/Java Apps on Heroku
Creating Scalable JVM/Java Apps on HerokuJoe Kutner
 
Jenkins vs. AWS CodePipeline (AWS User Group Berlin)
Jenkins vs. AWS CodePipeline (AWS User Group Berlin)Jenkins vs. AWS CodePipeline (AWS User Group Berlin)
Jenkins vs. AWS CodePipeline (AWS User Group Berlin)Steffen Gebert
 
Common primitives in Docker environments
Common primitives in Docker environmentsCommon primitives in Docker environments
Common primitives in Docker environmentsalexandru giurgiu
 
Spring in the Cloud - using Spring with Cloud Foundry
Spring in the Cloud - using Spring with Cloud FoundrySpring in the Cloud - using Spring with Cloud Foundry
Spring in the Cloud - using Spring with Cloud FoundryJoshua Long
 

Similar to Responsible DI: Ditch the Frameworks (20)

Developing applications with Hyperledger Fabric SDK
Developing applications with Hyperledger Fabric SDKDeveloping applications with Hyperledger Fabric SDK
Developing applications with Hyperledger Fabric SDK
 
Hexagonal architecture
Hexagonal architectureHexagonal architecture
Hexagonal architecture
 
Acercándonos a la Programación Funcional a través de la Arquitectura Hexag...
Acercándonos a la Programación Funcional a través de la Arquitectura Hexag...Acercándonos a la Programación Funcional a través de la Arquitectura Hexag...
Acercándonos a la Programación Funcional a través de la Arquitectura Hexag...
 
Pyruvate, a reasonably fast, non-blocking, multithreaded WSGI server
Pyruvate, a reasonably fast, non-blocking, multithreaded WSGI serverPyruvate, a reasonably fast, non-blocking, multithreaded WSGI server
Pyruvate, a reasonably fast, non-blocking, multithreaded WSGI server
 
Dropwizard with MongoDB and Google Cloud
Dropwizard with MongoDB and Google CloudDropwizard with MongoDB and Google Cloud
Dropwizard with MongoDB and Google Cloud
 
Getting More Out of the Node.js, PHP, and Python Agents - AppSphere16
Getting More Out of the Node.js, PHP, and Python Agents - AppSphere16Getting More Out of the Node.js, PHP, and Python Agents - AppSphere16
Getting More Out of the Node.js, PHP, and Python Agents - AppSphere16
 
How to debug IoT Agents
How to debug IoT AgentsHow to debug IoT Agents
How to debug IoT Agents
 
springtraning-7024840-phpapp01.pdf
springtraning-7024840-phpapp01.pdfspringtraning-7024840-phpapp01.pdf
springtraning-7024840-phpapp01.pdf
 
Rapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
Rapid Prototyping Chatter with a PHP/Hack Canvas App on HerokuRapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
Rapid Prototyping Chatter with a PHP/Hack Canvas App on Heroku
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great Justice
 
Comet from JavaOne 2008
Comet from JavaOne 2008Comet from JavaOne 2008
Comet from JavaOne 2008
 
Jenkins vs. AWS CodePipeline
Jenkins vs. AWS CodePipelineJenkins vs. AWS CodePipeline
Jenkins vs. AWS CodePipeline
 
Orchestrating the execution of workflows for media streaming service and even...
Orchestrating the execution of workflows for media streaming service and even...Orchestrating the execution of workflows for media streaming service and even...
Orchestrating the execution of workflows for media streaming service and even...
 
Behat internals for advanced usage. Symfony Camp 2016
Behat internals for advanced usage. Symfony Camp 2016Behat internals for advanced usage. Symfony Camp 2016
Behat internals for advanced usage. Symfony Camp 2016
 
Seeding a Tree in a Gherkin
Seeding a Tree in a GherkinSeeding a Tree in a Gherkin
Seeding a Tree in a Gherkin
 
BlackHat EU 2012 - Zhenhua Liu - Breeding Sandworms: How To Fuzz Your Way Out...
BlackHat EU 2012 - Zhenhua Liu - Breeding Sandworms: How To Fuzz Your Way Out...BlackHat EU 2012 - Zhenhua Liu - Breeding Sandworms: How To Fuzz Your Way Out...
BlackHat EU 2012 - Zhenhua Liu - Breeding Sandworms: How To Fuzz Your Way Out...
 
Creating Scalable JVM/Java Apps on Heroku
Creating Scalable JVM/Java Apps on HerokuCreating Scalable JVM/Java Apps on Heroku
Creating Scalable JVM/Java Apps on Heroku
 
Jenkins vs. AWS CodePipeline (AWS User Group Berlin)
Jenkins vs. AWS CodePipeline (AWS User Group Berlin)Jenkins vs. AWS CodePipeline (AWS User Group Berlin)
Jenkins vs. AWS CodePipeline (AWS User Group Berlin)
 
Common primitives in Docker environments
Common primitives in Docker environmentsCommon primitives in Docker environments
Common primitives in Docker environments
 
Spring in the Cloud - using Spring with Cloud Foundry
Spring in the Cloud - using Spring with Cloud FoundrySpring in the Cloud - using Spring with Cloud Foundry
Spring in the Cloud - using Spring with Cloud Foundry
 

More from kenbot

Grow your own tech leads
Grow your own tech leadsGrow your own tech leads
Grow your own tech leadskenbot
 
Applied category theory: the emerging science of compositionality
Applied category theory: the emerging science of compositionalityApplied category theory: the emerging science of compositionality
Applied category theory: the emerging science of compositionalitykenbot
 
FP adoption at REA
FP adoption at REAFP adoption at REA
FP adoption at REAkenbot
 
Lenses for the masses - introducing Goggles
Lenses for the masses - introducing GogglesLenses for the masses - introducing Goggles
Lenses for the masses - introducing Goggleskenbot
 
Good functional programming is good programming
Good functional programming is good programmingGood functional programming is good programming
Good functional programming is good programmingkenbot
 
Data made out of functions
Data made out of functionsData made out of functions
Data made out of functionskenbot
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mockskenbot
 
2 Years of Real World FP at REA
2 Years of Real World FP at REA2 Years of Real World FP at REA
2 Years of Real World FP at REAkenbot
 
Your data structures are made of maths!
Your data structures are made of maths!Your data structures are made of maths!
Your data structures are made of maths!kenbot
 
Category theory for beginners
Category theory for beginnersCategory theory for beginners
Category theory for beginnerskenbot
 
The disaster of mutable state
The disaster of mutable stateThe disaster of mutable state
The disaster of mutable statekenbot
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monadskenbot
 

More from kenbot (12)

Grow your own tech leads
Grow your own tech leadsGrow your own tech leads
Grow your own tech leads
 
Applied category theory: the emerging science of compositionality
Applied category theory: the emerging science of compositionalityApplied category theory: the emerging science of compositionality
Applied category theory: the emerging science of compositionality
 
FP adoption at REA
FP adoption at REAFP adoption at REA
FP adoption at REA
 
Lenses for the masses - introducing Goggles
Lenses for the masses - introducing GogglesLenses for the masses - introducing Goggles
Lenses for the masses - introducing Goggles
 
Good functional programming is good programming
Good functional programming is good programmingGood functional programming is good programming
Good functional programming is good programming
 
Data made out of functions
Data made out of functionsData made out of functions
Data made out of functions
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mocks
 
2 Years of Real World FP at REA
2 Years of Real World FP at REA2 Years of Real World FP at REA
2 Years of Real World FP at REA
 
Your data structures are made of maths!
Your data structures are made of maths!Your data structures are made of maths!
Your data structures are made of maths!
 
Category theory for beginners
Category theory for beginnersCategory theory for beginners
Category theory for beginners
 
The disaster of mutable state
The disaster of mutable stateThe disaster of mutable state
The disaster of mutable state
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monads
 

Recently uploaded

Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...Bert Jan Schrijver
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxRTS corp
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldRoberto Pérez Alcolea
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...OnePlan Solutions
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...kalichargn70th171
 
Key Steps in Agile Software Delivery Roadmap
Key Steps in Agile Software Delivery RoadmapKey Steps in Agile Software Delivery Roadmap
Key Steps in Agile Software Delivery RoadmapIshara Amarasekera
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?Alexandre Beguel
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdfAndrey Devyatkin
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesVictoriaMetrics
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptxVinzoCenzo
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolsosttopstonverter
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jNeo4j
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxSasikiranMarri
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorTier1 app
 
Effort Estimation Techniques used in Software Projects
Effort Estimation Techniques used in Software ProjectsEffort Estimation Techniques used in Software Projects
Effort Estimation Techniques used in Software ProjectsDEEPRAJ PATHAK
 

Recently uploaded (20)

Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptx
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
 
Key Steps in Agile Software Delivery Roadmap
Key Steps in Agile Software Delivery RoadmapKey Steps in Agile Software Delivery Roadmap
Key Steps in Agile Software Delivery Roadmap
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 Updates
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptx
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration tools
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryError
 
Effort Estimation Techniques used in Software Projects
Effort Estimation Techniques used in Software ProjectsEffort Estimation Techniques used in Software Projects
Effort Estimation Techniques used in Software Projects
 

Responsible DI: Ditch the Frameworks