Functional SOLID – Open/Closed Principle

Continuing on the series about SOLID principles on functional programming, the next one is the Open/Closed Principle. The definition from the Wikipedia:

The open/closed principle states “software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”; that is, such an entity can allow its behavior to be extended without modifying its source code.

This is kinda interesting on its own way: what’s an “extension”? Considering the context when it was written, and future interpretations of the principle, the idea is that any program should not be re-compiled (re-written, modified, etc) to be extended. The idea of this principle is that local changes should not propagate to other parts of the program: make entities as self-contained as possible, write then in a way that extensions would not depend on modifications on these entities, then “close” then to modifications. I can see two cases for the “open-closed principle” violation, and the first one is the most common:

(defn as-int [some-str]
  (when (re-matches #"\d+" some-str)
    (Integer/parseInt some-str)))

This code returns an Integer if it can parse a string as a number, and nil if it can’t. Now, suppose we want to “extend” this functionality by accepting other objects like Double (truncates to integer) or nil (returns 0). The only way to do it is to change the when to a case, but that means that for every new implementation I’ll have to change this function. Now, a better way is to use protocols:
(more…)

Quick Post – native apps with ClojureScript

React apps now run on the desktop with Electron. They also run on the desktop with react-native-desktop, or proton-native. In this simple post, I’ll share my (very small!) experience with proton-native:

First, you need Shadow-CLJS. Because of the npm integration, you can literally just:

npm install proton-native react react-dom create-react-class

And then add [reagent "0.8.1"] to dependencies on shadow-cljs.edn file. Then, configure a :node-script target and start to build things. This means that your shadow-cljs.edn file will be:

{:source-paths ["src" "test"]
 :dependencies [[reagent "0.8.1"]]
 :builds {:desktop {:target :node-script
                    :main demo.app/init
                    :output-to "target/index.js"}}}

(more…)

Functional SOLID – Single Responsibility Principle

I am a firm believer that we have to learn from the past instead of throwing all away for the future. And this is one of these moments: I have seen multiple talks, presentations, slides telling about SOLID and Design Patterns in functional programmings. Some are serious, some are satires, but most only speaks “you just need functions, really!” on their explanation on the principles, effectively diminishing the usefulness of the principles and also by imagining that, somehow, if we only use functions all our problems on developing software would be solved forever.

So, to counter that, I’m going to re-visit SOLID, but this time I’ll not compare with “OO” – instead, I’ll ask for us to try to grasp the meaning behind each principle. I’m going to use the definitions from Wikipedia, because (1) it’s easier to track changes and (2) it’s condensed from multiple sources, so it’ll probably not reflect a single opinion from an author. I also thought about being one single post, but it became quite complicated, so I’m splitting this post in multiple ones (and probably the one about LSP will be the most extensive of all). So, let’s begin by the first: the Single Responsibility Principle:

The single responsibility principle is a computer programming principle that states that every module, class, or function should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class, module or function
(more…)

My Atom editor configuration for working with Clojure/Script, revisited

Sometime ago, I did a post on how I work with Atom to develop Clojure and ClojureScript projects. It is in Portuguese, so I’m gonna re-visit the subject and also update with my current workflow.

There are two packages that I have to install to work with Clojure: lisp-paredit and chlorine. Without lisp-paredit, when I start a newline, the indentation gets all sorts of problematic. I use it on “strict mode” and use the tools to slurp/barf forward only. As for chlorine, it is needed to have autocomplete, evaluation, show documentation, goto var definition and so on. Last, I use also parinfer so I can remove whole lines of text and parinfer will infer the correct closing of parenthesis for me (most of the time at least).

Now, how exactly do I work with Clojure? When you use lein or boot, you’ll get a nREPL port. This is not the port you use with Chlorine, so I need a bit more of work. I can’t just start a REPL with lein repl or clj, I need to inform the tool to open a socket-repl server. The JVM option needed is: '-Dclojure.server.myrepl={:port,5555,:accept,clojure.core.server/repl}'. So, the commands below are what I use with lein or clj:

JAVA_OPTS='-Dclojure.server.myrepl={:port,5555,:accept,clojure.core.server/repl}' lein repl

or

clj -J'-Dclojure.server.myrepl={:port,5555,:accept,clojure.core.server/repl}'

This will open a REPL at port 5555 (or I can change the port if necessary). Then, it’s time to fire up the Atom’s command palette and select “Connect Clojure Socket REPL”, put 5555 on the port, and connect. Then, I’ll use “Refresh Namespaces” or “Load file” command to load my latest version of code into the REPL, and start working.
(more…)

Putting REPL-Tooling to test – VSCode!

Sometimes you make some tooling because you want to use it; sometimes, to experiment; and sometimes to test the waters.

The last tooling in that I did was one of these cases – now there’s a port of Chlorine to Visual Studio Code called Clover!

Now, when I started the project I imagined that VSCode would not have all the features that I have in Atom, nor all the APIs that I want to use – for example I didn’t have any hope of having the inline results in this version.

The thing is, I wasn’t expecting it to be so bad! To begin with, the API: is not really that bad documented, but compared to the Atom, it is incredibly weak. The first thing is that they expect you to use TypeScript so there’s little to no documentation on how to represent objects in pure JavaScript; for example in some cases you can use pure objects, on others you have to instantiate a TypeScript class in the JavaScript code. Also, there are multiple parts of the documentation when they just give you the type signatures and little (or even no) explanation (and let’s make a little detour here: what’s the deal with some people that use static types, that they expect you to understand how any API work just by showing the types of the functions?).

The second part is that VSCode expects you to fit your plug-in infrastructure on what they offer – so, some functionalities will land on the “peek definition” API, others on “Code Lens” and so on. The problem is that they don’t explain what’s a “code lens” for example nor give you any screenshots of the functionality in action – mostly the documentation is some code examples in GitHub repositories so you have to download, install the example extension on your machine and then run it to simply understand how something works.

The second hard part is that you can’t test the API in the devtools – in fact the devtools is almost useless because when you have an error, the stacktrace will point you to a minified JS code in the VSCode internal API. Also, some exception messages are completely obscure and some log errors on the devtools but things work fine on the editor. Well, to summarize: it’s completely useless to depend on the errors.

But the worst part, at least for REPL-Tooling, is that you can’t change the UI of VSCode in any way – and this means no pop-ups, no new elements, no console in the editor, nothing – the only way you have that you can extend the visual components is by implementing a webview – and by webview I am not saying an “electrom webview” when you can access all the Node.JS APIs – I am saying a simple web page when you have to pass your data to and from the editor using JSON. And and that’s all there is – no Date, no JavaScript classes and, of course no Clojure objects.
(more…)

Complex testing – the saga

While I’m developing Chlorine, sometimes I need to test multiple specific implementations of lots of really complicated stuff like REPL state, connection, async stuff (as the project is ClojureScript on Node.JS, all I/O treatment is via callbacks) and the complicated nature of rendering multiple different object types on Atom editor. I had multiple regression errors, then I’ve created some “acceptance” tests (these open up a real Atom editor and evaluate commands on it). The problem with these tests should be obvious: they are slow, and I mean REALLY SLOW, and they need a real Atom editor, lots of setups, and because Atom is not really predictable on its actions (sometimes you connect REPL and it changes the focus on the editor) there are lots of unnecessary interactions on the editor just to have less false-negatives.

Now, as I told before, I’m developing Chlorine together with REPL-Tooling, a library that should contain all tooling for any editor capable of running Javascript to run a port or Chlorine. There’s still too much on Chlorine that relies on internal Atom APIs (for example, detection of the beginning and end of forms is one, detection of namespace’s forms is other) but time is passing and more and more is being moved to REPL-Tooling, and as soon as the detection of forms is on REPL-Tooling (and is stable) there should be possible to port most Clojure parts to REPL-Tooling, and then I can think on how to refactor the ClojureScript part, test it, and then Chlorine will be a very easy project to port. Also, as a proof-of-concept there’s Clematis for NeoVIM (it’s still on the very beginning and nothing much happened after I wrote about it here), and also an “electron fake editor” that I’m using as test.

Wait, What?
(more…)

Heart of Clojure

It all started with the idea to send a talk to Heart of Clojure, based on my work on Chlorine. Now, the talk wasn’t selected, but I decided to go to the conference even then. Being on Brazil, this meant about 19 hours of travel, so without thinking too much I bought the ticket to the conference and decided what do to latter about the travel, where to stay, and how many days I would stay. The first idea was to simply go there to the conference, but I imagined it would be very tiring, so came a strange and incredible idea that I’ll let to another post.

Now, the conference. In fact, it was different from everything I ever saw. First of all, it was amazing – not only because of the technical talks, but the whole experience of being in Leuven, meeting new people, using English as the first language everywhere, trying to understand a little of Dutch (spoiler alert: it didn’t work), and so on…
(more…)

Rails’ ActiveRecord – the bad and the ugly

I’m known to not be a big fan of ActiveRecord. No, that would be a simplification: I probably hate ActiveRecord and think it adds more problems than it solves, specially after I began to work with functional programming and saw how difficult, if not utterly impossible, is to make ActiveRecord models behave like immutable structures or separate (and maybe even predict) the I/O from the rest of the code.

The ActiveRecord pattern (not the GEM) was created to hide SQL details from the users. The Gem elevates this to extremes: you never know when a query is issue, what query is issued (unless you check the logs), and sometimes a latter clause modifies the way previous clauses work. Also, to extend ActiveRecord, you need to rely on monkey-patches and other internal implementation details, and there are API changes that seem innocent but are tremendously dangerous.

Now, what I want to do in this post is to elaborate the bad and the ugly parts. I’m not gonna talk about the “good parts” because we already know: auto-discovery of fields, fast prototyping, simple CRUDs, and so on. One could argue that this “easy setup, fast prototyping” is not worth the amount of technical debt you’ll have later, but let’s focus on the bad parts instead:
(more…)

Object-oriented after working with functional programming

Sometimes I need to divide my knowledge in phases: when I started to program, I felt that C/C++ were the best languages to make a software. Then, I’ve began to work with Ruby and learned Test-Driven Development. I divide my knowledge “before TDD” and “after TDD”, because it literally changed the way I could think about software and tests in general. Now, I’ll probably make the same division: “before functional programming” and “after FP”, and I only discovered that things have changed this week: I just discovered I don’t know how to do object oriented programming anymore – and to be honest, it’s not really a bad thing: I also saw in practice how object-oriented programming expects you to write lots of boilerplate in most situations.

This realization came to me when I was working in a peculiar kind of problem – it’s basically a ruby code that needs to connect on messaging system and, when it receives a message, needs to persist it in a relational database. The problem is that this specific system have a strong consistency requirement, so the message could only be updated on DB before a specific event happens: after that, we can’t change it anymore, except for some specific fields. Also, as we’re working with messaging, we can receive the message multiple times, out of order, and all of those strange things that happens on Internet-land. So, to summarize:

  1. The system will receive a message
  2. It’ll UPSERT a record on DB, just with some identification fields (they’ll never change, and if they do, they characterize another message to be persisted – think about an external id)
  3. It’ll BEGIN a transaction and SELECT ... FOR UPDATE my just upserted message
  4. It’ll find, on another table, the rest of the fields on the message
    1. If this record doesn’t exist, we’ll create it (and log)
    2. If it does exist, we’ll check additional info, and decide: or we ignore it (and log), or we upsert (and log), or raise an error

Now, for the implementation. Because consistency is a must have on this system, I don’t want to expose for future programmers (be it myself or some of my friends) some code that’ll induce me to errors: after all, who wants to do with_consistency_check(msg) { Message.upsert!(msg) } when I can just do Message.upsert!(msg), right? So, I don’t want to allow people to be able to modify, find, update, or anything else outside of the with_consistency_check (or whatever name I decide). So, how to do it?
(more…)

Chlorine, Clematis, REPL Tooling

Recently I began to migrate some of the code on Chlorine to REPL Tooling, so things may become more testable. I already found multiple bugs in this approach and began an integration test methodology using Electron (I say that there are three kinds of developers in the field of automated tests – the ones that don’t test, the ones that do, and test freaks. I’m probably the later).

In the beginning, the idea would be to rewrite the renderer of results and exceptions so that I could fix lots of bugs that they have. So far, it’s progressing slowly, but I already can render datomic results in a meaningful way (the last renderer was interpreting as Java objects, which they indeed are) and fix some bugs with tags and other issues.

Now, one of the things that I wanted in the new renderer is the ability to copy/paste results in a meaningful way – as I’m using UNREPL, there are lots of tags that need to be reinterpreted, like #unrepl/browseable for datafy. These need to be “translated” to something useful for rendering on screen, with links to navigate inner details, but for copy-paste they should have a textual representation that makes sense (probably the hard part).

The results of all these experiments are quite interesting – when you evaluate something and th result is a Java object, there’s a link ... that can be used to navigate inside the object: it’ll show getters, the current class, methods that the object supports, so things like “goto definition for Java object” or “Javadocs” aren’t really necessary.

Then, one of my friends asked for a Vim option. Just for fun, I started Clematis, a port of Chlorine to NeoVim. And it seems they things are progressing faster than I thought!
(more…)