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…)

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…)

SOLID e SQL

Para os que não conhecem, o princípio SOLID é uma “sigla de siglas”, uma tentativa de formalizar códigos limpos, flexíveis e funcionais principalmente para linguagens orientadas a objeto. Os princípios são Single Responsibility Principle, Open-Closed Principle, Liskov Substitution Principle, Interface Segregation Principle e Dependency Inversion Principle. Sendo bem sucinto:

  • SRP indica que todo objeto deve ter apenas uma responsabilidade. Ou seja, fazer uma classe para atender apenas uma função específica.
  • OCP indica que toda classe deve ser aberta para adição de novas funcionalidades, mas fechada para modificação. Ou seja, quando for preciso adicionar mais funcionalidades, isso deve ser feito apenas adicionando novos métodos, sem precisar alterar os que já existem.
  • LSP indica que deve ser possível substituir um objeto por seus filhos, na herança, sem dar problema. Na prática, significa que um objeto filho altera a forma como o objeto pai funciona, extendendo ou não suas funcionalidades, mas nunca alterando o comportamento geral
  • ISP indica que todo código deve organizado de forma que jamais seja necessário implementar métodos que não são utilizados. A idéia é melhor explicada (com exemplos) neste post.
  • DIP indica uma necessidade de depender de classes abstratas, não de classes concretas. Ou seja, ao invés de, em um código, receber num método uma classe concreta, receber uma classe abstrata e, quando o método for chamado, passar uma classe concreta

Ok, e aonde o SQL entra nisso? Ele não é orientado a objeto, não é “turing-complete”, é apenas uma linguagem de busca num banco de dados, certo? E sim, eu tou falando de SQL, não de PL/SQL ou qualquer coisa semelhante. A explicação é muito simples: Clean Code
(more…)