Leiningen: Split an uberjar into dependencies.jar and app.jar (to optimize Docker layers and AWS Lambda functions)

I want to split my application uberjar into a separate JAR with only the dependencies and a JAR with only the application code so that I can upload them as separate “layers” and thus leverage layer caching. While my code changes frequently and is tiny, the dependencies change rarely and are much bigger. If I can add them as a separate Docker layer or AWS Lambda layer then this can be cached on the server and reused when I upload a new version - saving time, bandwidth, and money.

Continue reading →

Choose Clojure not because it is easy but because it is "`weird`"

When I was deciding what new language to learn, I could have picked the quite familiar Scala but chose instead Clojure - not despite of its lack of object-orientation, its immutable data structures, its too many parentheses on a single line - but because of it. (And because of Paul Graham’s Beating the Averages.) Why?!

Continue reading →

Defeating Legacy Code with Living Documentation And Business-Level Tests

The big struggle when entering a new code base is distinguishing the essential business logic from the incidental aspect of how it is implemented. Both are just code - but which parts must be there and the way they are and which can be changed? If you don’t know then you fear to change anything. And that is exactly what happened when we took over the application MB. What to do? How to save the code from becoming an incomprehensible mess of legacy code, and dying?! We found an answer:  clj-concordion. (Read: Functional Core, Imperative Shell and Specification by Example.) 

Continue reading →

Fixing JSON out-of-memory error with streaming and MapDB

Once upon time, an API returned 0.5 GB JSON and our server crashed. We cried, we re-implemented it with streaming parser and a disk-backed Map and it worked again - but was slow. We measured and tweaked and finally got to a pretty good time and decent memory and CPU consumption. Come to learn about our journey, streaming JSON parsing, and MapDB!

Continue reading →

Applying Spec-based generative testing to a transformation pipeline - tips and lessons learned

Having the computer generate tests for you, trying tens of devious inputs you would never have thought of, is awesome. There is however far less experience with and knowledge of generative (a.k.a property-based) testing so I would like to share what we have learned and what worked for us when testing an important data transformation pipeline. We mostly leveraged our existing Clojure Spec data specifications to generate the tests, while regularly reaching down to clojure.test.check to create custom generators and for low-level control.

Continue reading →

Clojure: Common beginner mistakes (WIP)

Common mistakes made by Clojure beginners and style recommendations.

Continue reading →

How generating test data saved us from angry customers and legal trouble

Me: Simple! First we sum all the raw charges. Then we sum the totals over all categories - the two should be equal.
Computer: … Nope!
Me: What?! Let me see… Are you telling me that -0.01 + -0.05 is different from -0.06?!
Computer: Yep!

That’s how I learned (again) to never use doubles for monetary amounts. I would never have thought of it myself (though I should have), hadn’t we used generative testing to produce random test data (popular troublemakers included) - data I wouldn’t have thought of, such as 0.01 + 0.05 that cannot be represented precisely with a double. Now that we switched safely over to BigDecimals and angry customers and law suits are off the table, you might wonder what is this generative testing about and how does it work.

Instead of hardcoding inputs and expected outputs, as in the traditional “example-based” testing, inputs are randomly generated and outputs are checked against rules (“properties”) that you define, such as “the output of +(sort list)+ should have the same elements and length as list; also, each element is >= its predecessor”. And you can generate as many inputs as you want, for instance 100 is a popular choice.

Continue reading →

Highlights from the talk '`Exploring four hidden superpowers of Datomic`'

During our regular “tech lunch,” we have got our brains blown by the talk Lucas Cavalcanti & Edward Wible - Exploring four hidden superpowers of Datomic (slides) that summarizes the key benefits a startup bank in Brazil got from using this revolutionary database as the core of their technical backbone. We would like to share our highlights from the talk and a few other interesting resources.

Continue reading →

Translating an enterprise Spring webapp to Clojure

How to translate the concepts and patterns we know from enterprise Java applications to Clojure? It is not just a different syntax, the whole philosophy of the language is different. The thing is, many concepts and patterns do not translate - you just do things differently. We will look shortly at how we can solve common enterprise concerns in Clojure, compared to Java.

This post is intended for an experienced Java developer curious about how his object-oriented, enterprise know-how would translate into the world of functional programming.

If you are short on time then just scan the Summary table and read Basic principles perhaps together with Clojure primer to make sense of it.

Continue reading →

Clojure vs Java: Troubleshooting an application in production

I have just gone through the painful experience of troubleshooting a remote Java webapp in a production-like environment and longed for Clojure’s explore-and-edit-running-app REPL. I want to demonstrate and contrast the tools the two languages offer for this case.

Continue reading →

Clojure vs Java: The benefit of Few Data Structures, Many Functions over Many Unique Classes

In Clojure we use again and again the same data structures and have many functions operating on them. Java programmers, on the other hand, create a unique class for every grouping of data, with its own “API” (getters, setters, return types, …) for accessing and manipulating the data. Having been forced to translate between two such “class APIs” I want to share my experience and thus demonstrate in practical terms the truth in the maxim

It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures.
- Alan Perils in Epigrams on Programming (1982)

Continue reading →

Solution design in Java/OOP vs. Clojure/FP - I/O anywhere or at the boundaries? - experience

As a Clojure developer thrown into an “enterprise” Java/Spring/Groovy application, I have a unique opportunity to experience and think about the differences between functional (FP) and object-oriented programming (OOP) and approach to design. Today I want to compare how the solution would differ for a small subsystem responsible for checking for and progressing the process of fixing data discrepancies. The main question we will explore will be where do we deal with external effects, i.e. I/O.

(We are going to explore here an application of the Functional Core, Imperative Shell architecture. You can learn more about it in the Related resources section.)

Continue reading →

It will only take one hour… (On why programmers suck at estimating and the perils of software development)

“It will only take about an hour,” I said to her. Two days later, a pull request awaits review. Where has all that time gone? What are the sources of delay in software development and how can we make it faster?

Continue reading →

Java/Spring App Troubleshooting on Steroids with Clojure REPL

(Published originally at the Telia Engineering blog.)

We have a Java/Groovy Spring Boot webapp, mainly running a bunch of batch jobs fetching, transforming and combining data. It is challenging to troubleshoot production issues because some production APIs are only accessible from the production servers and it is difficult and possibly dangerous to run the application in full production setup locally. Fortunately, we can now connect a REPL to the running application, get hold of its Spring beans, and interact with it (invoking remote calls, checking the returned data, …), which is a real life-saver and something I want to demonstrate and describe here.

Continue reading →

How to use Clojure 1.10 pREPL to connect to a remote server (WIP)

Clojure 1.10 includes a new, program-friendly REPL or prepl (pronounced as “preppy,” not p-repl). However there is still very little documentation about it, though it is reportedly in making (it is alpha, after all). Here I want to demonstrate how to start it and how to connect to it in a primitive way (I hope to improve the user experience of the client eventually).

Update 22/3: Check out O. Caldwell’s Clojure socket prepl cookbook.

Continue reading →

Copyright © 2022 Jakub Holý
Powered by Cryogen
Theme by KingMob