The value of canonicity (2020)
building.nubank.com.br
building.nubank.com.br
Its not the choice of technology, its the deliberate limiting to those choices. The team have said ok, we are choosing these things, and nothing else. This means that yes, some things are harder to do, but it also means that there is less shit to maintain.
If we built bridges like we built tech, we could see the silliness of choosing the components for the developer rather than the product:
the start of the bridge will be made of steel reinforced concrete, the hand rails will be made of carbon fibre, but they are taking too long, so the team switched to wood.
The middle of the bridge will be made from just steel, because one of the developers wanted to learn how to slip weld.
The tail end of the bridge is a suspension bridge, because one other developer decided that they looked cool.
That's not to say that developer efficiency doesn't matter, but efficiency is very different from "that looks cool, lets do it like that" Limiting choice is good, but when you first start, it fees like a straight jacket.
There is no "Done" state, there is no real plan for the future. It is possible to make software sustainable, but for many reasons there's not much incentive to do so.
Partly because its rare that the business understands that product it makes, or if they do understand, leadership get bored and want to try something new.
The bridge you describe sounds like one that was built and would be maintained in a more organic way. If we repaired more, we'd perhaps have more objects built like this. And we'd in turn learn much more about interactions between materials, and have a larger body of knowledge (and maybe folk wisdom) about objects built with such interactions.
But yes, more risk and uncertainty, which is intolerable in the current culture (though I suspect it could become more tolerable if our energy systems and supply chains start to break down, and the current calculus stops making sense)
I read this and think: ok, I guess this is going to be one of those posts advocating for boring tech (i.e just use Java everywhere).
> the answer is quite short... Clojure for production services, Kafka for asynchronous communication, Datomic as our database for high value business data, Scala for our analytical environment, and Flutter for our mobile app
Holy non-canonical technology choices, Batman!
Both are great examples contradicting conventional "wisdom".
IME Clojure is boring in a good way vs Java, as the pace of language evolution is slower, the language is simpler, and simplicity is more highly appreciated in the culture of the ecosystem.
[1] See first 5 in https://github.com/razum2um/awesome-clojure#database
More seriously, this content should be read and evaluated divorced from the reader's personal affection for specific tools, otherwise what value did this writeup provide if your opinion was set from the get go?
...
The Kafka being Java one is the most difficult one to refute I'd say.
Though I agree with the message that keeping the library choice small is good. I just think they already lost that war at some point. There are cracks in the argument in the article. Diatomic... "For high value data", implying it did not generalize to low value data, or they have several other dbs around. Shoulda picked postgres, it's more general, but hand was forced by clojure, which was the original hipster in the stack I expect.
How are they similar, apart from both running on the JVM? One is a Lisp dialect the other one an OOP language...
I guess your argument is "if you want to use the JVM environment (i.e., available libraries and frameworks), why not use Java?" -- which is a fair question. I suppose so, this argument just questions any JVM-language other than Java in general, and is not specifically tailored at the choices of Nubank.
You could as well have asked "why Clojure and not Common Lisp?" - I mean, if you for some reason determined that a lisp is the best language for the job, why would you choose Clojure... But I think the standard answer is that with Clojure, you get the best of both worlds: Java interoperability and Lisp expressiveness.
I personally find Lisps a maintenance nightmare (because of their ability to express complex computations very tightly), so the even more general question could have been: "Why Clojure?" (without comparison to any potential alternative).
> Diatomic, why not postgres?
Datomic kind of follows naturally from chosing Clojure, I suppose.
Apart from that, I do agree with your general analysis.
Clojure is 16 years old, how is that hipster tech?
> Diatomic, why not postgres?
If it works, why not?
> Flutter... it's gonna be cancelled.
????????
I don't like Google and Flutter as much as the next guy, but at least use some arguments instead of parroting "Le GoOgLe bad" meme.
But if they do, the bank loses their mobile apps, of which they built one (so far) that ports nicely to iOS and Android.
Then they make new ones.
What else should they have used?
At some point worrying that things will be deprecated is just a loosing proposition.
Mobile apps are not irreplaceable.
Common Lisp is 39 years old and it’s hipster tech. APL is 57 years old and it’s hipster tech. You can be a hipster at any age. (And it’s not a bad thing.)
Clojure is functional(valuable for correctness), based on lisp(a proven language), compatible with the JVM ecosystem, and attracts high quality programmers. Janestreet uses Ocaml for similar reasons.
I'm less familiar with Diatomic, but a quick look around seems to suggest that companies like Facebook and Netflix are paying customers, and Nubank are the owners. Plus it's written in Clojure. If it works well for them, seems like it's probably a fine investment.
Flutter might get canned, but also Flutter apps are cheap and high quality. It was probably a good choice, and can easily be replaced if the project dies.
My original (and common) perspective is to favour dynamism and choice ecologies.
But then I realized there's an interesting analogy here of mimicking how life tends to navigate the explore-exploit tension. For example, in lifecycles or social creatures:
Childhood as a solution to explore–exploit tensions https://royalsocietypublishing.org/doi/10.1098/rstb.2019.050...
Explore first (like "stupid" and "rash" children make decisions, in breadth first search of solution space) and then slowly ratchet into a more exploitative strategy, capitalizing on learnings. So adapt the decision strategy over time, instead of expecting a continuously applicable strategy. Older organisms adopt this strategy, and it's evolutionarily selected because it works in most environments.
So it's perhaps not unreasonable to make very exploratory hipster choices at the start, and then adapt to become more conservative after childhood :)
> Clojure is a immutable, functional language, and Java is the exact opposite.
Program in an immutable, functional style is possible in any language. It won't be as good as in Clojure, and if someone wants Clojure's style they should use Clojure. But that won't stop anyone who wants specific properties. I personally am happy to be writing code that is Clojureish in any language people want to pay me to use.
Regardless of that, the interop between Clojure and Java ecosystems is as close to perfect as can be achieved; they're basically the same circle on a Venn diagram. There is no risk of Clojure having a different deprecation schedule compared to Java.
It is so not. Clojure is to immutable-functional as Prolog is to logic: a procedural language with fancy syntax and funny execution order, masquerading as the other thing.
=> (def globalX 0) (defn getX [] globalX) (getX)
0
=> (def globalX 1) (getX)
1
=> (while (< globalX 10) (def globalX (+ globalX 1))) (getX)
10
It's built on the JVM. How could it be otherwise? Sure, you can program in the immutable-functional style in Clojure, but under the hood, it's procedural. You have to deal with all the same procedural issues: the compiler doesn't really smooth anything over for you.> This sounds very bitter.
This is bitter. But I thought what you replied to praised Clojure.
Assuredly. Yet, in an immutable-functional language, the examples I gave are unrepresentable. Clojure has nice syntax, like recur, to make it easy to write pure functional programs, but ultimately it's a procedural language full of side-effects, with a fairly simple mapping to JVM semantics.
Clojure is often the right tool for the job, and I'm sure the Clojure programmers reading this are thinking things like “a simple mapping to JVM semantics is not a bad thing!”. But mere usefulness doesn't make it Agda.
Or is enterprise Java effectively dynamically typed as well, so that the language-level difference matters less? I had only very limited exposure to JEE, and was surprised how much that was nominally unchecked at the Java language level was effectively type-checked by the JEE platform. But maybe this falls apart for non-toy projects?
More seriously, if you want something with type T, Clojure can give you something with type T. It understands types. Doesn't respect them, but it understands what it is ignoring. It isn't trying to replicate Java, but it has all the tools to replicate Java if necessary.
[0] The author acknowledges that this paragraph, while true, is unhelpful. It is offered in a wry tone.
I think, it makes sense to constrain yourself if you use a bit more alternative tech.
While this post makes sense -- limiting tech choices -- it's rather contrarian, limiting choices to bleeding edge tech, which can go away or change on a whim.
But their culture has always been like this, I once attended a conference were they touted how they were using 'hexagonal architecture', at the time, it felt like something only Google or Amazon could get away with (inventing tech buzzwords).
For what it's worth, they have a wrap for always talking up how they use bleeding edge/buzz word tech at meetups, interviews and the like. I guess they can get away with being a unicorn in their market (i.e. Latam neobank)
https://en.wikipedia.org/wiki/Hexagonal_architecture_(softwa...
instead of locking and mutexes and semaphores you think in terms of branching and merging, much like git or similar VCS systems.
what is "hipster" about that?
Are you implying Clojure is not compatible with Postgres?
Problem I have with gift cards is a lot of merchants and machines refuse them. I wonder if neobanks have this issue?
That's an exceedingly optimistic use of "just," I suspect.
But yeah, Bank of Brazil, a boring public bank has this for ages, just the app is ugly and intuitive only for financial savvy people.
You can set number of transactions, limit per transaction, total limit of that specific virtual card, etc.
Bookkeeping is not something people usually do here. And I hope that OpenFinance, that is a Brazil Central Bank endeavour (that Nubank is also adhering), be more open to the general public, because today is more about exchanging info between banks to provide better intel whenever you need loans, etc.
With OpenFinance you can choose to share your info from one bank to another, but you can't download this information yourself. Only through downloading ofx, CSV, pdf (the existing tools) on each of your banks, a nightmare to automate.
[1]: https://steve-yegge.blogspot.com/2007/06/rhino-on-rails.html
Anything else may be allowed, if it makes sense for the task at hand, but it's an uphill fight.