A web app in pure Clojure

5,395 views

Published on

A chronicle of my attempt to create a real time web app using pure clojure at every layer of the stack, from the client to the styles to the web server

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,395
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
77
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • A web app in pure Clojure

    1. 1. (parens(all(the(way(down))))) A web app in pure clojure
    2. 2. Clojure For
    3. 3. Clojure For Web Server HTML Css Javascript Web Sockets Data Transfer Deployment
    4. 4. Clojure Scramble
    5. 5. Clojure Scramble • A multiplayer game for practicing clojure
    6. 6. Clojure Scramble • A multiplayer game for practicing clojure • Transform given clojure collection into a new one in as many different ways as you can using list of permitted values
    7. 7. Clojure Scramble • A multiplayer game for practicing clojure • Transform given clojure collection into a new one in as many different ways as you can using list of permitted values • Compete against other clojurians for high score
    8. 8. Clojure Scramble • A multiplayer game for practicing clojure • Transform given clojure collection into a new one in as many different ways as you can using list of permitted values • Compete against other clojurians for high score • A work in progress - will launch at www.clojurescramble.com soon
    9. 9. Clojure For
    10. 10. Clojure For Web Server HTML Css Javascript Web Sockets Data Transfer Deployment
    11. 11. Clojure For Web Server • Noir - github.com/noir-clojure/noir HTML Css Javascript Web Sockets Data Transfer Deployment
    12. 12. Clojure For Web Server • Noir - github.com/noir-clojure/noir HTML • Hiccup - github.com/weavejester/hiccup Css Javascript Web Sockets Data Transfer Deployment
    13. 13. Clojure For Web Server • Noir - github.com/noir-clojure/noir HTML • Hiccup - github.com/weavejester/hiccup Css • Cssgen- github.com/paraseba/cssgen Javascript Web Sockets Data Transfer Deployment
    14. 14. Clojure For Web Server • Noir - github.com/noir-clojure/noir HTML • Hiccup - github.com/weavejester/hiccup Css • Cssgen- github.com/paraseba/cssgen Javascript • Clojurescript - github.com/clojure/clojurescript Web Sockets Data Transfer Deployment
    15. 15. Clojure For Web Server • Noir - github.com/noir-clojure/noir HTML • Hiccup - github.com/weavejester/hiccup Css • Cssgen- github.com/paraseba/cssgen Javascript • Clojurescript - github.com/clojure/clojurescript Web Sockets • Web Sockets - aleph, lamina, noir-async Data Transfer Deployment
    16. 16. Clojure For Web Server • Noir - github.com/noir-clojure/noir HTML • Hiccup - github.com/weavejester/hiccup Css • Cssgen- github.com/paraseba/cssgen Javascript • Clojurescript - github.com/clojure/clojurescript Web Sockets • Web Sockets - aleph, lamina, noir-async Data Transfer • Data Transfer - strings/reader. outgoing only! Deployment
    17. 17. Clojure For Web Server • Noir - github.com/noir-clojure/noir HTML • Hiccup - github.com/weavejester/hiccup Css • Cssgen- github.com/paraseba/cssgen Javascript • Clojurescript - github.com/clojure/clojurescript Web Sockets • Web Sockets - aleph, lamina, noir-async Data Transfer • Data Transfer - strings/reader. outgoing only! Deployment • Leinengen - superjar. upstart/monit. nginx proxy
    18. 18. Benefits of pure clojure
    19. 19. Benefits of pure clojure • No context switching
    20. 20. Benefits of pure clojure • No context switching • Share server and client code
    21. 21. Benefits of pure clojure • No context switching • Share server and client code • Enabled higher level abstractions
    22. 22. Benefits of pure clojure • No context switching • Share server and client code • Enabled higher level abstractions • Avoid web language pitfalls
    23. 23. Benefits of pure clojure • No context switching • Share server and client code • Enabled higher level abstractions • Avoid web language pitfalls • Everything maps easily to lisp
    24. 24. Clojure MVC
    25. 25. Clojure MVC • Namespaces make relationships explicit - good for architectural discipline. Control very directly who can see who.
    26. 26. Clojure MVC • Namespaces make relationships explicit - good for architectural discipline. Control very directly who can see who. • Quarantine state - lots of state inevitable in web programming. Can still be minimized compared to imperative programming. I’ve used atoms for everything so far. Simple updates. Other approaches?
    27. 27. Clojure MVC • Namespaces make relationships explicit - good for architectural discipline. Control very directly who can see who. • Quarantine state - lots of state inevitable in web programming. Can still be minimized compared to imperative programming. I’ve used atoms for everything so far. Simple updates. Other approaches? • Async events through lamina channels - decoupled interactions
    28. 28. Clojure MVC • Namespaces make relationships explicit - good for architectural discipline. Control very directly who can see who. • Quarantine state - lots of state inevitable in web programming. Can still be minimized compared to imperative programming. I’ve used atoms for everything so far. Simple updates. Other approaches? • Async events through lamina channels - decoupled interactions • I ended up with a thick ‘manager’ tier - async creates responsibilities that don’t fall neatly into mvc
    29. 29. Noir
    30. 30. Noir • Lightweight - gives you what you need. Server start (server.clj), routes (defpage), and basic http stuff (sessions, cookies, etc.). Mostly stays out of your way
    31. 31. Noir • Lightweight - gives you what you need. Server start (server.clj), routes (defpage), and basic http stuff (sessions, cookies, etc.). Mostly stays out of your way • Unopinionated - you must determine and enforce your own architecture. Doesn’t try to save you from yourself.
    32. 32. Hiccup
    33. 33. Hiccup • Expressive syntax
    34. 34. Hiccup • Expressive syntax • Composable in interesting ways
    35. 35. Hiccup • Expressive syntax • Composable in interesting ways • Crate - hiccup in clojurescript - github.com/ibdknox/ crate
    36. 36. Hiccup • Expressive syntax • Composable in interesting ways • Crate - hiccup in clojurescript - github.com/ibdknox/ crate • Death to xml! - xml is ugly and poorly implemented lisp. The designers will be fine.
    37. 37. cssgen
    38. 38. cssgen • Specify nested rules in clojure
    39. 39. cssgen • Specify nested rules in clojure • Mixins for functional css
    40. 40. cssgen • Specify nested rules in clojure • Mixins for functional css • Has a long way to go - less/sass/compass/etc. and some asset build tool like sprockets much better option at this point
    41. 41. cssgen • Specify nested rules in clojure • Mixins for functional css • Has a long way to go - less/sass/compass/etc. and some asset build tool like sprockets much better option at this point • Clojure needs a serious tool like clojurescript for css
    42. 42. cssgen • Specify nested rules in clojure • Mixins for functional css • Has a long way to go - less/sass/compass/etc. and some asset build tool like sprockets much better option at this point • Clojure needs a serious tool like clojurescript for css • Don’t underestimate front end organization! - clojure can and should take css to new heights
    43. 43. Clojurescript
    44. 44. Clojurescript • Namespaces are a huge improvement over js/ coffeescript - makes client side development feel a lot less like wandering through a dark Malaysian jungle
    45. 45. Clojurescript • Namespaces are a huge improvement over js/ coffeescript - makes client side development feel a lot less like wandering through a dark Malaysian jungle • You don’t need much state! - clojurescript can often function as a straight pipeline from server to ui. Don’t hold onto data unless you need it!
    46. 46. Clojurescript • Namespaces are a huge improvement over js/ coffeescript - makes client side development feel a lot less like wandering through a dark Malaysian jungle • You don’t need much state! - clojurescript can often function as a straight pipeline from server to ui. Don’t hold onto data unless you need it! • Feels like clojure! But native js interop can be tricky - javascript is a mutable paradigm. Leads to verbosity.
    47. 47. Clojurescript • Namespaces are a huge improvement over js/ coffeescript - makes client side development feel a lot less like wandering through a dark Malaysian jungle • You don’t need much state! - clojurescript can often function as a straight pipeline from server to ui. Don’t hold onto data unless you need it! • Feels like clojure! But native js interop can be tricky - javascript is a mutable paradigm. Leads to verbosity. • Check out Chris Granger libs - (ibdnox - noir/light table dude). jayq, crate, fetch. best cljs tutorial: chris- granger.com/2012/02/20/overtone-and-clojurescript/
    48. 48. Clojurescript • Namespaces are a huge improvement over js/ coffeescript - makes client side development feel a lot less like wandering through a dark Malaysian jungle • You don’t need much state! - clojurescript can often function as a straight pipeline from server to ui. Don’t hold onto data unless you need it! • Feels like clojure! But native js interop can be tricky - javascript is a mutable paradigm. Leads to verbosity. • Check out Chris Granger libs - (ibdnox - noir/light table dude). jayq, crate, fetch. best cljs tutorial: chris- granger.com/2012/02/20/overtone-and-clojurescript/
    49. 49. Noir-async
    50. 50. Noir-async • Netty wrapper
    51. 51. Noir-async • Netty wrapper • Noir-async/aleph/lamina make sockets simple
    52. 52. Noir-async • Netty wrapper • Noir-async/aleph/lamina make sockets simple • Lamina event channel
    53. 53. Noir-async • Netty wrapper • Noir-async/aleph/lamina make sockets simple • Lamina event channel • overtone/at-at for efficient short term scheduling
    54. 54. Noir-async • Netty wrapper • Noir-async/aleph/lamina make sockets simple • Lamina event channel • overtone/at-at for efficient short term scheduling • clj-time for date/time handling
    55. 55. Data transfer
    56. 56. Data transfer • Server to client. Clojure over the wire! - send clojure forms as strings and read them straight into context with clojurescript reader.
    57. 57. Data transfer • Server to client. Clojure over the wire! - send clojure forms as strings and read them straight into context with clojurescript reader. • Client to server. Use intermediary. - eval-ing client supplied strings = fail. Could use some sort of whitelist or safe eval? I used json -- encode and parse it on at both ends. Good json parser: github.com/dakrone/ cheshire
    58. 58. Deployment
    59. 59. Deployment • lein uberjar gotchas - specify :main and :keep-non- project-classes true in project.clj. specify (:gen-class) and require all views in server.clj
    60. 60. Deployment • lein uberjar gotchas - specify :main and :keep-non- project-classes true in project.clj. specify (:gen-class) and require all views in server.clj • nginx, upstart, monit - I haven’t deployed yet, but based on preliminary research, this lightweight stack should get the job done.
    61. 61. Deployment • lein uberjar gotchas - specify :main and :keep-non- project-classes true in project.clj. specify (:gen-class) and require all views in server.clj • nginx, upstart, monit - I haven’t deployed yet, but based on preliminary research, this lightweight stack should get the job done. • Continuous deploys? - git hooks? uberjar + scp + upstart?
    62. 62. Deployment • lein uberjar gotchas - specify :main and :keep-non- project-classes true in project.clj. specify (:gen-class) and require all views in server.clj • nginx, upstart, monit - I haven’t deployed yet, but based on preliminary research, this lightweight stack should get the job done. • Continuous deploys? - git hooks? uberjar + scp + upstart? • Environment config? - dev/staging/prod
    63. 63. Drawbacks of pure clojure
    64. 64. Drawbacks of pure clojure • Rough setup process • Cryptic stack traces - especially cljs • Lack of polished utilities - sass/compass, asset pipeline • Minor issues - overall, clojure is awesome for web dev!
    65. 65. Next steps
    66. 66. Next steps • DB integration
    67. 67. Next steps • DB integration • Test suite - unit/integration tests
    68. 68. Next steps • DB integration • Test suite - unit/integration tests • Advanced clojure - amazing what can be elegantly accomplished with 1/100th of the standard lib. I still don’t fully understand macros, state mechanisms, clojure concurrency, and a lot of functional constructs, but I’ve caught a glimpse of their power.
    69. 69. Next steps • DB integration • Test suite - unit/integration tests • Advanced clojure - amazing what can be elegantly accomplished with 1/100th of the standard lib. I still don’t fully understand macros, state mechanisms, clojure concurrency, and a lot of functional constructs, but I’ve caught a glimpse of their power. • Thanks for listening!

    ×