Functionally evaluating functions

This is a direct continuation of “Functionally thinking”. If you don’t start a trilogy by the second movie, why should you skip the first article?!

No questionably, you get a lot of good things by thinking functionally. Your entire algorithm becomes a set of functions, beautifully combined to compute results. The programmer tells the computer to do one thing, composing it by using a set of functions. One after another, the software will complete its cycle by outputting the result in a predefined way, like saving a file in the disk, showing something in a screen or performing a request.

Functional programming does not come just with new cool principles from Lambda Calculus and Mathematics. We also need to understand what are the effects caused by giving to functions so much importance and the benefits we get from it. In other words: more new cool principles.

let sumArgs x y = x + y
let times10 x = x * 10
times10 . sumArgs 1 $ 2

I have just one goal here: finish this letting you know why the last line of code above outputs 30 when evaluated by a Haskell compiler and how awesome this is.

Don’t be hasty

Do you remember that languages following principles of Lambda calculus (or “functional languages”) are lazy, right? They won’t process anything until it’s really needed. I mean… REALLY needed. This usually envolve some kind of IO, like showing the result in your screen.

Let’s ask GHCi - our Haskell interactive shell - to apply the function map into a List containing three other Lists:

> map maximum [[1,2,3], [20,10,30], [300,200,100]]
[3,30,300]
  • Function: map
  • 1st parameter: maximum
  • 2nd parameter: [[1,2,3], [20,10,30], [300,200,100]]

For every element of the second parameter ([1,2,3], [20,10,30] and [300,200,100]), map applies its first parameter. And as you might imagine, maximum is a function.

> :t maximum
maximum :: Ord a => [a] -> a

Typing :t <something> in GHCi, we get the properties of expressions in the language. This expression we call “maximum” takes a List of a's - call it “anything” - as argument and returns a single element of this same type. Since a is a downcased word, it does not refer to any predefined type. BUT, must implement the Ord class, saying that can be ordered in some way.

Functions are just another element

But… hey, have you noticed? Come back with me to that map:

map maximum [[1,2,3], [20,10,30], [300,200,100]]

maximum is a function. Something that does a computation based on parameters. And we are using as a parameter to the map function. Not its result after called, but the function itself. This is what in formal ways is called “Higher-order function”: in the most higher level of the language - the same way we use may use the integer 1 - we can use functions. There’s nothing so magical about them, we can pass functions as parameters or even return one in a function.

Talking about functions using functions, we can do this pretty easily.

> let applyWith10 aFunction = aFunction 10

Up there you can see the definition of applyWith10. Applies any function with the integer 10.

> let sumWith2 x = x + 2
> applyWith10 sumWith2 -- has the same result of evaluating `sumWith2 10`
12

Or pass one as parameter to another:

> let complexCalculation = 4 + 8
> sumWith2 complexCalculation -- has the same result of evaluating `sumWith2 4 + 8`
14

Partial application

Hold yourself, you don’t need to leave your job (already) to start playing with Haskell just because you learned a dozen of new things. Because I have more.

> let sumThreeNumbers x y z = x + y + z
> sumThreeNumbers 2 4 8
14
> let sumTwoNumbersWith2 = sumThreeNumbers 2
> sumTwoNumbersWith2 4 8
14
> let sumNumberWith6 = sumTwoNumbersWith2 4
> sumNumberWith6 8
14

We first define a function receiving 3 parameters. If you apply it with less than the complete number of parameters, Haskell will automatically return a function ready to complete the computation with the remaining parameters.

> :t sumTwoNumbersWith2
sumTwoNumbersWith2 :: Integer -> Integer -> Integer
> :t sumNumberWith6
sumNumberWith6 :: Integer -> Integer

What the type definitions of these intermediate functions mean? sumTwoNumbersWith2 takes 2 integers as parameters and returns another integer. sumNumberWith6, by itself, takes just 1 integer and returns another. And what do you get from it? Modularity with no sweat. If you think really well on defining interfaces to your functions, like giving good names and receiving nothing different than the needed as parameters, you can share the same function across more blocks of a project, partially applying it and getting just the necessary parts of the algorithm.

Look mum, no parenthesis!

You’ve been seeing that I didn’t use parenthesis to apply functions. Neither on their definition.

You can try using them, but they won’t accept being used for this, lowered to a position where they aren’t welcome.

> let sumThreeNumbers(x y z) = x + y + z

:2:21: Parse error in pattern: x
> let sumThreeNumbers (x y z) = x + y + z

:3:22: Parse error in pattern: x
> let sumThreeNumbers x y z = x + y + z
> sumThreeNumbers(2 4 8)

:5:1:
    No instance for (Num a0) arising from a use of `sumThreeNumbers'
    The type variable `a0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in `GHC.Real'
      ...plus three others
    In the expression: sumThreeNumbers (2 4 8)
    In an equation for `it': it = sumThreeNumbers (2 4 8)

:5:17:
    No instance for (Num (a1 -> a2 -> a0)) arising from the literal `2'
    Possible fix:
      add an instance declaration for (Num (a1 -> a2 -> a0))
    In the expression: 2
    In the first argument of `sumThreeNumbers', namely `(2 4 8)'
    In the expression: sumThreeNumbers (2 4 8)

