Clojure at ardoq

52
Ardoq.com @ebaxt Erik Bakstad Clojure at Ardoq Oslo Socially Functional Programmers

description

Two years ago Ardoq set out to build the documentation platform that the IT-professional wants to use. Starting a “greenfield” project, we were free to choose what we considered to be the best technology for the job, so we ended up using Clojure for all backend components. In this talk I will share our experience using Clojure to build the http://ardoq.com/ documentation platform. A few highlights - Building comprehensive REST-APIs in Clojure - Rapid feedback using REPL driven development - Building a “realtime web” backend using Clojure, WebSockets and Redis. I will also share some of the mistakes we made along the way, as well as lessons learned and tips for anyone starting a new Clojure project.

Transcript of Clojure at ardoq

Page 1: Clojure at ardoq

Ardoq.com @ebaxt

Erik Bakstad

Clojure at

Ardoq

Oslo Socially Functional Programmers

Page 2: Clojure at ardoq

Ardoq.com @ebaxt

! 6 years as consultant (finance/telecom)

! Mostly Java & JavaScript professionally

! Discovered Clojure in 2009

! Groovy, Ruby, Python, SML, Racket, Scala …

! CTO & Co-founder of Ardoq

My background

Page 3: Clojure at ardoq

Ardoq.com @ebaxt

AGENDA

! What is Ardoq?

! Why we decided to use Clojure

! Overview Clojure at Ardoq + 2 Cases

! REPL/development environment

! Experience so far / Q&A / Discussions

Page 4: Clojure at ardoq

Ardoq.com @ebaxt

What is Ardoq?

Page 5: Clojure at ardoq

Ardoq.com @ebaxt

We‘re building larger, more complex systems

! Many different “sub-systems“

! Different technologies

! Wide range of integrations

! System-of-systems problem

Page 6: Clojure at ardoq

Ardoq.com @ebaxt

To achieve conceptual understanding we create artifacts

! Documents

! System maps

! Diagrams

! Flowcharts

These artifacts are hard to maintain!

Page 7: Clojure at ardoq

Ardoq.com @ebaxt

Existing tools are either ...

Enterprise architecture software

Very Complex

Word

Not powerfull enough

Excel PowerPoint

Wikis

V isio

Page 8: Clojure at ardoq

Ardoq.com @ebaxt

Ardoq is a documentation platform that offers

! Explorable, “Living” documentation

! Automatically visualizes dependencies and hierarchies

! REST-api for data import/export

! Supports custom visualizations via plugins

Page 9: Clojure at ardoq

Ardoq.com @ebaxt

DEMO

Page 10: Clojure at ardoq

Ardoq.com @ebaxt

Why Clojure?

Page 11: Clojure at ardoq

Ardoq.com @ebaxt

Page 12: Clojure at ardoq

Ardoq.com @ebaxt

Page 13: Clojure at ardoq

Ardoq.com @ebaxt

Ship software

Quickly Fun!

C onsistently (over time)

Quality

Try out different solutions

Understand How it works!

Leverage

Page 14: Clojure at ardoq

Ardoq.com @ebaxt

JavaScript

MongoDB

Clojure

BSON

JSON

{ "firstname": "Erik", "lastname": "Bakstad", "age": 30, "hobby": ["hockey", "cycling"] }

{ "firstname": "Erik", "lastname": "Bakstad", "age": 30, "hobby": ["hockey", "cycling"] }

{ :firstname "Erik" :lastname "Bakstad" :age 30 :hobby ["hockey", "cycling"] }

EDN

Page 15: Clojure at ardoq

Ardoq.com @ebaxt

! Extensive REST-api

! “Version control” on top of MongoDB

! Real-time web backend

! 3-party integrations (recurly, jira, segment.io, +++)

! Attachment service with pluggable storage provider

Stuff we‘ve built in Clojure

Page 16: Clojure at ardoq

Ardoq.com @ebaxt

