Antecedentes: sou defensor da programação funcional que trabalha em uma loja do VB.NET em que o modelo mental predominante é a programação imperativa. Sendo a base do nosso sistema o WinForms, posso entender que não vamos nos afastar totalmente da programação imperativa, mas ainda tento usar o FP (principalmente via Linq) sempre que possível, porque acredito em seus méritos.
Argumentos e contra-argumentos contra FP
Pode-se notar que o Linq fluente é menos eficiente do que sua contraparte imperativa, pois esse estilo processa uma sequência em outra sequência e a repete. Geralmente, são necessárias mais algumas passagens do que a abordagem imperativa, que pode ser melhor otimizada para evitar repetições de passagens em uma sequência. Por esse motivo, o líder não conseguiu entender por que escolheria uma abordagem funcional claramente "menos eficiente".
- Contra-argumento : argumentei que, embora às vezes seja menos eficiente em termos de ciclos de CPU, senti que era mais humanamente inteligível e fácil de seguir, pois cada linha faz apenas uma coisa ao passar pela sequência. Para mim, é como ter uma linha de montagem em que cada pessoa em sua estação tenha apenas um trabalho a fazer. Eu sinto que a troca insignificante de eficiência é recompensada por código cujas preocupações são nitidamente separadas.
O próximo argumento contra o FP que ouvi na minha loja é que é mais difícil depurar - o que é verdade. Não é fácil passar por cima do código Linq. E às vezes tenho que desvendar uma cadeia de métodos para seguir e dissecar melhor os problemas que não consigo identificar imediatamente.
- _ Argumento do contador: Na maioria das vezes, embora eu não tenha problemas com isso, porque acho que o estilo funcional é mais declarativo na maneira como ele é lido e quando um erro é gerado dentro de uma cadeia funcional, geralmente consigo identificar o problema imediatamente.
Minha pergunta
Eu tenho tentado promover o estilo funcional em nossa loja e não sinto que estou fazendo progresso. Eu fiz os dois estilos de programação e só recentemente me envolvi com Haskell. Apesar de anos de experiência imperativa, agora que estou fazendo uso rotineiro de FP em JavaScript, ele cresceu em mim. Soa uma nota de retidão em meu âmago quando a comparo com o que eu poderia ter feito se seguisse um estilo imperativo. Eu treinei meu cérebro para o pensamento funcional, para a composição funcional.
O que não consigo entender é como tem sido difícil convencer outras pessoas dos méritos da FP.
Por exemplo, os desenvolvedores da minha loja usam o Linq, mas acho que eles geralmente o usam no contexto de lidar com dados do domínio. Eu o uso em um sentido mais geral e prefiro sempre que estou lidando com sequências / listas ou estruturas de dados persistentes. Não consegui convencer meus colegas de equipe a expandir o uso do Linq.
O que estou tentando entender é o que faz com que um desenvolvedor não goste de FP.
Gostaria de receber uma resposta de alguém que tenha muita experiência com a FP, mas tenha decidido a favor do estilo imperativo. O que levou a decisão de permanecer no imperativo em vez de usar o funcional?
Aqui está um exemplo adicional destacando as diferenças entre programação imperativa e funcional.
Eu escrevi o SelectedRows
método da nossa grade no Linq da seguinte forma:
Public Property SelectedRows() As DataRow() Implements IDataSourceControl.SelectedRows
Get
Return Me.ugrBase.Selected.Rows.
OfType(Of Infragistics.Win.UltraWinGrid.UltraGridRow)().
Select(Function(ugr) ugr.ListObject).
OfType(Of DataRowView)().
Select(Function(drv) drv.Row).
ToArray
End Get
No entanto, esse estilo de código deixa alguns de nossos desenvolvedores desconfortáveis e, portanto, nosso líder o reescreveu para o mais familiar:
Public Property SelectedRows() As DataRow() Implements IDataSourceControl.SelectedRows
Get
Dim plstRows As New List(Of DataRow)
For Each bugrLoop As Infragistics.Win.UltraWinGrid.UltraGridRow In Me.ugrBase.Selected.Rows
If bugrLoop.ListObject IsNot Nothing Then
plstRows.Add(CType(bugrLoop.ListObject, DataRowView).Row)
End If
Next
Return plstRows.ToArray()
End Get