https://a.storyblok.com/f/270183/65366/5a832fba53/multi-language-team-1.png

Trabalhando em uma equipe multilíngue

Publicado em March 17, 2022

Tempo de leitura: 8 minutos

Na maioria das vezes, como desenvolvedores que trabalham em equipe, estamos acostumados a que todos os membros dessa equipe estejam familiarizados com as mesmas linguagens, a mesma pilha de tecnologias e o mesmo conjunto de ferramentas. Dependendo do contexto, isso pode envolver o uso de mais de uma linguagem de programação propriamente dita.

Se você estiver trabalhando com front-end, provavelmente precisará “dominar” HTML, CSS e JavaScript. Em um contexto full-stack, você também pode incluir uma das diversas linguagens de programação de back-end. Deixando de lado qualquer especialização ou foco em uma parte específica da pilha, os desenvolvedores dessa equipe terão um vocabulário técnico comum e um referencial compartilhado, definido pela pilha de tecnologias que estão utilizando. No entanto, desde que entrei para a equipe de Relações com Desenvolvedores da Vonage, tive que me acostumar com uma realidade bem diferente daquela que acabei de descrever.

Só para contextualizar, um dos principais objetivos da nossa equipe é ajudar e dar suporte aos desenvolvedores no uso das diversas APIs de comunicação da Vonage. Uma das maneiras de fazermos isso é fornecer SDKs que simplificam parte da complexidade de baixo nível do uso das APIs, facilitando sua integração em um aplicativo. É claro que os desenvolvedores que utilizam as APIs da Vonage o fazem usando uma ampla variedade de linguagens de programação e pilhas de tecnologia. Por isso, fornecemos SDKs para diversas implementações de linguagens e ambientes: SDKs de servidor para Ruby, PHP, Python, Java, Node e .NET; SDKs de cliente para JavaScript, iOS e Android.

Como Ruby Developer Advocate da equipe, parte das minhas funções envolve manter e aprimorar nossos SDKs de Ruby. Quando preciso corrigir um bug ou adicionar um recurso, faço isso escrevendo código em Ruby. Meus colegas de equipe, no entanto, não estão escrevendo Ruby. Em vez disso, estão escrevendo PHP, Python ou C#. Podemos, na verdade, estar trabalhando na implementação do mesmo recurso, mas fazendo isso em linguagens completamente diferentes.

Bem, gosto de pensar que meus conhecimentos de JavaScript são bastante bons, mas não é minha linguagem principal. Já escrevi um pouco de PHP no passado (embora nosso especialista em PHP, Jim, me garanta que a linguagem mudou bastante desde aquela época!) e sei um pouco de Python, mas não me considero especialista em nenhuma dessas linguagens, e definitivamente me sinto mais à vontade trabalhando com código Ruby.

No entanto, se eu quiser ser um bom membro da equipe e poder apoiar meus colegas no trabalho, preciso, de vez em quando, sair da minha zona de conforto no Ruby.

Durante os cerca de sete meses desde que entrei para a equipe, acabei atuando como alguém a quem os colegas podem recorrer para trocar ideias ou como um segundo par de olhos para aqueles que trabalham com bugs ou novos recursos em seus SDKs (que não são em Ruby). Ajudei a revisar pull requests para as bibliotecas de PHP, Python e .NET. Cheguei até a enviar alguns pequenos commits para um dos repositórios de Python.

Na verdade, sentir-se desconfortável (às vezes) faz bem

Trabalhar em uma equipe multilíngue pode, sem dúvida, apresentar alguns desafios. No entanto, gostaria de sugerir que isso também traz muitos benefícios.

Como desenvolvedores, buscamos o domínio de nossa profissão. Desenvolvemos nossa expertise até um nível em que nos sentimos à vontade em um determinado domínio de conhecimento. Construir essa “zona de conforto do conhecimento” traz muitas vantagens — podemos trabalhar com confiança, rapidez e eficiência, sem precisar verificar duas vezes ou consultar informações o tempo todo. Por outro lado, isso pode nos tornar preguiçosos e propensos a suposições. Ao nos depararmos com um novo problema ou situação, às vezes podemos recorrer a padrões familiares e achar que já sabemos a solução sem refletir claramente sobre o problema.