:5:19:
    No instance for (Num a1) arising from the literal `4'
    The type variable `a1' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in `GHC.Real'
      ...plus three others
    In the first argument of `2', namely `4'
    In the first argument of `sumThreeNumbers', namely `(2 4 8)'
    In the expression: sumThreeNumbers (2 4 8)

:5:21:
    No instance for (Num a2) arising from the literal `8'
    The type variable `a2' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in `GHC.Real'
      ...plus three others
    In the second argument of `2', namely `8'
    In the first argument of `sumThreeNumbers', namely `(2 4 8)'
    In the expression: sumThreeNumbers (2 4 8)
> sumThreeNumbers (2 4 8)

:6:1:
    No instance for (Num a0) arising from a use of `sumThreeNumbers'
    The type variable `a0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in `GHC.Real'
      ...plus three others
    In the expression: sumThreeNumbers (2 4 8)
    In an equation for `it': it = sumThreeNumbers (2 4 8)

:6:18:
    No instance for (Num (a1 -> a2 -> a0)) arising from the literal `2'
    Possible fix:
      add an instance declaration for (Num (a1 -> a2 -> a0))
    In the expression: 2
    In the first argument of `sumThreeNumbers', namely `(2 4 8)'
    In the expression: sumThreeNumbers (2 4 8)

:6:20:
    No instance for (Num a1) arising from the literal `4'
    The type variable `a1' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in `GHC.Real'
      ...plus three others
    In the first argument of `2', namely `4'
    In the first argument of `sumThreeNumbers', namely `(2 4 8)'
    In the expression: sumThreeNumbers (2 4 8)

:6:22:
    No instance for (Num a2) arising from the literal `8'
    The type variable `a2' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in `GHC.Real'
      ...plus three others
    In the second argument of `2', namely `8'
    In the first argument of `sumThreeNumbers', namely `(2 4 8)'
    In the expression: sumThreeNumbers (2 4 8)

Besides those creepy error messages, we’re already aware about this aspect: we don’t need and won’t be using parenthesis to enclose parameters for a function. Take your time to digest the idea.

How many times have you been in trouble on understanding where is the start/ending of each expression enclosed by parenthesis? What would you do if, from today, you woudn’t need them anymore? Maybe have more time to actually solve problems coding? Ya, that’s sound a good idea for everyone involved in a project.

Side effects of cleaning syntax

Let’s think about a use case more practical.

-- Since this block is intended to seem like more real world code,
-- I am using type declaration even when not required.
-- You will need to save it in a *.hs file and load it in a GHCi session
-- by using `:l `
platformFee = 0.03
paymentGatewayFee = 0.01
contributionsAmounts = [1000.0, 2300.0, 100.0, 5100.0, 800.0]

netAmount :: Double -> Double
netAmount grossAmount = (1.0 - platformFee - paymentGatewayFee) * grossAmount

In Neighborly's context, a crowdfunding platform, we have many contributions to projects. After a campaign is finished, we need to handle the project owner takeout. But first, we need to calculate the net amount of the campaign, subtracting platform (platform owners have the feature of keeping a percentage of received contributions) and payment gateway fees.

At first, we could think of using the above functions in this way:

> netAmount sum contributionsAmounts

:8:1:
    Couldn't match expected type `[Integer] -> t0'
                with actual type `Double'
    The function `netAmount' is applied to two arguments,
    but its type `Double -> Double' has only one
    In the expression: netAmount sum contributionsAmounts
    In an equation for `it': it = netAmount sum contributionsAmounts

