O documento discute as abordagens funcionais para programação orientada a objetos. Apresenta as diferenças entre os paradigmas funcional e orientado a objetos e argumenta que a programação funcional é mais adequada para descrever processos e cálculos, enquanto a orientação a objetos é melhor para descrever estados. Também fornece exemplos de como usar F# para implementar injeção de dependência.
2. Porque programação funcional?
É mais divertido?
Quer tirar onda?
Virou “modinha”?
Não é algo mais acadêmico?
Resolve mesmo os problemas da OO?
Aumenta a produtividade?
Me mostra uma aplicação real usando isso?
3. Por que programação funcional?
É mais divertido? Sim!
Quer “tirar onda”? Claro! Porque não? :D (falando sério, não)
Virou “modinha”? Ainda não. Tem tido um aumento de popularidade por alguns
motivos.
Não é algo mais acadêmico? Permeia o acadêmico (assim como orientação
a objeto?) e atende muito bem o cenários reais corporativos.
Resolve os problemas da OO? Usa uma abordagem diferente, que simpatiza
mais com processos e cálculos.
Aumenta a produtividade? Uma vez imerso no paradigma, sim.
Me mostra uma aplicação real usando isso? Sim senhor!
4. O que é programação funcional?
Paradigma de programação
Computação como avaliação de funções matemáticas
Evita estados ou dados mutáveis
5. Abordagem orientada a objeto
Dados e operações fortemente acoplados
Objetos abstraem suas operações por meio de interfaces
O centro das operações são os dados, o valor de um termo
não é determinado pela entrada (stateful)
A atividade central é compor novos objetos e extender objetos
existentes adicionando novas operações à eles
6. Abordagem funcional
Dados fracamente acoplados à funções
Abstrações são feitas por meio de funções e combinação de
funções
O centro da abstração é a função, o valor de um termo é
sempre determinado pela entrada (stateless)
A atividade central é escrever novas funções
7. Voltando à pergunta inicial
Programação OO cresceu a partir da programação de
interfaces, e sua força está na descrição de estados
Botões, caixas de texto, plugues, checkboxes
Decompõe o programa em objetos com estados e
capacidades, comportamentos
8. Voltando à pergunta inicial
Programação funcional é adepta à descrição de computações
e processos
Cresceu a partir do cálculo lambda (área da matemática
responsável por descrever como computar)
O ator central da peça são as ações, não os dados
9. Voltando à pergunta inicial
Programação funcional desencoraja stateful operations
Variáveis globais
Paralelismo
Side effects
Necessidade de reproduzir um bug para corrigi-lo
Wikipedia example
Qualquer pessoa pode alterar um conteúdo e colocar uma
informação falsa
10. Voltando à pergunta inicial
Programação funcional encoraja operation definitions
Defina claramente sua entrada (domínio)
Conheça a saída (imagem)
Todas as condições são claramente conhecidas
Livre de interferências externas
Validação precisa
Você pode ter assertividade completa, desde que seu processo seja
corretamente descrito
Se o seu código não vai mudar estados, você pode executar em
paralelo com risco menor
11. Voltando à pergunta inicial
Orientação a objeto é melhor para descrever estados
Paradigma funcional é melhor para descrever processos e
cálculos
Concorrência, paralelismo e regras de negócio complexas tem tido
mais relevância para o desenvolvedor que o armazenamento e a
manipulação dos dados
Programação funcional parece mais adaptada às necessidades
modernas das aplicações corporativas
12. Alguns outros pontos interessantes
F# foi a escolha da Microsoft para criar um cenário funcional no
ecossistema .NET
Já faz muito tempo que o desenvolvimento da linguagem F# está
afetando a evolução da linguagem C#
Lambda expressions
Tuples
Pattern matching
Func<T>, Action<T> (function as data)
Generics (parametric polymorphism)
LINQ (list comprehensions)
Type inference (var)
System.Collections.Immutable
13. O que eu preciso para aprender?
Pensar funcionalmente
Gaste muito tempo no básico, é uma mudança de paradigma
Não ter medo, ter curiosidade (#vamoquerer)
É intimidante no início
F#: primariamente funcional, aceita orientação a objeto
Procure bons exemplos
Foque em aplicações empresariais
Divertir-se!
Aprender paradigma funcional “reinventa a sua mente”
Se você gostou muito de aprender a programar no passado, vai voltar a sentir isso
16. Características
• Primariamente funcional
• Aceita orientação a objetos quando necessário
• Está no ecossistema .NET
• Open source
• Cross-platform
Windows
Linux
Mac OS X
Android
iOS
GPU’s
Browsers
17. Tipos específicos
• Function values
• Tuples
• Records
• Discriminated unions
• Option types
• Lists
Prefira sempre estes tipos ao invés dos tipos da CLI
São imutáveis
Não podem ser nulos
São estruturalmente comparáveis
Pretty printing embutido
18. Outras features
• Type inference
• Baixo overhead para criar tipos
• Partial application
• Function as interface (interface segregation principle)
• Imutabilidade
• Actor model nativo (similar ao Akka.NET)
• Interoperabilidade com outras linguagens .NET
20. type UserId = int
type UserName = string
type EmailAddress = string
type UpdateProfileRequest = {
UserId : UserId
Name : UserName
EmailAddress : EmailAddress
}
21. type UserProfileUpdater() =
member this.UpdateCustomerProfile(json : string) =
try
let request = this.ParseRequest(json)
let currentEmail = DbService.GetEmail(request.UserId)
DbService.UpdateProfile(request.UserId, request.Name, request.EmailAddress)
Logger.Info("Updated Profile")
if currentEmail <> request.EmailAddress then
Logger.Info("Sending Email Changed Notification")
EmailService.SendEmailChangedNotification(currentEmail,request.EmailAddress)
with
| ex ->
Logger.Error(sprintf "UpdateCustomerProfile failed: '%s'" ex.Message)
22. type ILogger =
abstract Info : string -> unit
abstract Error : string -> unit
type IDbService =
abstract GetEmail : UserId -> EmailAddress
abstract UpdateProfile : UserId * UserName * EmailAddress -> unit
type IEmailService =
abstract SendEmailChangedNotification : EmailAddress * EmailAddress -> unit
23. type UserProfileUpdater
( dbService:IDbService,
emailService:IEmailService,
logger:ILogger ) =
member this.UpdateCustomerProfile(json : string) =
try
let request = this.ParseRequest(json)
let currentEmail = dbService.GetEmail(request.UserId)
dbService.UpdateProfile(request.UserId, request.Name, request.EmailAddress)
logger.Info("Updated Profile")
if currentEmail <> request.EmailAddress then
logger.Info("Sending Email Changed Notification")
emailService.SendEmailChangedNotification(currentEmail,request.EmailAddress)
with
| ex ->
logger.Error(sprintf "UpdateCustomerProfile failed: '%s'" ex.Message)
member this.ParseRequest(json:string) : UpdateProfileRequest =
...
24. type LogInfo = string -> unit
type LogError = string -> unit
type DbGetEmail = UserId -> EmailAddress
type DbUpdateProfile = UserId * UserName * EmailAddress -> unit
type Notify = EmailAddress * EmailAddress -> unit