Existe um conceito no budismo zen chamado Shoshin, que se traduz como “mente de principiante”. Essencialmente, refere-se à ideia de estar aberto às possibilidades e sem preconceitos ao estudar um tema ou abordar um novo problema. Adquirir conhecimento especializado afasta a “mente de principiante”, mas, ocasionalmente, sair da sua zona de conforto linguística pode ajudar a restabelecê-la.

Por exemplo, se estou trabalhando em um recurso para uma das bibliotecas do Ruby e pensando nisso em um contexto puramente do Ruby, posso cair no mau hábito de me concentrar exclusivamente na solução e não refletir com clareza sobre o problema. Se, no entanto, eu estiver discutindo esse mesmo recurso com colegas no contexto do PHP ou do Python, isso me obriga a abandonar quaisquer suposições específicas do Ruby sobre a solução e, em vez disso, concentrar-me no problema.

Além de eliminar preconceitos, trabalhar no dia a dia com desenvolvedores que vêm de outras linguagens de programação pode ampliar seus horizontes de outras maneiras. Isso permite que você se abra para diferentes abordagens e formas de fazer as coisas e, em última análise, para diferentes formas de pensar.

Existe uma teoria linguística conhecida como relatividade linguística ou hipótese de Sapir-Whorf. Essa teoria sugere que a estrutura de uma língua pode influenciar a maneira como pensamos e como vemos o mundo. A teoria foi desenvolvida tendo em mente as línguas humanas, e não as linguagens de programação. No entanto, como as linguagens de programação são criadas por seres humanos, a mesma teoria pode ser aplicada.

O design das linguagens de programação pode criar certas convenções sobre como o software deve ser escrito. As linguagens podem ser de tipagem forte ou fraca. Algumas linguagens se prestam a uma abordagem imperativa, outras a uma abordagem declarativa. Recursos da linguagem como esses podem fazer com que você pense de uma determinada maneira ao escrever código.

Se uma determinada maneira de pensar é a única que você já conheceu, você pode cair na armadilha de acreditar que essa é a maneira certa. Experimentar diferentes linguagens e abordagens abre sua mente para as diversas formas de pensar sugeridas pela estrutura dessas linguagens. Isso pode mostrar que não existe necessariamente uma única maneira “certa”, mas sim diferentes “maneiras”, cada uma com suas próprias vantagens e desvantagens.

Por exemplo, embora o Ruby sempre tenha sido (e ainda seja, por padrão) uma linguagem de tipagem dinâmica, agora temos a opção de introduzir a verificação estática de tipos em nossos programas em Ruby. Bibliotecas como o Sorbet já existem há alguns anos e, mais recentemente, o Ruby 3 introduziu essa opção de forma nativa. Pensar de maneira estaticamente tipada provavelmente ainda pareça um pouco estranho para a maioria dos desenvolvedores de Ruby, e podemos aprender muito analisando o código de uma linguagem estaticamente tipada, como o C#.

private static void ValidSmsResponse(SendSmsResponse smsResponse)

Ao analisar a assinatura de um método em uma linguagem desconhecida como essa, não temos nenhuma ideia prévia sobre a linguagem. Para entender o que o código está fazendo, precisamos nos perguntar para que cada elemento da assinatura significa e por que foi escrito dessa forma. Podemos aprender com esse processo e aplicar esse aprendizado ao nosso código em Ruby.

Pontos de aprendizagem e dicas

Nos últimos meses, aprendi algumas estratégias úteis para trabalhar em uma equipe multilíngue e gostaria de compartilhar algumas delas aqui.

Ampliar a visão para estabelecer o contexto

Há alguns meses, Jim estava trabalhando na desativação e remoção de vários Traits de uma das bibliotecas PHP e queria alguém com quem pudesse discutir as mudanças que estava fazendo na base de código. No início da nossa conversa, eu estava meio perdido nos meandros da sintaxe específica do PHP. O que realmente ajudou naquela situação foi dar um passo atrás e discutir as mudanças em um nível mais abstrato. Em vez de pensar no que uma linha específica de código estava fazendo, ficou mais fácil entender o contexto das mudanças fazendo perguntas como “qual é o objetivo desse Trait?”, “qual é a relação entre essas classes?” e assim por diante. Depois de estabelecer um contexto claro para o que um código desconhecido está fazendo, fica muito mais fácil voltar a se concentrar nos detalhes da implementação.

