{"id":1076,"date":"2015-03-18T19:24:30","date_gmt":"2015-03-18T23:24:30","guid":{"rendered":"http:\/\/blog.agilityfeat.com\/?p=1076"},"modified":"2020-11-09T23:35:32","modified_gmt":"2020-11-09T23:35:32","slug":"clojure-walking-skeleton","status":"publish","type":"post","link":"http:\/\/34.200.113.64\/en\/blog\/2015\/03\/clojure-walking-skeleton\/","title":{"rendered":"How to build a Walking Skeleton in Clojure"},"content":{"rendered":"<p><strong>This blog post was co-authored with <a href=\"https:\/\/github.com\/ggoldens\" target=\"_blank\" rel=\"noopener noreferrer\"> Germ\u00e1n Goldenstein<\/a>.<\/strong><\/p>\n<p>At AgilityFeat we strongly believe that our technical success in building products is based on the combination of meticulous software engineering practices and a simple, yet powerful, software design.<\/p>\n<p>We are always looking for ways to motivate our developers to write code that follows a simple design. A simple (although not simplistic) design leads to maintainable and resilient code. The kind of code we are looking for:<\/p>\n<ul>\n<li>has low coupling: modules don\u2019t have dependencies between them.<\/li>\n<li>has high cohesiveness: a module does only the thing that he is supposed to do, no more.<\/li>\n<li>is readable: \u201cAlways code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.\u201d<\/li>\n<li>uses high levels of abstraction to manage complexity.<\/li>\n<\/ul>\n<p>In other words, at AgilityFeat we build software products that bring a competitive advantage to our clients in terms of rapid feature implementation.<\/p>\n<h2>The Case for Lisp<\/h2>\n<p>Back in 2001, Paul Graham <a href=\"http:\/\/www.paulgraham.com\/avg.html\">famously confessed<\/a> that the functional programming \u00a0language Lisp was the secret weapon that gave him such a competitive advantage during his days as a start-up founder.<\/p>\n<p>Paul makes an argument in favor of using Lisp:<\/p>\n<ul>\n<li>\u201c[&#8230;] it follows inexorably that, except in special cases, you ought to use the most powerful [language] you can get.\u201d<\/li>\n<li>\u201c[&#8230;] the only programmers in a position to see all the differences in power between the various languages are those who understand the most powerful one.\u201d<\/li>\n<li>\u201c[Lisp] is simply the most powerful language available\u201d<\/li>\n<li>\u201c[&#8230;] because Lisp was so high-level, we wouldn&#8217;t need a big development team, so our costs would be lower. If this were so, we could offer a better product for less money, and still make a profit.\u201d<\/li>\n<\/ul>\n<p>Implicitly Paul was predicting that lots of features that Lisp already had in the 60\u2019s or 70\u2019s would be slowly adopted in modern languages as a proof of its superiority.<\/p>\n<h2>A Functional Programming Renaissance<\/h2>\n<p>Surely, fifteen years later, we have seen how Functional Programming has had a strong revival, not only because of the abstraction power at managing complexity, but also because it is really useful in keeping integrity and good performance in distributed systems. When you have a distributed infrastructure, your \u00a0program needs to behave exactly the same every time and it needs to operate in a way where its tasks can be shared across of thousands of instance machines.<\/p>\n<p>There is a significant number of Functional Programming concepts that were first introduced decades ago in Lisp and now are enabled and the recommended standard in languages like Ruby, Python, Javascript, Swift, Java and C#. These concepts include immutable values, no side-effects, higher-order functions, currying, recursion, lazy evaluation, functions as objects, lambda statements, closures, decorators\u2026.<\/p>\n<p>For Paul Graham, one particular feature that set Lisp apart is macros: the ability of write a program that can manipulate, or deal with another program, exploiting the<a href=\"http:\/\/en.wikipedia.org\/wiki\/Homoiconicity\"> homoiconicity <\/a>of Lisp code.<\/p>\n<p>We are not going to go any deeper regarding macros, for now, because as Paul said: \u201cIt would be convenient here if I could give an example of a powerful macro, and say there! how about that? But if I did, it would just look like gibberish to someone who didn&#8217;t know Lisp; there isn&#8217;t room here to explain everything you&#8217;d need to know to understand what it meant. In Ansi Common Lisp I tried to move things along as fast as I could, and even so I didn&#8217;t get to macros until page 160.\u201d<\/p>\n<h2>Let\u2019s Imagine a Walking Skeleton<\/h2>\n<p>The one thing we are going to do now is to imagine that we are required to build a privacy communication platform based on PGP cryptography, in Clojure. Being a Lisp dialect, Clojure is an excellent choice for getting into the Functional Paradigm.<\/p>\n<p>For educational purposes, we will skip all the specifications of a formal requirement list and please let\u2019s assume that the following Walking Skeleton sums up all the technical risks we want to address during the <b>Iteration 0<\/b> of this imaginary project.<\/p>\n<p>Let me emphasize this: We will not build a Walking Skeleton for a real world project. We will build a Walking Skeleton whose complexity could be equivalent to the <b>complexity<\/b> of a real world project.<\/p>\n<p>We will build our Walking Skeleton, step by step. It will take a lot of patience. Don\u2019t panic! Grab your towel!<\/p>\n<p>You can take a look at the code and the working demo here:<\/p>\n<p>&#8211; Demo deployed in Heroku:<a href=\"http:\/\/agilityfeat-challenge.herokuapp.com\"> http:\/\/agilityfeat-challenge.herokuapp.com<\/a><\/p>\n<p>&#8211; Frontend code:<a href=\"https:\/\/github.com\/agilityfeat\/clojure-pgp-skeleton-front-end\"> https:\/\/github.com\/agilityfeat\/clojure-pgp-skeleton-front-end<\/a><\/p>\n<p>&#8211; User\u2019s Microservice code:<a href=\"https:\/\/github.com\/agilityfeat\/clojure-pgp-skeleton\"> https:\/\/github.com\/agilityfeat\/clojure-pgp-skeleton<\/a><\/p>\n<p>Let\u2019s start!<\/p>\n<h2>But\u2026 What is a \u2018Walking Skeleton\u2019?<\/h2>\n<p>Let\u2019s try to explain what a Walking Skeleton is quoting the following definition by Alistair Cockburn:<\/p>\n<blockquote><p>\u00abA Walking Skeleton is a tiny implementation of the system that performs a small end-to-end function. It need not use the final architecture, but it should link together the main architectural components. The architecture and the functionality can then evolve in parallel.\u00bb<\/p><\/blockquote>\n<p>Why should <a href=\"http:\/\/blog.codeclimate.com\/blog\/2014\/03\/20\/kickstart-your-next-project-with-a-walking-skeleton\/\">kickstart your next project with a Walking Skeleton<\/a>? Because the main source of failure in any software project is <b>integration<\/b> of your domain application with the rest of the world. Think of any API, library, architecture decision, new technology in the back-end or front-end. Think of all the integration points and then make them part of your Walking Skeleton specification. Addressing the most\u00a0risky part of your project at the beginning is in many orders of magnitude cheaper than later, when is usually too late to have any wise reaction when integrations go wrong.<\/p>\n<p>Important clarification: The main objective of implementing a Walking Skeleton is obtaining a huge amount of learning after the feedback loop is completed, namely, after the Walking Skeleton is completed. The beauty of the code or the visual design is not important at this stage. We want you to get your hands dirty with Clojure first. Once the <b>Iteration 1<\/b> starts, beautiful code and beautiful designs are paramount. Ugliness perpetrators shall be persecuted!<\/p>\n<p>Let\u2019s see a User Story that specifies our kind of meaty Walking Skeleton:<\/p>\n<p>As a final user I want to create an account with a PGP public key, that I already possess, so when the account is created the Welcome page is decrypted on the client\u2019s side.<\/p>\n<ul>\n<li>All the backend code must be in Clojure and it should use the<a href=\"https:\/\/github.com\/otto-de\/tesla-microservice\"> Tesla microservices<\/a> architecture from<a href=\"http:\/\/dev.otto.de\/2015\/01\/30\/we-released-the-basis-for-our-clojure-microservices\/\"> Otto<\/a>.<\/li>\n<li>All the Javascript code must be generated from ClojureScript<\/li>\n<li>Use<a href=\"http:\/\/openpgpjs.org\/\"> OpenPGP.js<\/a>.<\/li>\n<li>The frontend must use React with Reagent following a Flux [or<a href=\"https:\/\/github.com\/spoike\/refluxjs\/tree\/master\/dist\"> Reflux<\/a>] architecture.<\/li>\n<li>It should be a Responsive Design, mobile first.<\/li>\n<\/ul>\n<p>Let&#8217;s analyze what we should do:<\/p>\n<ol>\n<li>We must create an app in Clojure, where a user can sign up using a PGP public key previously generated.\u00a0This public key will be used in the backend side to encrypt the welcome page. The welcome page will be decrypted from the client side using the<a href=\"http:\/\/openpgpjs.org\/\"> OpenPGP.js<\/a> library, which will require the user to enter his private key at the time of receiving the encrypted message from the backend.<\/li>\n<li>The backend must be developed in Clojure using<a href=\"https:\/\/github.com\/otto-de\/tesla-microservice\"> Tesla micro-services<\/a> architecture developed by<a href=\"http:\/\/dev.otto.de\/\"> Otto<\/a>. We will\u00a0talk about Tesla &#8211; Microservices later, but for now just keep in mind that the backend must be implemented as a micro-service which receives data (the username and the public key), stores the data in a database, and then returns the welcome page encrypted with PGP.\u00a0In the repository you will also find the Login part, which is not included in this document for practical reasons.<\/li>\n<li>To build the frontend, we must use ClojureScript for generating all the Javascript code. We will also use<a href=\"http:\/\/holmsand.github.io\/reagent\/\"> Reagent<\/a> for handling the DOM with<a href=\"http:\/\/facebook.github.io\/react\/\"> React.js<\/a> from ClojureScript, using the logic of Flux. Finally, we must keep in mind that the site should be Responsive.<\/li>\n<\/ol>\n<p>Click the next chart if you want to visualize the whole process:<\/p>\n<p><a href=\"https:\/\/agilityfeat.com\/wp-content\/uploads\/2015\/03\/clojure-walking-skeleton-chart.png\"><img loading=\"lazy\" class=\"size-large wp-image-1077\" style=\"max-width: 510px; max-height: 720px;\" src=\"\/wp-content\/uploads\/2015\/03\/clojure-walking-skeleton-chart-725x1024.png\" alt=\"Clojure Walking Skeleton\" width=\"510\" height=\"720\" \/><\/a><br clear=\"left\" \/><br \/>\n<em>Clojure Walking Skeleton<\/em><\/p>\n<h2>Read a Lot, Learn, and Read More!<\/h2>\n<p>Before we start, we want to recommend some useful sites and tutorials that can help the Clojure novice in her quest for greatness:<\/p>\n<p>Clojure:<\/p>\n<ul>\n<li>Getting Started with Clojure:<a href=\"http:\/\/clojure-doc.org\/articles\/tutorials\/getting_started.html\"> http:\/\/clojure-doc.org\/articles\/tutorials\/getting_started.html<\/a><\/li>\n<li>Leiningen:<a href=\"http:\/\/leiningen.org\/\"> http:\/\/leiningen.org\/<\/a><\/li>\n<\/ul>\n<p>ClojureScript:\u00a0Modern ClojureScript tutorials:<a href=\"https:\/\/github.com\/magomimmo\/modern-cljs\"> https:\/\/github.com\/magomimmo\/modern-cljs<\/a><\/p>\n<p>Reagent:\u00a0Official page<a href=\"http:\/\/holmsand.github.io\/reagent\/\"> http:\/\/holmsand.github.io\/reagent\/<\/a><\/p>\n<p>Flux:\u00a0Flux Overview:<a href=\"http:\/\/facebook.github.io\/react\/docs\/flux-overview.html\"> http:\/\/facebook.github.io\/react\/docs\/flux-overview.html<\/a><\/p>\n<p>Tesla-microservices:<\/p>\n<ul>\n<li>GitHub Repo:<a href=\"https:\/\/github.com\/otto-de\/tesla-microservice\"> https:\/\/github.com\/otto-de\/tesla-microservice<\/a><\/li>\n<li>Otto\u2019s Blog: <a href=\"http:\/\/dev.otto.de\/2015\/01\/30\/we-released-the-basis-for-our-clojure-microservices\/\">http:\/\/dev.otto.de\/2015\/01\/30\/we-released-the-basis-for-our-clojure-microservices\/<\/a><\/li>\n<li>Component Framework: <a href=\"https:\/\/github.com\/stuartsierra\/component\">https:\/\/github.com\/stuartsierra\/component<\/a><\/li>\n<\/ul>\n<h2>A quick review of the required technologies<\/h2>\n<p>These are the most interesting features in Clojure:<\/p>\n<ol>\n<li>Clojure is a general-purpose language, with an emphasis on <a href=\"http:\/\/clojure.org\/functional_programming\">functional programming<\/a>. This is a programming paradigm that treats all as the evaluation of functions, mostly written between parentheses.<\/li>\n<li>Also, Clojure works with <a href=\"http:\/\/clojure.org\/data_structures\">immutable data structures<\/a><b>,<\/b> which means that once a data structure has been created, It can\u2019t be changed. If you add or remove something from an immutable collection, you would get a new one. A data structure can be shared among different concurrent threads without concurrent modification exceptions.<\/li>\n<li>Using mutable structures make it \u00a0really difficult to come up with a source code debug looking for the error line where the value of an object was changed. By having immutable data structures, it is guaranteed that every time you call a function with the same arguments it will return the same value.<\/li>\n<li>Clojure is a hosted language. It\u2019s a compiled language and it runs on <b>Java Virtual Machine<\/b>, so we can take advantage of the Java libraries!<\/li>\n<li>Using <a href=\"http:\/\/leiningen.org\/\">Leiningen<\/a>, we have a great tool for experimenting with code called <b>REPL (Read-Eval-Print Loop)<\/b>. You can type code into it, and then REPL evaluates it and prints the result. It will enable you to quickly check your functions behavior, and we strongly recommend its implementation.<\/li>\n<li>With <a href=\"https:\/\/github.com\/clojure\/clojurescript\">ClojureScript<\/a> you can convert your Clojure code into Javascript!. This means that you could take advantage of the Clojure language features (such as immutability, data structures) and you have a new way to write Javascript code without typing plain code.<\/li>\n<li>With <a href=\"https:\/\/github.com\/reagent-project\/reagent\">Reagent<\/a>, you will find a new way to write efficient React.js components using ClojureScript functions, even faster than plain old javascript React code. Reagent use the <a href=\"https:\/\/github.com\/weavejester\/hiccup\">Hiccup<\/a> syntax to write HTML code, and we were pleasantly surprised at the simplicity of representing HTML within Clojure.<\/li>\n<\/ol>\n<h2>Let\u2019s start coding<\/h2>\n<h3>Stage 1: Create the Clojure Environment<\/h3>\n<p>To start developing with Clojure, you must have installed Leiningen.<\/p>\n<p>To install it, follow these steps ( Copied from <a href=\"http:\/\/leiningen.org\/#installg\">http:\/\/leiningen.org\/#installg<\/a> ) :<\/p>\n<ol>\n<li>Download the lein script (or on Windows lein.bat)<\/li>\n<li>Place it on your $PATH where your shell can find it (eg. ~\/bin)<\/li>\n<li>Set it to be executable (chmod a+x ~\/bin\/lein)<\/li>\n<li>Run it (lein) and it will download the self-install package<\/li>\n<\/ol>\n<h3>Stage 2: Create the micro-service (backend)<\/h3>\n<h4>Create the new project with \u201clein new ms_users\u201d.<\/h4>\n<p>This will create the basic structure of a clojure project \u00a0with the default template.<\/p>\n<h4>Configure dependences in the project.clj file.<\/h4>\n<p>To build this backend, we need to include several dependences:<\/p>\n<ul>\n<li>\u00a0\u00a0 Tesla-microservices<\/li>\n<li>\u00a0\u00a0 Component Framework<\/li>\n<li>\u00a0\u00a0 Ring Codec (this is helpful to convert form-params like \u201ca=1&amp;b=2\u201d to a map {:a 1 :b 2})<\/li>\n<li>\u00a0\u00a0 PGP libraries (to encrypt the welcome page)<\/li>\n<li>\u00a0\u00a0 A data base library. We chose MongoDB for this exercise.<\/li>\n<\/ul>\n<p>So, the dependencies declaration in the project.cls file should look like this:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/ddd4728500037a5d5a87.js\"><\/script><\/p>\n<h5>About Tesla-microservice<\/h5>\n<p>According to the Walking skeleton definition, we must use the Tesla micro-services architecture. Tesla microservices is the common basis for some of otto.de&#8217;s microservices. It is written in clojure using the<a href=\"https:\/\/github.com\/stuartsierra\/component\"> component framework<\/a>. These are the features included:<\/p>\n<ul>\n<li>Load configuration from filesystem.<\/li>\n<li>Aggregate a status and application health.<\/li>\n<li>Deliver a json status report.<\/li>\n<li>Report to graphite using the metrics library.<\/li>\n<li>Manage routes using compojure.<\/li>\n<li>Serve content with an embedded jetty.<\/li>\n<\/ul>\n<p>You can see the code Tesla Micro-services and an example of how to use it on github: <a href=\"https:\/\/github.com\/otto-de\/tesla-microservice\">https:\/\/github.com\/otto-de\/tesla-microservice<\/a><\/p>\n<h4>Create a Database<\/h4>\n<p>For the purpose of this Walking Skeleton, We chose to use MongoDB as it is one of the most used NoSQL Engine DB. To install it locally, \u00a0We recommend reading the following link:<a href=\"http:\/\/docs.mongodb.org\/manual\/tutorial\/getting-started\/\"> http:\/\/docs.mongodb.org\/manual\/tutorial\/getting-started\/<\/a> Once installed, create the src\/db\/core.clj file where we are going to write the code to connect to the database, and perform some basic database operations. To create a DB connection, we can do it as follows:<script src=\"https:\/\/gist.github.com\/agilenature\/b9ba7dcc4afe1976ffb8.js\"><\/script><\/p>\n<p>We must create an environment variable \u00abMONGOLAB_URI\u00bb with the value of the local database URI. This is used to run the app in different environments (development, staging, production, etc ) . In our case, my local URI is <b>mongodb:\/\/127.0.0.1\/ms_users<\/b><\/p>\n<p>Now add two more functions to retrieve and insert users:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/agilenature\/f96b6bcc408380d417cf.js\"><\/script>The function\u00a0<b>create-user<\/b> receives a Clojure Map, and saves it in the collection \u201cusers\u201d.\u00a0The function <b>get-user<\/b> receives a username (string) and searches in the collection \u201cusers\u201d the document (record) that matches with that username.<\/p>\n<h4>Create the main function, and define the user-system component.<\/h4>\n<p>Let&#8217;s start with the example of Tesla. It all starts in the example_system.clj file.<script src=\"https:\/\/gist.github.com\/agilenature\/15ff322b881d29a56f7a.js\"><\/script><br \/>\nIn this file it is defined the <b>-main<\/b> function, which is the entry point to the app, and also defines the system component <b>example-system<\/b>. The main function, starts the <b>example-system<\/b> component.<\/p>\n<p><b>What is a Component?<\/b> The Component framework use <i>components<\/i>. A <i>component<\/i> is a collection of functions or procedures which share some runtime status. A component is defined as a Clojure Record implementing the Lifecycle protocol, which requires defining the start and stop of the component.<\/p>\n<p>Components are composed into <i>systems<\/i>. A <i>System<\/i> is a component which knows how to start and stop other components.<\/p>\n<p>In this case, the System <b>example-system<\/b> includes the <b>example-page<\/b> component (developed in example_page.clj ) and <b>calculator<\/b> component (developed in calculator.clj) .<\/p>\n<p>We will use this example to create our code. We will create the system <b>user-system<\/b>, which will contain the component <b>user-component <\/b>which is where we will write the main code of the Sign up.<\/p>\n<p>Our code will look like this:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/e5f5af0efa1e500f55e6.js\"><\/script>Notice that the namespace changed to <b>ms-users.user-system<\/b>, and the :require part now includes the <b>user-component<\/b> that we have to write now. On the other hand we add the key :server-port to the map that we send as a parameter to the <b>system\/empty-system<\/b>, with the value <b>(or (System\/getenv \u00abPORT\u00bb) 8080).<\/b> The function <b>System\/getenv<\/b> reads the environment variable \u00abPORT \u00bb to start the jetty server. If this variable is not set in our environment, then we will use the port 8080 by default. Environment variables are useful for working with different environments. We will write this code in the <b>src\/user_system.clj<\/b> file. The file name must match the name of the namespace. It\u2019s important to know that the \u00ab-\u00bb namespace should be replaced by \u00ab_\u00bb symbol in the file name.<\/p>\n<h4>Create the user-component<\/h4>\n<p>Let\u2019s create the file <b>src\/user-component.clj<\/b>. One more time, we are going to learn how to write a component with the Tesla example. To do this, we should look at the file <b>src\/example-page.clj<\/b> A component is defined as follows:<script src=\"https:\/\/gist.github.com\/agilenature\/3d86ce8796b38057d3b1.js\"><\/script><\/p>\n<p>In this example, Compojure (one of the features into Tesla) is used to define system routing.<\/p>\n<p>These routes are defined in the start of this component.<\/p>\n<p>We see that if we run<a href=\"http:\/\/localhost:8080\/example\/\"> http:\/\/localhost:8080\/example\/<\/a> the <b>usage-page<\/b> function will get executed.<\/p>\n<p>If we go to<a href=\"http:\/\/localhost:8080\/example\/\"> http:\/\/localhost:8080\/example\/<\/a>foo\/ the function <b>result-page<\/b> will be executed.<\/p>\n<p>Now that we understand how we have to create our user-component, we are going define a route \u201c\/signup\u201d that receives the POST request with the username and public key, and calls a function that performs the user sign up and returns the welcome page encrypted.<br \/>\nThe component is now as follows:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/7eb07a801bd5d8a7e44b.js\"><\/script><\/p>\n<h4>Define the function \u201csignup-user\u201d.<\/h4>\n<p>This function will take care of starting the registration process:<\/p>\n<ul>\n<li>Get the user data from a POST request (username and public key)<\/li>\n<li>Save the user data in the database<\/li>\n<li>Encrypt the welcome page, which for our example, is going to be a simple welcome message.<\/li>\n<li>Return the welcome page in json format.<\/li>\n<\/ul>\n<p>Ok, let&#8217;s start with the <b>signup-user<\/b><script src=\"https:\/\/gist.github.com\/agilenature\/eb42956feb6f361107bc.js\"><\/script><\/p>\n<p>This function receives the parameters and returns to Compojure the welcome page encrypted in json format. In order to format the welcome page in json, we have to add in :require the library <b>[clojure.data.json :as json :only [write- str] ]<\/b>.<\/p>\n<p>The welcome page encrypted is generated by the <b>welcome-page-signup<\/b> function, that is written below:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/c2c0d9554a123c928003.js\"><\/script>This function receives the \u201cbody\u201d parameter in the format \u00abvar1=1&amp;var2=2\u00bb. We are going to turn it into a map {:var1 1 :var2 2} to read it more easily. We\u2019ll do this in the line <b>(def form (<\/b><b>utils\/getmap<\/b><b> body))<\/b> This utility function (and some others) will be defined in the <b>utils.clj<\/b> file, and to use it we need to add the namespace in :require of <b>\u00a0user_component.clj<\/b> like this:<b> [ms-users.utils : as utils]<\/b>. Our utils.cljs file is now as follows:<script src=\"https:\/\/gist.github.com\/agilenature\/a25e273bb1cdf5b17539.js\"><\/script><\/p>\n<p>Let&#8217;s go back to the <b>welcome-page-signup<\/b> function.<\/p>\n<p>In the line <b>(if (<\/b><b>register-user<\/b><b> form<\/b>) we check the boolean value returned by the <b>register-user<\/b> function. This value will be <i>true<\/i> when the user was successfully inserted, and it will be <i>false<\/i> if it wasn\u2019t. If the username already exists in the database, then it will return the \u201cuser-exists\u201d error message . If it doesn\u2019t exist, then perform the insert in the database, and returns the welcome page generated by the <b>encrypt-message <\/b>function.<\/p>\n<p>Now, let\u2019s write the <b>register-user<\/b> function:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/5709e825f6b9ec595409.js\"><\/script>Good! We\u2019re almost there. Now we need to create the function <b>encrypt-message<\/b> that will be responsible for generating the welcome page and return it encrypted.<script src=\"https:\/\/gist.github.com\/agilenature\/d0acf5096fa4a62aefe1.js\"><\/script><\/p>\n<p>As we see, this function generates the welcome page in <b>message<\/b> with the text \u00abWelcome <b>name<\/b>! Your registration was successful ! \u00bb .<\/p>\n<p>Then, we call the function that performs the encryption. The function utils\/get-encrypted-message \u00a0will be defined in utls.clj because we might need to re-use it later in another function.<\/p>\n<p>So, we define this function in utils:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/28324db1c5e7e2082877.js\"><\/script><\/p>\n<h4>Setup the project.clj<\/h4>\n<p>To run this app, we have to finish the configuration of project.clj file. Add these lines:<script src=\"https:\/\/gist.github.com\/agilenature\/d4ecee4a5eeb87a2e161.js\"><\/script><\/p>\n<p>&#8211; :main key is to indicate where the main function is.<\/p>\n<p>&#8211; :clean-targets indicates the folder where the files are going to be deleted when you run \u00ablein clean\u00bb<\/p>\n<p>&#8211; :source-paths by default is \u00absrc\u00bb<\/p>\n<p>&#8211; :uberjar-name indicates the filename of the .jar file generated when you run \u201clein uberjar\u201d<\/p>\n<p>You can see the complete code (with the Login part) in the<a href=\"https:\/\/github.com\/agilityfeat\/clojure-pgp-skeleton\"> repo<\/a>.<\/p>\n<h3>Stage 3: Create the frontend app<\/h3>\n<p>Let\u2019s use <a href=\"http:\/\/www.luminusweb.net\/\">\u00a0Luminus<\/a>. It is just what we need.<\/p>\n<p>With a simple \u00ablein new luminus my-app\u00bb you have a frontend project basis.<\/p>\n<p>Also, Luminus has different project templates (see<a href=\"http:\/\/www.luminusweb.net\/docs\/profiles.md\"> http:\/\/www.luminusweb.net\/docs\/profiles.md<\/a>).<\/p>\n<p>As defined by our Walking Skeleton, we need to build the frontend with ClojureScript, Reagent and logic Flux, and Luminus has an exact template for this:<a href=\"http:\/\/www.luminusweb.net\/docs\/clojurescript.md#reagent\"> http:\/\/www.luminusweb.net\/docs\/clojurescript.md#reagent<\/a>.<\/p>\n<p>We just need to add the parameter +cljs and we will have a project basis with reagent.<\/p>\n<p>Also, according to the Walking Skeleton the frontend should be responsive, and Luminus uses<a href=\"http:\/\/getbootstrap.com\"> Bootstrap<\/a>, which is a CSS responsive framework. Great!<\/p>\n<p>For more information of Luminus framework, see:<a href=\"http:\/\/www.luminusweb.net\"> http:\/\/www.luminusweb.net<\/a>.<\/p>\n<h4>Create the frontend project<\/h4>\n<p>Type this in a command line: <b>lein new luminus frontend + cljs<\/b><\/p>\n<p>This will generate the project structure for us.<\/p>\n<p>In a new terminal, type: <b>lein cljsbuild auto<\/b><\/p>\n<p>The \u00ablein cljsbuild auto\u00bb is the instruction to compile the ClojureScript code that is inside the \u00a0\u201csrc-cljs\u00bb folder.<\/p>\n<p>The \u00abauto\u00bb setting guarantees that when we save the changes in a ClojureScript file, the compilation process that generates the JavaScript code will run automatically.<\/p>\n<p>Once this is done, we must type \u00ablein ring lein server\u00bb, which will automatically open a browser window to http:\/\/localhost:3000\/ which is the default localhost port.<\/p>\n<p>Now, we have the basis to begin developing the frontend.<\/p>\n<h4>Add openpgp.min.js<\/h4>\n<p>The file \/frontend\/resources\/templates\/home.html contains the base template code. In an earlier version of Luminus that we used the file is called \u00abapp.html\u00bb, so in the repository you will see that this file has that filename.<\/p>\n<p>In this file add the js the OpenPGP.js that will be used later to decrypt in the client side the welcome page received from the micro service. We have to use the minify versi\u00f3n which you can download<a href=\"https:\/\/github.com\/openpgpjs\/openpgpjs\/releases\"> here<\/a>.<\/p>\n<p>Save this file in\/frontend\/resources\/public\/js\/<br \/>\nYou have to include it in home.html as follows:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/2c9b91f461c2763a7ed9.js\"><\/script><\/p>\n<h4>Prepare the home template<\/h4>\n<p>We are going to reuse the home.html file to start writing our form. Just leave in thethe navbar, and the div with the id \u00abapp\u00bb, as follows:<script src=\"https:\/\/gist.github.com\/agilenature\/42637d9a798b6639aaea.js\"><\/script><br \/>\nReagent will generate the menu in the div \u00ab<b>navbar<\/b>\u00ab, and center the page in the div \u00ab<b>app<\/b>\u00ab.<\/p>\n<h4>Create the Signup form with Reagent<\/h4>\n<p>Now, let&#8217;s create the sign up form, which will be our home.<\/p>\n<p>In the folder \/frontend\/src-cljs\/ we have all our code Clojurescript.<\/p>\n<p>In the \/frontend\/src-cljs\/frontend\/core.cljs file we have the core code. Luminus comes with example code here, which we will definitely reuse.<\/p>\n<p>We will define severals<a href=\"https:\/\/github.com\/jonase\/reagent-tutorial\"> Reagent\u2019s Atom<\/a> that will help us manage the state of the form and the values \u200b\u200bof the components:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/5bb72e7038abdf71ec84.js\"><\/script>Now create some functions with Reagent to generate HTML code:<script src=\"https:\/\/gist.github.com\/agilenature\/9df9622e313170182589.js\"><\/script><\/p>\n<p>Both function atom-text-input and atom-text-area receive as parameters the id, the label, and the value, which is an atom.<\/p>\n<p>Whenever the value of an [:input] changes, Reagent will render again the components. This is the logic of<a href=\"http:\/\/facebook.github.io\/react\/docs\/flux-overview.html\"> Flux<\/a>.<\/p>\n<p>So, let&#8217;s define the form:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/5ecb9526126ac3f73bfa.js\"><\/script>As we can see, in this form there will be two fields to enter the username and the public key. This will be the first part of the sign up. The second part will receive the welcome page encrypted and decrypt it in the client side. Let&#8217;s modify the home function. Now we see:<script src=\"https:\/\/gist.github.com\/agilenature\/861202ded2f87c9f807b.js\"><\/script><br \/>\nLet&#8217;s change it to:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/72754007a1bea4cc3f4d.js\"><\/script>Consider this. The first thing you see is a <b>let [doc (atom {})]<\/b> and what it does is creating a Reagent atom locally, just for this function. By default it stores an empty map. Then, if the value of <b>(:saved? @state) <\/b>\u00a0is false, it will show the Signup page form, calling the function of Reagent \u00ab<b>bind-fields<\/b>\u00ab. This function displays a form, and assigns an atom to save the values\u200b\u200b. It also has a callback. Below we see that we use the Reagent component :button, where we define that the onClick event fires the <b>save-doc<\/b> function. Let&#8217;s write the save-doc function:<script src=\"https:\/\/gist.github.com\/agilenature\/af06df536e17f8463684.js\"><\/script><\/p>\n<p>When we perform a form submit, if the username and public key are not empty, the form values will be sent by POST to the route \u00ab\/save\u00bb. With the help of Compojure, we define that when a POST request comes to \u00ab\/save\u00bb, it receives the data and calls the micro-service sending the parameters, and finally returning the welcome page. This is explained below in section 3.5.<\/p>\n<p>We receive the response from the micro-service into the atom <b>encrypted-message<\/b>.<\/p>\n<p>If the response is equal to \u00abuser-exists \u00bb then will show an alert to the user telling that the username is already in use. Otherwise, we will have the welcome page encrypted in <b>@encrypted-message.<\/b><\/p>\n<p>Then, we modify the atom state to <i>true<\/i> doing:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/4d5c0418ba909141e9a9.js\"><\/script>According to the logic of Flux, when the state of an atom changes, Reagent will render again. So again the home function will be executed. This time <b>(:saved? @state)<\/b> will be true. If the value of <b>(:saved? @state)<\/b> is true, the second part of the Signup form (where the user enters their passphrase and private key) are displayed. Then, it comes the <b>welcome-page-form-component<\/b> function, which we define below along with the other functions we need:<script src=\"https:\/\/gist.github.com\/agilenature\/ce190eebbc0ac2ff54cb.js\"><\/script><\/p>\n<p>The function <b>welcome-page-form-component<\/b> will show us the second form, with the \u201cpassphrase\u201d and \u201cprivate key\u201d inputs.<\/p>\n<p>The user must complete both fields to decrypt the welcome page, as he\u2019s the only one who knows this information.<\/p>\n<p>When the button \u201cShow my welcome page!\u201d is clicked, the function <b>decrypt-welcome-page<\/b> \u00a0is called:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/agilenature\/859e7f6ef93439236354.js\"><\/script>This function validates if the input data is empty. If it\u2019s not, then it calls the javascript function <b>decrypt_message<\/b> which will decrypt the welcome page. The <b>decrypt_message<\/b> is a simple javascript function that uses the OpenPGP.js library:<script src=\"https:\/\/gist.github.com\/agilenature\/df9ccec8bf8124e73234.js\"><\/script><br \/>\nYou can copy\/paste this function and save it into \/frontend\/resources\/public\/js\/functions.js. Remember to add it to the home.html file, this way:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/0f4a37927d9cc92d2ba7.js\"><\/script>Finally, once the welcome page is decrypted, we store the text into the atom <b>decrypted_message<\/b>, and then we change the value of (<b>:page @state) <\/b>so that the content of the <b>welcome-page-component <\/b>\u00a0component is displayed<script src=\"https:\/\/gist.github.com\/agilenature\/98f91076938c8a0be200.js\"><\/script><\/p>\n<h3>Configure the \u201c\/save\u201d route with Compojure<\/h3>\n<p>Let&#8217;s configure the \u00ab\/save\u00bb route to receive the form and send it to the micro-service, adding to \/frontend\/src\/routes\/home.clj the following functions:<br \/>\n<script src=\"https:\/\/gist.github.com\/agilenature\/3531830743c54791f7b6.js\"><\/script><\/p>\n<p>We will use Compojure to define routes, and define that when a POST request arrives, send parameters to the \u00ab<b>save-document<\/b>\u00bb function.<\/p>\n<p>The <b>save-document<\/b> function sends the form data to the micro-service doing a <b>client\/post<\/b> function (<b>clj-http.client<\/b>) that allows us to make an internal call to a url, sending POST parameters.<\/p>\n<p>Notice that the url of the micro-service is defined in a environment :ms-user-url. This environment variable can also be created in the project.cljs adding the following line in the dev profile:<\/p>\n<p><b>:env {:dev true :ms-user-url \u00abhttp:\/\/localhost:8080\/signup\u00bb}<\/b><\/p>\n<p><b>Important<\/b>: When you deploy the application, you must create the environment variable MS_USER_URL (to be read by Clojure as :ms-user-url) in the production environment.<\/p>\n<p>You can see the complete code (with the Login part) in the<a href=\"https:\/\/github.com\/agilityfeat\/clojure-pgp-skeleton-front-end\"> repo<\/a>.<\/p>\n<h2>Conclusions<\/h2>\n<p>We discussed the concept and importance of a Walking Skeleton. We also mentioned some of the most interesting features of Clojure and ClojureScript.<\/p>\n<p>We saw step by step how to build a Clojure app composed by a micro-service and a frontend, following the Walking Skeleton\u2019s definition.<\/p>\n<p>With Clojure, we learned new ways of development, with new programming paradigms, tools, and new ways to create beautiful UI. Also, We learned the logic of micro-services, allowing an application to scale much easier.<\/p>\n<p>Thanks so much for reading all of this. Please feel free to contact me!<br \/>\nI look forward to hearing comments or questions from you!<\/p>","protected":false},"excerpt":{"rendered":"<p>This blog post was co-authored with Germ\u00e1n Goldenstein. At AgilityFeat we strongly believe that our technical success in building products is based on the combination of meticulous software engineering practices and a simple, yet powerful, software design. We are always looking for ways to motivate our developers to write code that follows a simple design. [&hellip;]<\/p>","protected":false},"author":9,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":""},"categories":[116],"tags":[139,140],"jetpack_featured_media_url":"","yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to build a Walking Skeleton in Clojure - AgilityFeat Panama Software Test Center<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/03\/clojure-walking-skeleton\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to build a Walking Skeleton in Clojure - AgilityFeat Panama Software Test Center\" \/>\n<meta property=\"og:description\" content=\"This blog post was co-authored with Germ\u00e1n Goldenstein. At AgilityFeat we strongly believe that our technical success in building products is based on the combination of meticulous software engineering practices and a simple, yet powerful, software design. We are always looking for ways to motivate our developers to write code that follows a simple design. [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/03\/clojure-walking-skeleton\/\" \/>\n<meta property=\"og:site_name\" content=\"AgilityFeat Panama Software Test Center\" \/>\n<meta property=\"article:published_time\" content=\"2015-03-18T23:24:30+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-11-09T23:35:32+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/34.200.113.64\/wp-content\/uploads\/2015\/03\/clojure-walking-skeleton-chart-725x1024.png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"22 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/34.200.113.64\/#website\",\"url\":\"https:\/\/34.200.113.64\/\",\"name\":\"AgilityFeat Panama Software Test Center\",\"description\":\"AgilityFeat Panama offers customized, multilevel web and mobile software testing for a variety of industries.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/34.200.113.64\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/03\/clojure-walking-skeleton\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"\/wp-content\/uploads\/2015\/03\/clojure-walking-skeleton-chart-725x1024.png\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/03\/clojure-walking-skeleton\/#webpage\",\"url\":\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/03\/clojure-walking-skeleton\/\",\"name\":\"How to build a Walking Skeleton in Clojure - AgilityFeat Panama Software Test Center\",\"isPartOf\":{\"@id\":\"https:\/\/34.200.113.64\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/03\/clojure-walking-skeleton\/#primaryimage\"},\"datePublished\":\"2015-03-18T23:24:30+00:00\",\"dateModified\":\"2020-11-09T23:35:32+00:00\",\"author\":{\"@id\":\"https:\/\/34.200.113.64\/#\/schema\/person\/fab573848f9e8605e2015db33035948d\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/agilityfeatpanama.com\/en\/blog\/2015\/03\/clojure-walking-skeleton\/\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/34.200.113.64\/#\/schema\/person\/fab573848f9e8605e2015db33035948d\",\"name\":\"David\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/34.200.113.64\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"http:\/\/1.gravatar.com\/avatar\/?s=96&d=mm&r=g\",\"caption\":\"David\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/posts\/1076"}],"collection":[{"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/comments?post=1076"}],"version-history":[{"count":1,"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/posts\/1076\/revisions"}],"predecessor-version":[{"id":1331,"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/posts\/1076\/revisions\/1331"}],"wp:attachment":[{"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/media?parent=1076"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/categories?post=1076"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/34.200.113.64\/en\/wp-json\/wp\/v2\/tags?post=1076"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}