couchapps: requiem for accidental complexity
DESCRIPTION
Talk i gave at Nosqlday with Giordano Scalzo on March 25th 2011. It's about how CouchDB can replace a full serverside mvc stack making development of simple web apps a piece of cake Also http://federico.galassi.net/ http://www.nosqlday.it/ http://couchdb.apache.org/ Follow me on Twitter! https://twitter.com/federicogalassiTRANSCRIPT
![Page 1: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/1.jpg)
CouchApps: Requiem for Accidental Complexity
Federico Galassi Giordano Scalzo
![Page 2: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/2.jpg)
We have a problem...
![Page 3: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/3.jpg)
Writing software is really hard...
![Page 4: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/4.jpg)
A little bit of history
![Page 5: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/5.jpg)
It wasn’t easy
![Page 6: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/6.jpg)
A little bit better
![Page 7: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/7.jpg)
Something happened
![Page 8: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/8.jpg)
A different way of programming
![Page 9: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/9.jpg)
DataBusiness Logic + Presentation
Two tiers architecture
![Page 10: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/10.jpg)
DataBusiness LogicPresentation
Three tiers architecture
![Page 11: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/11.jpg)
Tim Berners Lee invented the world wide web
![Page 12: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/12.jpg)
ModelView+
Thin client
Controller
Three tiers internet style
![Page 13: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/13.jpg)
Evolution ofMVC Web App
![Page 14: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/14.jpg)
Browser is a thin client
![Page 15: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/15.jpg)
Talking to asmart server
![Page 16: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/16.jpg)
It all starts withan HTTP request
GET / HTTP/1.1Host: example.org
![Page 17: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/17.jpg)
It hits theController
![Page 18: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/18.jpg)
Web server parses itController
![Page 19: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/19.jpg)
Controller
Dispatch tofront controller
![Page 20: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/20.jpg)
Controller
Routing
![Page 21: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/21.jpg)
Controller
Custom action
![Page 22: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/22.jpg)
Gets datafrom Model
![Page 23: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/23.jpg)
Query onmodel objects
Model
![Page 24: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/24.jpg)
ORM fits into SQLModel
![Page 25: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/25.jpg)
Hits a RDBMSModel
![Page 26: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/26.jpg)
Populates aView
![Page 27: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/27.jpg)
Template engineView
![Page 28: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/28.jpg)
HTML back tothe server
View
![Page 29: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/29.jpg)
HTTP/1.1 200 OK
HTML back tothe client
![Page 30: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/30.jpg)
Model
View
Controller
That’s MVC
![Page 31: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/31.jpg)
A little bit old school
![Page 32: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/32.jpg)
We love AJAX speed
![Page 33: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/33.jpg)
Model
View
Just need an API
Json View
Api ActionController
![Page 34: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/34.jpg)
And somejavascript on client
Model
View Json View
Api ActionController
Javascript View
![Page 35: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/35.jpg)
Niceone ring to rule ‘em all
![Page 36: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/36.jpg)
Nocontraindications ?
![Page 37: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/37.jpg)
Accidentalcomplexity
![Page 38: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/38.jpg)
Every changetouches the server
![Page 39: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/39.jpg)
Hard to scale
We mustadd another
serveeeeerrrr
![Page 40: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/40.jpg)
Last technology cycleVisib
ility
maturity
technologytrigger
peak ofinflated
expectation
disillusionment
productivity
obsolescence
MVCWE WERE HERE
![Page 41: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/41.jpg)
Last technology cycleVisib
ility
maturity
technologytrigger
peak ofinflated
expectation
disillusionment
productivity
obsolescence
NOW HERE
![Page 42: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/42.jpg)
Last technology cycleVisib
ility
maturity
technologytrigger
peak ofinflated
expectation
disillusionment
productivity
obsolescence
IF YOU’REAT THIS CONFYOU MAY BE
ALREADY HERE
![Page 43: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/43.jpg)
Visib
ility
maturity
?
Next technology to save us?
![Page 44: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/44.jpg)
Visib
ility
maturity
It’s a cyclebut we know one thing ...
![Page 45: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/45.jpg)
Specializationis
Good
![Page 46: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/46.jpg)
![Page 47: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/47.jpg)
![Page 48: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/48.jpg)
Very opinionateddocument DB
![Page 49: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/49.jpg)
Very good forsome problems
![Page 50: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/50.jpg)
A document DB{ "company": "CleanCode", "members": [ { "name": "Gabriele Lana", "role": "software craftsman"}, { "name": "Federico Galassi", "role": "software craftsman"}, { "name": "Giordano Scalzo", "role": "software craftsman"} ]}
![Page 51: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/51.jpg)
Self contained data
NO JOINS
![Page 52: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/52.jpg)
Schema-less data
EVOLVE YOUR DATA
![Page 53: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/53.jpg)
{
"id": 1,
"day": 20100123,
"checkout": 100
}
{
"id": 2,
"day": 20100123,
"checkout": 42
}
{
"id": 3,
"day": 20100123,
"checkout": 215
}
{
"id": 4,
"day": 20100123,
"checkout": 73
}
100 42 215 73
Reduce: sum(checkouts)
142 288
430
IncrementalMap/Reduce
Map
Reduce
Re-reduce
![Page 54: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/54.jpg)
Multi-VersionConcurrency Control
![Page 55: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/55.jpg)
Crash-onlyarchitecture
lucky by design
![Page 56: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/56.jpg)
A distributed DB
![Page 57: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/57.jpg)
Eventualconsistency
![Page 58: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/58.jpg)
Incremental replication
![Page 59: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/59.jpg)
Automatic conflict resolution
![Page 60: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/60.jpg)
Built of the Web“Django may be built for the Web, but CouchDB is built of the Web. I’ve never seen software that so completely embraces the philosophies behind HTTP.”
Jacob Kaplan-MossCo-creator of Django
![Page 61: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/61.jpg)
Restful APIGET / Returns MOTD
GET /_all_dbs List of databases
POST /_restart Restart the server
GET /_log Tail of the server’s log
GET /_config Entire server config
GET /_config/<section>/<key> Single config value
PUT /_config/<section>/<key> Set a single config value
GET /<db> Database info
PUT /<db> Create new database
DELETE /<db> Delete database
GET /<db>/<doc> Latest revision of the document
PUT /<db>/<doc> Insert a new revision of the document
... and everything else
![Page 62: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/62.jpg)
Javascript toprogram
// MAPfunction(doc) { if(doc.date && doc.title) { emit(doc.date, doc.title); }}
![Page 63: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/63.jpg)
JSON toexchange data
{ "_id":"hello-‐world", "_rev":"43FBA4E7AB",
"title":"Hello World", "body":"Well hello and welcome to my new blog...", "date":"2009/01/15 15:52:20"}
![Page 64: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/64.jpg)
Applicationsare
documents
![Page 65: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/65.jpg)
Replicationas
deploy
![Page 66: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/66.jpg)
A modern web application server
![Page 67: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/67.jpg)
CouchApps arejavascript and html5applications served
directly from CouchDB
![Page 68: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/68.jpg)
Model
View Json View
Api ActionController
Javascript View
Problem
![Page 69: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/69.jpg)
Javascript View
Simple Solution
HTTP
![Page 70: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/70.jpg)
Experiment:5 minutes comet chat
![Page 71: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/71.jpg)
The couchapp tool
![Page 72: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/72.jpg)
Generate the app
![Page 73: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/73.jpg)
Configure the app
![Page 74: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/74.jpg)
Deploy the app
![Page 75: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/75.jpg)
That’s it
![Page 76: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/76.jpg)
That’s it
![Page 77: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/77.jpg)
User can post a message
Add form elements
![Page 78: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/78.jpg)
On click POST message to couch
User can post a message
![Page 79: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/79.jpg)
User can post a message
Yes!
![Page 80: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/80.jpg)
User gets a stream of messages
Add messages container
![Page 81: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/81.jpg)
User gets a stream of messages
![Page 82: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/82.jpg)
User gets a stream of messages
Yes!
![Page 83: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/83.jpg)
Validation?
![Page 84: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/84.jpg)
Authentication?
![Page 85: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/85.jpg)
Create a user
Authentication?
![Page 86: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/86.jpg)
Add Form Elements
Authentication?
![Page 87: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/87.jpg)
HTTP Basic Auth
Authentication?
![Page 88: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/88.jpg)
If it goes wrong
Authentication?
![Page 89: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/89.jpg)
Check sender is the authenticated user
Authentication?
![Page 90: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/90.jpg)
{ sender: “whitehouse” } // spoofing
Authentication?
![Page 91: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/91.jpg)
Yes!
Authentication?
![Page 92: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/92.jpg)
BASIC HTTP ?????
No SSLYes cookie auth via _session api
![Page 93: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/93.jpg)
UGLY URLS ?????
Rewrites and Virtual hosts
![Page 94: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/94.jpg)
Easy eh?
![Page 95: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/95.jpg)
But it’s not that ring
![Page 96: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/96.jpg)
Very good forCRUD/small/simple
web
![Page 97: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/97.jpg)
![Page 98: CouchApps: Requiem for Accidental Complexity](https://reader033.vdocuments.net/reader033/viewer/2022061218/54b790524a79591d4a8b457c/html5/thumbnails/98.jpg)
[email protected] [email protected]/giordanoscalzotwitter.com/federicogalassi
slideshare.net/fgalassi slideshare.net/giordano