Reutilizar modelos mentais

Outra coisa que pode ser útil ao nos aventurarmos em território desconhecido é reutilizar ou adaptar modelos mentais já existentes. Ao longo de nossa trajetória de aprendizado como programadores, todos nós dedicamos muito tempo a construir modelos mentais sólidos para os inúmeros Concepts técnicos com os quais trabalhamos. A boa notícia é que muitos deles podem ser reutilizados ou adaptados para outros contextos, como em outras linguagens de programação.

Um exemplo seria tentar explicar algo como os blocos do Ruby para um desenvolvedor que não conhece Ruby. Sintaticamente, os blocos são bastante específicos da linguagem Ruby, mas se eu precisar explicar o que são para, digamos, um desenvolvedor de JavaScript, posso dizer algo como “eles funcionam mais ou menos como funções de retorno de chamada”. Claro, se você se aprofundar nos detalhes da implementação da linguagem, verá que não são exatamente a mesma coisa, mas, como modelo mental geral para explicar o que eles fazem e como são usados, essa comparação provavelmente é bastante adequada.

Conceitualmente, passar um bloco para map no Ruby:

[1, 2, 3].map do |num|
  num + 1
end

na verdade, não é tão diferente de passar uma função de retorno de chamada para map no JavaScript:

[1, 2, 3].map(function(num) {
  return num + 1;
});

Dependendo das nossas escolhas sintáticas em ambas as línguas, elas podem até parecer bastante semelhantes:

# Ruby
[1, 2, 3].map { |num| num + 1 }
// JavaScript
[1, 2, 3].map(num => num + 1)

Identificar semelhanças para compreender as diferenças

Continuando com esse tema, outra coisa a se fazer é buscar as semelhanças entre diferentes linguagens e pilhas de tecnologia. Mencionei anteriormente as vantagens que podem advir de explorar e estar aberto às diferentes abordagens que as linguagens de programação podem adotar. No fim das contas, porém, essas linguagens — e as ferramentas desenvolvidas em torno delas — geralmente têm como objetivo resolver o mesmo conjunto de problemas.

Por exemplo, existem bibliotecas de testes disponíveis para a maioria das linguagens de programação. A sintaxe que elas utilizam varia de linguagem para linguagem; algumas, como o RSpec, podem até mesmo usar sua própria DSL. No entanto, em última análise, todas as bibliotecas de testes resolvem o mesmo problema. De maneira geral, todas elas utilizam asserções de alguma forma.

O Minitest e o PyTest são bibliotecas de testes, uma para Ruby e a outra para Python. Identificar as semelhanças entre elas pode fornecer um contexto básico que, por sua vez, pode ajudar a destacar as diferenças interessantes na forma como funcionam ou como foram implementadas.

Um mundo além do Ruby

Acho que o que estou tentando dizer com tudo isso é que, embora possa ser tentador simplesmente ficar na sua zona de conforto e se limitar ao que você está acostumado, o que vivi nos últimos meses me lembrou que existe um mundo inteiro de coisas vibrantes e interessantes acontecendo em outras linguagens além do Ruby. Adoro Ruby e, certamente, não tenho planos de deixá-la de lado como minha linguagem principal, mas estou super animado para mergulhar e explorar ainda mais algumas dessas outras linguagens.

Compartilhar:

https://a.storyblok.com/f/270183/373x376/e8d3211236/karl-lingiah.png
Karl LingiahDefensor da Comunidade de Desenvolvedores Ruby

Karl é um Developer Advocate da Vonage, com foco na manutenção de nossos SDKs de servidor em Ruby e na melhoria da experiência dos desenvolvedores da nossa comunidade. Ele adora aprender, criar coisas, compartilhar conhecimento e tudo o que esteja relacionado à tecnologia da web em geral.