Architecture

Page 17: Clojure at ardoq

Ardoq.com @ebaxt

Backbone.js !D3.js!jQuery!Require.js! JavaScript-app!

Clojure!backend!

MongoDB!! Redis!

H T TP Websockets SNS!S3!

Segment.io!Mailchimp!Mandrill!Recurly!JIRA!Tarsnap!!

H T TP

TCP

Plugins!JavaDoc / Excel! H T TP

Page 18: Clojure at ardoq

Ardoq.com @ebaxt

api!

com.ardoq.*

utils! service!

gateway!persistence!

MongoDB!!

SNS!S3!

Segment.io!Mailchimp!Mandrill!Recurly!JIRA!!!

hAp://www.infoq.com/presentaGons/DDDIClojure$

Page 19: Clojure at ardoq

Ardoq.com @ebaxt

Libraries

! Carmine

! amazonica

! core.async

! Pantomime

! clj-http/chime/clostach

! Ring/compojure/Liberator

! http-kit/clj-wamp

! Friend/oauthentic/clj-oauth

! clj-schema/antisamy

! Monger/ragtime

Page 20: Clojure at ardoq

Ardoq.com @ebaxt

Testing/debugging

! Started out with midje

! Now using clojure.test

! ring.mock

! Lein test selectors

! Mongodb + redis

! clojure.tools.trace

! IntelliJ with Cursive

! Embedded REPL

! criterium

Page 21: Clojure at ardoq

Ardoq.com @ebaxt

Editor/IDE

! Emacs + Cider

! clojure-mode + paredit

! clojure-test-mode

! clojure-refactor (just started)

! company-cider

Page 22: Clojure at ardoq

Ardoq.com @ebaxt

Infrastructure/monitoring

! S3 (wagon)

! SNS

! Zapier

! Tarsnap

! HipChat

! AWS / on-site

! Ansible /python/bash

! Circle-CI

! Logstash + Kibana

! Pingdom

Page 23: Clojure at ardoq

Ardoq.com @ebaxt

Case 1

REST-api

Page 24: Clojure at ardoq

Ardoq.com @ebaxt

Request Response

Servlet C ontainer Servlet AP I

Ring

Application

Page 25: Clojure at ardoq

Ardoq.com @ebaxt