:8:11:
    Couldn't match expected type `Double' with actual type `[a0] -> a0'
    In the first argument of `netAmount', namely `sum'
    In the expression: netAmount sum contributionsAmounts
    In an equation for `it': it = netAmount sum contributionsAmounts

But, as we already learned, no parenthesis are allowed. This is trying to apply the function netAmount with 2 parameters: the function sum and the list contributionsAmounts, which is wrong.

> let grossAmount = sum contributionsAmounts
> netAmount grossAmount
8928.0

We can give a name to the intermediate step of calculate the gross amont summing all contributions’ amounts. But why, if is going to be referenced just in the following line? We can surely improve this.

> netAmount $ sum contributionsAmounts
8928.0

The only thing special about the $ function is its infix purpose. Unlike functions with alphanumeric characters, $ was made to receive one parameter before its name and another after.

> :t ($)
($) :: (a -> b) -> a -> b

Evaluating netAmount $ sum contributionsAmounts has almost the same result as netAmount sum, with the difference that says “parameters after sum must be passed to sum function, not netAmount”. You might have a vague idea why this function is called “function application operator”.

> x 1 2 $ y 3 4 5

The above line will evaluate the expression y 3 4 5 and use the result as third parameter of the x function.

Summing up: composition nirvana

Usually payment gateways asks for whole numbers when dealing with money amounts. The reason is that, if you trigger a transaction with the value 120.222 should he complete with 22 or 23 cents? Or just consider the integral part (120)?

To complete this action, we will need to “compose” a function. In other words, use the result of a function as parameter to another.

> truncate . (* 100) . netAmount $ sum contributionsAmounts

You just used function application to get the sum of all contributions’ amounts, got the net amount from it, composed it using a partially applied function *, multiplying the number by 100 and truncated it.

> truncate ((netAmount (sum contributionsAmounts)) * 100)

At a higher level, you’re just doing this: applying some functions cleverly.

If this wasn’t already enough to consider Haskell a well designed language, I have more. Much more!

Mr. Burns touching fingers of one hand to another

Functionally thinking

Let’s refresh our minds with some concepts you learned in high school and may have forgotten.

In Mathematics, we have something cool that is used to play with numbers. Given one, we operate over it and return another.

100 (---) 103.5

For instance, we could input the number 100 and receive 103.5 back.

10, 42 (---) 105

Is even allowed to use more than one number in the input. We will use this pair of numbers, transform then the way we want and return the result. Since it’s just a matter of transformation, inputting the same values to this bubble will always output the same result. We call this bubble “function”.

Function is a basic concept when considering the origin of computers. These, created to give faster results for problems hard or slow to solve manually. If you had the chance to decrypt a message between two allies in a war, reading the original message fast were a matter of survival, helping you to prepare your army before enemy’s attack. You input some apparently random characters to the decryption function - which will be responsible to transform it - and receive back a readable message. The exact kind of function you learned in school, but with letters in the place of numbers.

No Pain, No Gain

No, it isn’t easy to learn anything on Mathematics. But there is a reason for this.

∠A + ∠B + ∠C = 180˚, ∀ ΔABC

Math aims to define concepts and use them to build larger structures. How about the above statement? Do you understand it? Translated to English, it’s something like “For all triangles ABC, the sum of angles A, B and C is equal to 180 degrees”.

ABC triangle, where ∠A + ∠B + ∠C = 180˚, ∀ ΔABC

Should be already enough to get the idea, but to get even more from this translated definition, you must know what “triangle”, “angle” and “degree” is and how these concepts relate to each other.

To better understand the large, you should know about concepts used in its construction. You end up getting a lot of information with a less words.

λ calculus (or just Lambda calculus if you don’t want to sound cool)

In 1924 and 1930, we had a major work made by two mathematicians toward the goal of making functions more powerful than ever. Moses Schönfinkel was the first, answering the question that, yes, we can create functions that depend lesser and lesser of external variables. This motivated Haskell Curry in his study to show that even functions with multiple arguments could be made combining single argument functions.

In 1936, Alonzo Church was the responsible of creating the whole new field called Lambda calculus, a notation to define and apply operations using just functions. He proved that every numeric function can be expressed by lambda-terms, or as you might know today by just “lambda”. Think about the following function:

λx. x + 3

This is the notation developed to express functions in this field. In the example, it defines a function receiving one argument - x - and, when evaluated, returns it summed with 3.

But I mentioned he proved we can express ANY numeric function. Which means we can include addition, multiplication, loops and even conditionals. Together with another name you may know better, Alan Turing, he showed that Lambda calculus can accomplish the same computations of a Turing machine. Every set of operations you make in any computer language can be expressed by functions. Both returning the same value.

Relation with computation #1: functions are immutable

In Mathematics, functions are always immutable.

gross_amount(price) = price * 1.03
gross_amount(100) => 103

When we defined this function “gross_amount”, we also defined the relation between the numbers and how we can get to the result. Also in computation.

gross_amount(100) => 103
gross_amount(100) => 103

We can run this function as many times as we want. Nothing will change its result. Calling it with 100 must always return 103, since 100 * 1.03 will always be 103. Wait 30 minutes and try again. 103. Multiplication didn’t changed its rules, so same result.

Even functions made to generate randomic numbers are immutable. To understand how, watch this Numberphile video, because you will understand way better than any explanation I would try to do.

x(y) = 10 * 4
x(10) = 100
x(12) = 120
x(3001.23) = 30012.3

If these functions will always return the same result when called with the same parameters, the computer can remember the last time you called and give the result to you. This is called “Memoization”.

But Irio, I can’t memoize all of my functions.
def store_contributions
  File.write("#{Time.now.to_i}"_contributions", contributions)
end

You are cheating. This is a procedure, not a function. It performs an IO operation, so yes, must be run in a different way.

Relation with computation #2: expressions does not have order

x(y) = 10 * y
y = 7
z(x) = 5 * x + 2

Think about this system of equations. If I want to know z(5), does it matter if I calculate first x, y or z? The result will always be 352, right?

numberOfProjects = 0
contribution = 1000
contributedToEachProject = contribution / numberOfProjects
puts contributedToEachProject

In this case, I don’t need to calculate contributedToEachProject until reaching the 4th line. No one is using, so why should I care? I just to remember that know how to calculate numberOfProjects, contribution and contributedToEachProject. When I ask for contributedToEachProject to do something really useful (printing in the screen), I go to its definition. I will need the contribution value, so I get it. The order of evaluation could be lines 4, 3, 2, 1 without any problem. What means this? I could run all of the three first lines in parallel, using multiple cores of my processor.

Since I don’t evalute expressions until being really needed, we’re going to call this “Lazy evaluation”.

But Irio, sometimes we do need order. I don’t want to detonate a missile and then lauch it. For sure.
a_collection.insert(some_value)
a_collection.remove(42)

If the first line run after the second, we might not have the expected result. I could be adding 42 to a_collection, the 42 wouldn’t be removed as we would expect. The problem is given the shared variable, a_collection.

-- Haskell
a_collection -: insert some_value -: remove 42
# Elixir
a_collection.insert(some_value)
  |> a_collection.remove(42)

Languages like Haskell and Elixir have ways to get around this and define order of operations. One way available is named “Monads" and is and abstraction used in Haskell implementation, for instance.

Paradise #NOT

Unfortunately, programming following these concepts in languages that support them well - called functional languages - won’t be (always) faster than doing your procedural code. Existing commercial processors essentially follow the Turing machine, so asking the processor to do exactly what will end up doing, most of the time, will bring faster results.

Sometimes, like when taking advantage of memoization, will beat times of imperative. But we started using abstrations like Object-oriented because maintaing pure imperative code wasn’t always the best option. With functional programming, we have another paradigm, focused on defining the solution of problems (grounded in its Mathematics’ foundations). We start saying a lot with less and using more the current multiple core processors we already have, making sure we learned what was presented to us more than 70 years ago.

Appendice

Do you want to learn more about Lambda calculus? Study this theoric introduction by Stuart A. Kurtz.

Do you want to learn more about Haskell? Read Learn You a Haskell.

Do you want to learn more about Elixir? The Pragmatic Bookshelf has something for you.

Do you want to learn more about how Mathematics can be applied in software development? Follow me!

Encontro mensal do GURU londrino

Como estava planejando uma viagem para a Europa iniciando em duas semanas, resolvi procurar uma conferência ou mesmo grupo de usuários que me permitisse apresentar algo sobre Ruby. Tenho estudado cálculo lambda e functional programming em geral nos últimos tempos, tenho uma talk simples que eu poderia traduzir para inglês e melhorar baseado no público que o evento tivesse. Por que não?

Fui pro Google e encontrei o LRUG, o GURU londrino. Mandei um e-mail para o organizador explicando que estudo Matemática e tinha alguns comentários acerca de functional programming que seriam úteis pros rubistas.

Hi Irio,

Yeah, sorry, the June meeting is full for talks. The group is quite big and so there’s about a 2-3 month lead time on slots for talks at the moment.

[…]

Agradeço e digo que de qualquer forma estaria por lá.

Ontem eu e o Josemar Luedke (vulgo Josemas) fomos no tal encontro mensal. Essa imagem é o que quero deixar:

128 confirmações de presença no evento

Com 128 confirmações, seguramente tiveram 60 presentes.

O café, água, chá e bolachinha são detalhes. Apesar de terem seguido estritamente o modelo tradicional de apresentação seguida de perguntas, a interação realmente aconteceu no fim de cada palestra com o pessoal virando pro lado e comentando algo interessante. E na ida subsequente ao pub, que pareceu ser rotineira.

Software development needs a Campfire

You will always want the best developers. Or at least those more adequate to your company. They won’t be in your city. The world has 7 billion of people, and each one can have good reasons to not reallocate or travel daily. Forcing it to do it will result in more costs and dissatisfaction with the moving. But don’t get me wrong: someone isn’t accommodated just for deciding to not leave friends.

Limitations. At least geographical distance is not one. We are on the 21st century.

Hiring remote doesn’t necessarily mean closing a deal with Indonesians (but would probably add a lot in culture); a remote employee can be in a close city or even in the peripheral area of the same one. Because, definitely, developers don’t need to be in the same office to do their job

Although it can be seem, the developer job is not just deploy a list of features. He needs a casual environment of constant knowledge exchange. It’s like an office itself, where he can talk about the need of semicolons in JavaScript while drinking a cup of coffee. An abnormal rate of delivered points on Pivotal Tracker can be a sign of a successful project, as exhaustion and introduction of bugs to be noticed just a couple of sprints later. As any professional, he will have a place to learn and cool off when needed. Problems solved joining everyone interested in the project in the same room; no wonder a discussion group on Campfire is called room.

Campfire doesn’t have any witchcraft. It’s just a chat. People send messages that other team members can read. With a differential: not every message needs to be read instantly. When you feel that this is needed, you can use… instant messaging (like Google Talk or Skype), which keep working as always. But what kind of message would you send in a company’s (or team’s) chat? The same sentences said out loud in the office’s room: “Guys, do you know any lib for authorizations compatible with Rails 4.1?”, “I’m using rbenv, but Ruby 2.1 isn’t properly loading with the project”, “What do you think of the design of this autocomplete” or “We can’t send user’s password by e-mail? Can we find any alternative without leaving the page?”. All of them are part of features that a developer could do alone (with or without Google’s help), but why not share?

As any workroom, not everything is about work. The Campfire room is free to talk about the movie watched in the weekend, an article being shared on Twitter or the last video from Freddie Wong. This kind of action will bring the office to anyone distant to it.

A concern to those trying this method is about communication. Although is a really important worry, cannot be a reason to prevent its use. Working physically remote won’t stop - or increase - communication problems, but will make them clearer. Given the both sides of the coin, you can use this to fix existing problems. A person pushing a feature after its estimate without getting help shows someone without pro activity. Being in the same site, he can argue the problem was “demonstrated”; remote, it must be directly reported.

And remember about necessity of instantly reading each message? It will give you a bonus: having a lot of people in the same room will force you to scan messages from those not working directly with you. This process will stand to, in a future point, remember yourself that someone knows something about a given problem that you are having. Will stand to know what happens in the company. In a way that working in site wouldn’t allow you. This will give the flexibility to do your job outside of office’s schedule and even attending to some courses.

But one of the challenges of working with Campfire is using it in the same room (that with four walls). What should be spoken and what goes as text? Each company can find the better solution for itself, but one simple and interesting use is: needs to be heard or can be interesting to someone else? Campfire. Is immediate? Skip instant messaging and poke your co-worker. You will see satisfaction and more concentration in the team.

So, use Campfire. Even if not from 37signals. You can have HipChat, a channel on IRC or any set group on a chat. Tools, as any other, must be used with a purpose.

Desenvolvimento de software precisa de um Campfire

Você vai sempre querer os melhores desenvolvedores. Ou ao menos os mais adequados à sua empresa. Eles não estarão na sua cidade. O mundo possui 7 bilhões de pessoas, e cada uma pode ter os seus bons motivos para escolher não se mudar ou deslocar-se grandes distâncias diariamente. Obrigá-la a isso trará problemas como custos com deslocamento e insatisfação com a mudança física. E não leve a mal: a pessoa não é acomodada apenas por não querer deixar amigos.

Limitações. Ao menos a distância física não é mais uma. Estamos no século XXI.

Contratar pessoas remotas não significa necessariamente fechar contrato com indonésios (apesar de poder te adicionar muito no quesito cultural); um empregado remoto pode estar numa cidade vizinha ou mesmo na periferia do mesmo município. Porque definitivamente desenvolvedores não precisam estar no mesmo espaço físico para desempenharem o próprio trabalho.

Apesar do que pode aparecer à primeira vista, o trabalho de desenvolvedor não é apenas fazer deploy de funcionalidades. Este, precisa de um ambiente de troca de informação constante e descontração. Ele é como o próprio escritório, onde você pode parar para trocar uma ideia sobre a necessidade ou não de ponto e vírgula no JavaScript durante um café. Uma taxa de entrega anormalmente alta de pontos no Pivotal Tracker pode ser sinal de um projeto bem sucedido, mas também de cansaço e introdução de bugs que serão detectados apenas meia dúzia de sprints adiante. Como qualquer profissional, a ideia é que tenha tempo para conseguir esfriar a cabeça e se auto-aperfeiçoar. Problemas estes resolvidos reunindo os interessados na mesma sala; e não é à toa que um grupo de discussão do Campfire é chamado de room.

O Campfire não tem nenhuma magia negra. É apenas um chat. Pessoas digitam mensagens que membros do grupo podem ler. Com um diferencial de uso: nem toda mensagem precisa ser lida instantaneamente. Quando essa necessidade realmente existe, você tem… mensageiros instantâneos (como Google Talk ou Skype), que seguem funcionando perfeitamente. Mas que tipo de mensagem enviaria num chat da empresa (ou da equipe)? O mesmo que diria em voz alta na sala física: “Pessoal, alguém conhece uma biblioteca para ajudar a criar permissões compatível com Rails 4.1?”, “O Ruby 2.1 não é carregado corretamente no meu projeto. Estou usando o rbenv.”, “O que vocês acham dessa aparência para o autocomplete?“ ou “Não podemos enviar a senha do usuário por e-mail. Tenho como contornar isso sem sair da página atual?”. Todas fazem parte de alguma tarefa que um desenvolvedor deveria ser capaz de realizar sozinho (com ou sem ajuda do Google), mas por que não compartilhar?

Como toda sala de trabalho, nem tudo que é ouvido é referente a trabalho. O Campfire é livre para qualquer um falar sobre o filme que assistiu no fim de semana, colocar o artigo da vez sendo compartilhado pelo Twitter e postar o último vídeo do Porta dos Fundos. Esse será o tipo de atitude que trará o ambiente físico do escritório para qualquer pessoa distante dele.

Uma preocupação constante de quem está entrando no mundo do Campfire é a comunicação. Apesar de ser um bom motivo para se repreender à mudança, não pode ser impeditivo. Trabalhar fisicamente remoto não impedirá - nem aumentará - problemas de comunicação, mas os deixarão mais evidentes. São dois lados da mesma moeda que podem ser aproveitados de modos diferente, caso exista interesse. Uma pessoa prolongando uma tarefa enquanto tem dificuldades e não procura ajuda, demonstra a falta de pró-atividade do profissional. Presencialmente poderia ter criado a ilusão que a dificuldade foi “demonstrada”; remoto, ela deve ser reportada diretamente.

E lembra da parte de não precisar ler as mensagens imediatamente? Você leva mais um bônus: se tiver bastante gente na sala, você pode escolher apenas escanear mensagens de determinadas pessoas com quem não está trabalhando diretamente. Esse scanning pode servir para num futuro lembrar que alguém já teve um determinado problema que atualmente te incomoda, por exemplo. Servirá para saber o que acontece na empresa. De um modo que trabalhar presencialmente não permitiria. E de um jeito que permitirá você ter horários mais flexíveis, talvez até para fazer cursos em um turno.

Agora talvez um dos maiores desafios de se trabalhar com Campfire é usá-lo dentro do escritório físico. O que devo falar pessoalmente e o que vai por escrito? Cada empresa pode encontrar o que se encaixa mais com o seu fluxo, mas uma forma interessante de usar é: precisa ou acha que qualquer um pode se interessar? Campfire. É imediato? Pule o mensageiro instantâneo e cutuque o colega diretamente. Você verá ganhos em satisfação e concentração da equipe.

Por isso, use o Campfire. Mesmo que não seja o da 37signals. Você tem o HipChat, um canal do IRC ou um grupo fixo em qualquer chat. Eles são apenas ferramentas, e como qualquer outra, não tem utilidade se não for usada com um propósito.

A necessidade de desenvolver aprendendo

Dificilmente você conseguirá manter desenvolvedores (ou, se preferir, “criadores”, já que não é de apenas programadores que me refiro) instigados no ambiente de trabalho se ele não oferecer formas de sempre aprender coisas novas. Um profissional desses está em constante formação e quer trabalhar em volta de pessoas que saibam mais do que ele, para que todos os dias possa tirar coisas novas. E tão constante quanto as reclamações, vemos gente que sente não estar aprendendo tudo o que poderia. Vindo de empregados de empresas pequenas, como é comum no ramo de tecnologia, é fácil encontrar causas: dificilmente num grupo de 10 pessoas encontraremos gente com grande (seja em dimensão ou profundidade) conhecimento e saiba instigar os outros a elevar o próprio nível.

As tentativas

Sabendo que depois de certo tempo a pessoa pode se achar limitada, a primeira alternativa é recorrer à literatura para conhecer casos passados. Do mesmo modo que um escritor lê obras clássicas para aprender padrões em casos de sucesso, o desenvolvedor quer conhecer técnicas provadas como funcionais. A literatura técnica, seja em qualquer área, não é exatamente barata. Mesmo ganhando 1 ou 2 salários mínimos, isso é um problema contornável, mas você quer ou não apoiar quem está se esforçando para aumentar a qualidade da sua empresa? Para ambos é um investimento baixo e com alta chance de bons lucros.

Muito valorizada também, é direcionar o profissional para cursos. Estes geralmente são fáceis de encontrar e têm preços variados. A empresa paga o empregado em dobro (salário e curso) e é um dos mais arriscados. E exatamente por isso que pode trazer melhor retorno: você está treinando uma pessoa em alguma habilidade necessária para o seu trabalho. Talvez esta seja única na empresa. O risco, caso você não consiga fidelizar o funcionário, de a médio prazo estar evoluindo o time do seu concorrente existe, mas aí valem as conversas que você vai constantemente levar com ele sobre o alcance de suas expectativas.

A terceira, e talvez a mais interessante de incentivar o aprendizado, é o networking. Chame do que quiser, mas conhecer pessoas novas e discutir ideias com gente diferente só tem a adicionar à capacidade da sua empresa. Nesse caso não pode haver medo da concorrência: ai existem pessoas com objetivos semelhantes, seja trabalhando com o mesmo crachá ou não.

Como se não bastasse, esse pessoal costuma levar a sério qualquer conselho bonito que ouvem por ai. Resultado: se passar 2 dias insatisfeito com o que está fazendo, tentará corrigir os problemas e propor soluções. De você, líder, é esperado que aproveite a oportunidade. Daí podem surgir mudanças interessantes e inovadoras.

As alternativas

Para contornar isso, não tem bala de prata: você precisará confiar em quem contratou e ser sincero (como também cobrar a contra-parte) no máximo de aspectos possíveis. Incentive, discuta e apoie.

Quer uma alternativa simples de ser implementada? Rotatividade. Se a empresa possui poucos funcionários, dê a oportunidade para trocas de projeto a cada 3 ou 6 meses. Isso fará bem para o profissional - que estará em um ambiente novo e de maior aprendizado - e para o projeto - que pode ter problemas invisíveis até então, revelados por carne nova no pedaço. Não tem gente nem projeto suficiente para ficar rotando? Use o networking que espero que já tenha feito para trocar um empregado por outro de mesmo nível em uma empresa parceira. Laços entre todos os envolvidos têm grande chance de se reforçarem.

O fim

E esse processo simplesmente não tem fim. Trabalhar com gente que está sempre criando é extremamente disposta a inovar. Aprender é fundamental para que essa capacidade esteja crescendo e tendendo ao infinito.

Sobre a relação entre satisfação e prestação de consultoria

A partir desse momento você é um consultor. Você conhece bem um processo ou ferramenta e sabe apontar quando ela deve ou não ser usada. Você é um especialista na resolução de problemas relacionados à sua área de domínio. Seu trabalho será estressante.

Prestar consultoria não é um trabalho fácil. Você só tem clientes com problemas e quanto mais extensos e complicados, mais interessante são para a empresa que presta o serviço. E este é seu papel: ter um cliente que só chegou até você porque tinha problemas, porque algo fugiu do controle. É possível generalizar para um cenário: a equipe atual não dá conta do que precisa ser feito. Prazos estão apertados, gente pouco qualificada para cumprir os requisitos ou o processo do projeto não ficou claro a todos. Resumindo: uma empresa precisa da sua ajuda.

Ajudar uma empresa não é fácil. Mas errar é comum e você deve encontrar cada um desses erros. Seu trabalho é estudar como ela funciona, participar dos processos e ensinar conceitos novos. Para você, de fora, será menos complicado de identificar os pontos deficitários. Mesmo este sendo aberto a novas ideias, alguém da empresa estará errado e o responsável pela sua contratação tem certa culpa no cartório. Seja por falta de conhecimento de melhores ferramentas ou exigências por mudanças bruscas, as pessoas da empresa não foram capazes de cumprir as restrições e obrigações que o mercado exige.

Mas você não vai querer que o cliente simplesmente aceite os seus argumentos. Um bom consultor - que vai ser lembrado pela sua capacidade de resolver problemas - deve ensinar o porquê de estar propondo mudanças. E argumentos frágeis não serão aceitos. Da mesma forma que você tem o objetivo ético de apontar qualquer coisa que deva ser melhorada, seu cliente tem um negócio que gera dinheiro. Para ele, que talvez tenha funcionários subordinados e parceiros comerciais, teorias acadêmicas nem sempre terão validade. Evidências práticas do funcionamento das ideias geralmente são requisitos para uma avaliação mais séria do que vai ser implementado. Se o próprio responsável pela empresa não souber claramente causas e consequências dos problemas, logo voltarão ao ponto inicial sem terem ideia do porquê. A forma mais efetiva de criar resultados satisfatórios é a partir de boas discussões com o dono do negócio. Se juntos chegarem a uma segunda ou terceira solução mais efetiva, esta deve ser colocada à prova. Dificilmente vocês terão algo perfeito, mas no fim isso não tem tanta importância. Antes de uma resposta pronta é importante se fazer a pergunta certa, que exigirá boa experiência. Pode ser que seu trabalho no fim seja até visto como supérfluo, mas ele foi o responsável por plantar sementes que vieram a germinar semanas depois.

E nem tudo são flores. Do mesmo modo que pessoas e empresas falham, você pode falhar. Esse entendimento, apesar de pré-requisito para qualquer pessoa se formar em Medicina, não é obrigatório em outros cursos. Assim como luta para melhorar o que você vê acontecendo de errado, você deve aconselhar medidas contrárias. Vale mais você ser honesto e prescrever eutanásia em partes que não têm mais chances de sobreviver sem a devida dignidade. Um especialista não deveria ter problemas em ser honesto e sugerir soluções efetivas.

Sendo um trabalho tão complicado e precisando argumentar sobre tudo o que faz, resta ser bem pago ou você deveria estar direcionando seus esforços diretamente para si. Mas qual seria a melhor forma de encontrar as respostas (e, obviamente, suas perguntas) se não fosse tornando-as cada vez mais fortes? A partir do momento que você é obrigado a argumentar convincentemente cada uma das suas decisões para pessoas que realmente precisam do seu trabalho, você tem muito mais satisfação ao saber que fez diferença. Sem dúvida é um trabalho que exige altruísmo e persistência.

Já é hora de acelerar minha startup?

Podemos pensar em 3 períodos de uma startup que essa pergunta vem à tona:

  • A ideia do produto ou serviço a ser oferecido não passa disso: uma ideia.
  • Temos algo funcionando e usuários, mas falta um modelo de negócios rentável.
  • Já foi gerado uma quantia em dinheiro considerável mas ultimamente o crescimento tem diminuído ou estagnou.

Se o seu caso não se enquadra em nenhum destes, você já deve ter várias opções de como fazer a empresa crescer e não sabe qual ou como decidir; ou talvez não seja mais uma startup.

Da ideia à prática

Neste ponto, você teve uma ideia. Genial ou nem tanto. Mas mesmo que seja baseada em algum modelo já existente, ela vai ser aplicada em um contexto diferente, então é necessário que você conheça os usuários envolvidos para poder adaptá-la e melhor agradá-los.

Talvez seja esta uma das fases mais interessantes de uma startup. É nela que vão ser formuladas hipóteses para serem testadas e validadas. Os fundadores começarão a descobrir quais dos seus sonhos têm possibilidade de funcionar no mundo real e ainda terão tempo de verem-se frustrados a ponto de não seguirem com a ideia adiante.

Se aí você já estiver comprometido com investidores, estará impedindo esse aprendizado necessário entre fundadores e mercado. Você pode acabar se vendo como uma pessoa que prefere seguir ordens e ter estabilidade financeira a arriscar-se montando uma empresa. Obviamente dinheiro será importante antes de torná-la lucrativa, mas passado esse período, você terá muitos argumentos para convencer pessoas competentes a te ajudarem - financeiramente ou não - no negócio.

Se uma aceleradora te oferecer ajuda para iniciar um projeto sem que você seja já um bom empreendedor ou conheça muito do mercado alvo, desconfie. Talvez ela não saiba da importância das ideias ou queira se aproveitar de um negócio que pode dar certo. Se você pagar o trabalho deles com uma porcentagem da empresa, terão um risco baixo (apenas o custo do próprio tempo durante a aceleração) apostando em você. Já que 20% de algo que vale zero é 0, a aprovação do mercado ao modelo tem chances boas de render frutos no futuro; se pagar com uma quantia fixa caso o projeto não alcance determinado patamar, beira à agiotagem. Investiram esta quantia com chance maior que 100% de retorno.

Dificuldade em análise de mercado

Chegado à este estágio, pode ser que a startup tenha até mesmo sido criada sem querer. Sendo ela ligada à software, talvez seja algum programa desenvolvido em algumas horas durante à noite. Clientes começaram a cobrar nota fiscal e você abriu uma empresa formal mas não consegue encontrar um modelo de negócios rentável ou agradável à todas as partes.

Estes fatores sugerem que sua ideia tem potencial. Ter usuários é um passo vencido, já que mostra que você não é o único acreditando na utilidade do serviço que presta. Agora qual a melhor forma - além de estudar - de tornar rentável aquele seu software que pelo acaso tem retornado menos dinheiro do que toma com suporte e servidores?

Permitir-se aprender conceitos novos é necessário em todas as etapas da vida, mas tendo uma empresa que não se paga pode ser decisivo. O que aconteceria se você precisasse fazer uma cirurgia daqui a alguns dias e não pudesse desempenhar seu papel de CEO por uma semana? A empresa teria rendimento negativo? Outros funcionários (talvez sejam você próprio) conseguiriam realizar suas tarefas sem mudanças drásticas?

Administração te ensinará a se posicionar bem para alcançar suas metas. Contabilidade explicará como funcionam finanças e ajudará a se organizar para entender quais metas devem ser alcançadas para tornar a empresa mais rentável. Psicologia e Filosofia serão ótimas para definir posicionamentos e como apresentar suas ideias a mentores em lugares específicas. Ou, ainda, pode explorar a área técnica usada no produto ou serviço prestado. Tendo esse conhecimento, basta que alguém te apresente as metodologias utilizadas para testar o mercado envolvido que será bem mais fácil de analisar resultados e aplicar os que tiverem sucesso comprovado.

Estabilizado ou decaindo

Existe um conceito matemático denominado “derivada”. A partir dele, podemos obter resultados referentes à taxa de crescimento da startup.

Gráfico mostrando "sucesso" em função de "tempo"

Se você manter um histórico organizado do que aconteceu na empresa, é simples construir um gráfico deste tipo a partir da definição de algumas métricas. Como o sucesso é definido por um número bastante complexo de fatores, podemos inicialmente considerar quantidade de lucro como “sucesso”.

Gráfico mostrando "sucesso" em função de "tempo" com retas indicando diferentes inclinações da imagem

No início, vemos que o sucesso - determinado pelo lucro - da startup está negativo (abaixo da linha em azul horizontal). Temos um aumento para algo positivo com o teste de algum modelo de negócio. Algum tempo depois, ela passa a permanecer constante (sem crescimento) até que percebamos que estamos na fase “Dificuldade em análise de mercado” e, mantendo o mesmo ritmo que temos, tudo indica que estagnou, deixando de crescer ou diminuir de “sucesso”. Você passa a estudar mais e descobre que o crescimento pode ser maior que qualquer outro momento, e se dedica cada vez mais a desenvolver e aproveitar a crista da onda (momento indicado pela reta “crescimento positivo”).

Gráfico mostrando "sucesso" em função de "tempo" com retas indicando diferentes inclinações da imagem e períodos com crescimento baixo e negativo

No entanto, chegamos a um momento que, apesar de ainda estar em crescimento, o faz mais lentamente (em “crescimento positivo, mas menor”); apesar de ainda estar crescendo, passou a fazer isso mais devagar. Este é o primeiro ponto que devemos considerar contratar consultores para tentar descobrir a causa deste comportamento diferente do histórico. Nesse ponto você já terá conhecimento prévio para aprender conceitos já adaptados ao seu modelo de negócio. Assim, conseguirá tirar muito mais proveito do que essas pessoas têm pra te passar e entenderá melhor a causa da diminuição. Isso poderá ser reaplicado em outros períodos, já que mesmo sob causas diferentes, você terá melhorado sua habilidade analítica e tem bom conhecimento dos problemas e soluções já utilizados.

Mas o momento decisivo para acelerar a startup é um decrescimento (mais à direita no gráfico, sinalizado pelo “crescimento negativo”). Apesar de possuir experiência e competência para fazer o negócio dar certo o suficiente para se manter no mercado a tempo de ter diferentes fases de crescimento, o “sucesso” tem diminuído e você não consegue mais enxergar formas com boas chances de reverter a situação. Uma aceleradora correta será uma ótima aliada para descobrir os motivos dessa mudança e aconselhar formas de subir consideravelmente o patamar da empresa. Nela, você encontrará outros empreendedores que tiveram as mesmas dificuldades e souberam enxergar soluções, conhecerá investidores que ajudarão em marketing e contratação de gente qualificada e ter um ambiente físico onde cada startup está diariamente tentando crescer e aproveitar o mercado que se inserem.