all look at HealthUnlocked’s adopAon of Clojure, 4 years on. A discussion of some of the problems we encountered. A grab bag of pracAcal techniques we found for miAgaAng them.
GP/doctor less frequently had be3er interacAons with their GP/doctor would recommend HealthUnlocked We posiDvely affect people’s health z healthunlocked.com 27% 77%
an ASP.NET Web Form applicaAon, was released. 2010 2012 The first big rewrite, into a .NET API and Javascript frontend. 2013 An a3empt to introduce NodeJS backfired, and in the rush to deal with the fallout, our first Clojure app was born. We decided we quite liked Clojure, actually, and built preIy much everything in it from then on
of (nearly) duplicated code Each app has its own code for cross-cuYng concerns such as logging, configuraAon, error reporAng, connecAon management…. Our understanding of how to do those things has evolved over the years So we have many variaAons on similar themes sca3ered across our codebases
And they’re probably busy because they’re also the only person who knows how apps Y and Z work… Usually there’s only one person who knows how app X works and/or how to deploy it
combined data from mulAple other apps or data sources. To understand what data you had, it was someAmes necessary to follow the thread through mulAple different applicaAons. Dependencies between apps or of apps on services made it difficult to test all features locally.
decent (Midje) unit test coverage, but: • they seemed to break whenever we made any changes • rarely caught any of the bugs we introduced • mocked out all external services, so didn’t test these interacAons
designs which are copies of [their] communicaAon structures” “The 'Inverse Conway Maneuver' recommends evolving your team and organizaAonal structure to promote your desired architecture” Your code, organisaAon, and teams are interrelated parts of the same ecosystem, and should be designed together
• Consolidate our code into fewer, bigger applicaAons • Create mulA-app repos to group together related apps We wanted to: • Promote collaboraAon and pairing • Create good examples of best pracAces • Have these examples followed consistently
by funcAonal area Database access isolated to apps in the repository Everything needed to run the set of applicaAons collected in one place Easy start-up of dev- and test-Ame services using docker-compose
the re-frame template A simple change but one we found to have a profound effect Code is grouped by funcAonal area Shared code dealing with cross-cuYng concerns at the top-level - this is scary to change Code sharing between subfolders is not allowed, so the effect of changes here is localised
• Focus on integraAon tests over unit tests • Move from Midje to clojure.test • Write tests that hit the DB rather than mocked it out • InvesAgate generaAve tesAng
an applicaAon we built in partnership with Macmillan Cancer Support We used an append-only data model to make the data more easily auditable. Halfway into the project we ran into some performance issues with our table design Thanks to our integraAon tests we were able to completely replace every database table and all our data access code with a new, performant design with no bugs introduced.
level • Schemas to validate config, inputs and outputs • Isolated imperaAve code for each individual feature • The tricky to get right stuff pushed into shared code
mind, and vice versa An integraAon test is worth a thousand unit tests VerAcal slices allow you to group code by funcAonal area LimiAng the potenAal scope of changes makes them much less scary Schemas at applicaAon boundaries are invaluable for validaAon and documentaAon