{:scheme(:http,((:session({}((:request3method(:get,((:query3string("q=hello"((:cookies({}((:uri("/test"((:headers(({"accept3encoding"("gzip,(deflate"}((:body(...}$

(defn%handler([request](...()$

{:status(200((:headers({"Content3Type"((((((((((((("text/plain"}((:body("Hello(World!"}$

Page 26: Clojure at ardoq

Ardoq.com @ebaxt

(defn%middleware([handler]((((()$

Page 27: Clojure at ardoq

Ardoq.com @ebaxt

(defn%middleware([handler]((((fn%[req](((...((((handler(req)(((...())$

Page 28: Clojure at ardoq

Ardoq.com @ebaxt

(defroutes(api((((GET("/"([](...)((((POST("/"([](...))(((def%handler(((((logging((session((security(app))))((((run3jetty(handler({:port(8080}))$

Page 29: Clojure at ardoq

Ardoq.com @ebaxt

(defroutes(api((((GET("/"([](...))(

?

Page 30: Clojure at ardoq

Ardoq.com @ebaxt

Page 31: Clojure at ardoq

Ardoq.com @ebaxt

Liberator

hAp://clojureIliberator.github.io/liberator/$

(defroutes(api((((GET("/"([](...))(

Decision graph

Page 32: Clojure at ardoq

Ardoq.com @ebaxt

Decision graph

hAp://clojureIliberator.github.io/liberator/assets/img/decisionIgraph.svg$

(resource((((((((((:allowed3methods([:get]((((((((((:allowed?((fn%[_]((permission/is3admin?))((((((((((:available3media3types(["application/json"]((((((((((:exists?((fn%[_]({::result(...)((((((((((:handle3ok(::result)))$

Page 33: Clojure at ardoq

Ardoq.com @ebaxt

Authentication

hAps://github.com/cemerick/friend$

! Basic Auth

! Token Auth

! Oauth (Log in with Github, Google, Live Connect)

Page 34: Clojure at ardoq

Ardoq.com @ebaxt

Friend

hAps://github.com/cemerick/friend$

Page 35: Clojure at ardoq

Ardoq.com @ebaxt

Friend

hAps://github.com/cemerick/friend$

{:workflows([(ajax3login)(((((((((((((((token3workflow(:realm("Ardoq"(:credential3fn(...)(((((((((((((((workflows/http3basic(:realm("Ardoq")(((((((((((((((github3oauth(system)(((((((((((((((live3connect3oauth(system)(((((((((((((((google3oauth(system)]((:credential3fn((partial(verify3credentials(system)((:login3uri("/login"((:unauthorized3redirect3uri("/login"((:default3landing3uri("/index.html"}$

Page 36: Clojure at ardoq

Ardoq.com @ebaxt

Middleware

! wrap-impersonate

! wrap-organization

! wrap-session-expiry

! clojure-metrics

Page 37: Clojure at ardoq

Ardoq.com @ebaxt

Case 2

Real-time web

Page 38: Clojure at ardoq

Ardoq.com @ebaxt

API-1! API-2!

Nginx-1! Nginx-2!

Browser-1! Browser-2!POST$/api/component${“name”:$“foo”}$

NoGfy$user$of$BrowserI1’s$POST$

Page 39: Clojure at ardoq

Ardoq.com @ebaxt

Why not use something like Pusher.app or firebase?

Page 40: Clojure at ardoq

Ardoq.com @ebaxt

The Web Application Messaging Protocol

hAp://wamp.ws/$

Page 41: Clojure at ardoq

Ardoq.com @ebaxt

API-1! API-2!

Nginx-1! Nginx-2!

Browser-1! Browser-2!

Websocket + Wamp

Http-kit + cl j-wamp

Autobahn.js + f lash-fal l back

?

Page 42: Clojure at ardoq

Ardoq.com @ebaxt

API-1! API-2!

Nginx-1! Nginx-2!

Browser-1! Browser-2!

Redis PubSub + core.async Redis!

Page 43: Clojure at ardoq

Ardoq.com @ebaxt

Publish!Event! Redis!

Carmine!listener!

Core.async!mult-channel!

(loop! …! (wamp/send-event …)! (recur))!!

Browser-2!Browser-1!

Workspace-event Organization- event

dao!

Page 44: Clojure at ardoq

Ardoq.com @ebaxt

Publish!Event! Redis!

Carmine!listener!

Core.async!mult-channel!

(loop! …! (wamp/send-event …)! (recur))!!

Analytics!

Testing!

dao!

Page 45: Clojure at ardoq

Ardoq.com @ebaxt

REPL

Driven Development

Page 46: Clojure at ardoq

Ardoq.com @ebaxt

http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

https://github.com/juxt/jig

https://github.com/stuartsierra/component

https://www.youtube.com/watch?v=13cmHf_kt-Q

Page 47: Clojure at ardoq

Ardoq.com @ebaxt

The Clojure experience

So far

Page 48: Clojure at ardoq

Ardoq.com @ebaxt

Page 49: Clojure at ardoq

Ardoq.com @ebaxt

Other benefits

Tiny codebase Fast feedback Libraries (both Java and Clojure) Concurrency

Page 50: Clojure at ardoq

Ardoq.com @ebaxt

Challenges

Dynamic language - tradeoffs Lack of signatures LISP – with great power comes…

Page 51: Clojure at ardoq

Ardoq.com @ebaxt

Thank you!

Questions?

Page 52: Clojure at ardoq

Ardoq.com @ebaxt

THANK YOU!