O que você não sabia sobre Funções: o coração da Programação Funcional
Summary
TLDRProfessor Manuel Campos introduces functional programming concepts in this educational video, focusing on pure functions, side effects, and immutability. He explains the importance of pure functions in maintaining a program's state without causing side effects, emphasizing immutability as a key starting point. Campos also discusses the principles of SOLID, particularly the Single Responsibility Principle (SRP), and introduces the idea of referential transparency, which ensures predictability in code. The video further explores higher-order functions, their role in abstraction and reducing coupling, and concludes by highlighting the benefits of functional programming in producing higher quality software with fewer bugs and easier maintenance.
Takeaways
- 😀 The core of functional programming is functions, which are explored in-depth in this lesson.
- 🔍 Pure functions are discussed, defined as functions that do not cause side effects, such as altering objects, files, or databases.
- 📚 Immutability is introduced as a foundational concept for creating pure functions, emphasizing that variables should not be altered.
- 🤔 Side effects are explained with examples, including changing object attributes, file operations, and database interactions.
- 📝 The importance of separating pure functions from impure ones is highlighted, adhering to the Single Responsibility Principle (SRP).
- 🔗 The concept of referential transparency is introduced, where a function's output is predictable and consistent for the same inputs.
- 📉 Functions with referential transparency are contrasted with those without, emphasizing the benefits of clarity, simplicity, and reliability.
- 🔄 The principle of least astonishment is mentioned, advocating for code that behaves as expected to minimize surprises.
- 🔀 High-order functions are introduced, which can take other functions as arguments or return them, enhancing abstraction and reusability.
- 🔧 The benefits of reducing coupling in software engineering are discussed, showing how high-order functions can achieve this.
Q & A
What is the core concept of functional programming discussed in the script?
-The core concept discussed in the script is functions, which are considered the heart of functional programming. The lecture covers pure functions, side effects, immutability, and principles like SRP, which are foundational to functional programming.
What are pure functions and why are they important?
-Pure functions are functions that do not cause side effects. They are important because they make the code more predictable, testable, and easier to maintain, as they always return the same result given the same inputs and do not alter any external state.
What is a side effect in the context of programming?
-A side effect in programming refers to any change in the state of an object, a variable, or the environment outside the program, such as modifying an object's attribute, saving or deleting a file, or inserting a record in a database.
How does immutability relate to pure functions?
-Immutability is a starting point for creating pure functions. If all variables are immutable, the function can only perform calculations and return results without altering any state, which is a characteristic of pure functions.
What does the script mean by separating pure functions from impure ones?
-Separating pure functions from impure ones means keeping the code that performs calculations or transformations (pure) separate from the code that interacts with external systems or states (impure), like databases or files. This separation follows the Single Responsibility Principle (SRP) and improves code maintainability.
What is the Single Responsibility Principle (SRP) and how does it apply to functional programming?
-The Single Responsibility Principle (SRP) is a software design principle that states a class or module should have only one reason to change. In functional programming, it applies by ensuring that functions have a single purpose, such as calculating a result, separate from functions that handle side effects like data storage.
What is referential transparency and why is it significant in functional programming?
-Referential transparency is a concept in functional programming where a function or expression can be replaced with its result without changing the program's behavior. It is significant because it ensures predictability and reliability, making the code easier to understand, test, and debug.
How do pure functions inherently possess referential transparency?
-Pure functions possess referential transparency because they do not cause side effects, do not alter any external state, and always return the same result for the same inputs. This consistency allows their results to be predicted and used interchangeably without affecting the program's outcome.
What are first-class functions and how do they contribute to functional programming?
-First-class functions are functions that are treated like any other value in the programming language. They can be stored in variables, passed as arguments, and returned from other functions. In functional programming, first-class functions contribute to higher-order functions, which increase abstraction and flexibility in code.
What are higher-order functions and how do they enhance abstraction in code?
-Higher-order functions are functions that can take other functions as arguments or return them as results. They enhance abstraction by allowing developers to write more generic and flexible code. This approach reduces coupling and increases the reusability of code, as functions like Filter, Map, and Reduce can operate on different data and conditions without modification.
How does the script suggest using functional programming to improve software quality?
-The script suggests that by using functional programming principles and practices, such as creating pure functions and using higher-order functions, developers can produce higher quality software that is less prone to bugs and easier to maintain.
Outlines
💡 Introduction to Functional Programming Concepts
Professor Manuel Campos introduces the core concepts of functional programming, emphasizing the importance of functions as the heart of this paradigm. He discusses pure functions, side effects, immutability, and the first principle of a set of principles known as SOLID. The lecture aims to clarify what pure functions are, explaining that they do not cause side effects, which are any changes to the state of an object, variable, or external environment. Examples of side effects include altering object attributes, file operations, and database transactions. The professor highlights the necessity of separating pure functions, which perform calculations, from impure functions that handle side effects, adhering to the principle of separation of concerns (SoC).
🔍 Deep Dive into Referential Transparency
The concept of referential transparency is explored, which means a function or expression can be replaced with its resulting value without changing the program's behavior. This concept ensures predictability and reliability in code, simplifying testing and maintenance. Functions with referential transparency always return the same result for the same input and do not modify external environments or variables. Examples of functions with and without referential transparency are given, such as a simple addition function versus a function that retrieves the current date and time. The latter's output varies with each call, making it less predictable.
🛠️ The Benefits of Pure Functions and First-Class Functions
Pure functions are inherently referentially transparent, as they do not cause side effects, modify variables, or interact with external states like files or databases. The video explains that even if a function receives mutable parameters, it should not alter them to maintain purity. In functional programming languages, functions are treated as first-class citizens, meaning they can be stored in variables, passed as arguments, and returned from other functions. This feature enhances the language's flexibility and power, allowing for higher-order functions that can manipulate other functions.
🌟 High-Order Functions and Reducing Code Coupling
High-order functions, which can take other functions as parameters or return them, are introduced. These functions provide a higher level of abstraction and flexibility, allowing for code that is less coupled and more maintainable. The video uses the example of summing numbers to illustrate how high-order functions like Filter, Map, and Reduce can be used to perform operations on data with minimal code changes. The professor emphasizes that by using high-order functions, developers can write more generic and reusable code, adhering to the principles of software engineering that aim to reduce coupling and increase abstraction.
🚀 Conclusion and Encouragement to Practice Functional Programming
The video concludes by emphasizing that functional programming is about producing higher quality software through good programming practices. The professor encourages viewers to apply functional programming concepts in their code as much as possible and to look forward to more practical lessons in upcoming videos. He invites viewers to like the video, subscribe to the channel, and ask questions in the comments if they have any doubts.
Mindmap
Keywords
💡Functional Programming
💡Pure Functions
💡Side Effects
💡Immutability
💡SOLID Principles
💡First-Class Functions
💡Higher-Order Functions
💡Referential Transparency
💡Separation of Concerns
💡Principle of Least Astonishment
💡Abstraction
💡Coupling
Highlights
Introduction to functional programming concepts by Professor Manuel Campos.
Definition of pure functions and their lack of side effects.
Explanation of side effects in programming, such as altering object attributes or database states.
The importance of immutability as a foundation for creating pure functions.
Discussion on the need for side effects and how to separate them from pure functions.
Introduction to the Single Responsibility Principle (SRP) and its role in software engineering.
Explanation of Referential Transparency and its significance in functional programming.
Examples of functions with referential transparency and their predictability.
The benefits of referential transparency for code clarity, simplicity, and testability.
Introduction to the Principle of Least Astonishment in software engineering.
Examples of functions without referential transparency, such as those that modify files or generate random numbers.
The inherent immutability of pure functions and their automatic referential transparency.
Introduction to First-Class Functions and their treatment as values in functional languages.
Definition and examples of Higher-Order Functions that can take other functions as parameters or return functions.
The role of Higher-Order Functions in increasing abstraction and reducing coupling in code.
Practical example demonstrating the use of Filter, Map, and Reduce functions for abstraction and reusability.
Final thoughts on the goal of functional programming to produce higher quality software with good practices.
Transcripts
Olá pessoal aqui é o professor Manuel
Campos e vamos lá para mais uma aula do
nosso curso de programação funcional
essa aula você vai ver o que não sabia
sobre funções que é o coração da
programação funcional a gente vai
abordar o que são funções puras efeito
colateral ou Side Effects funções puras
e imutabilidade que a gente viu em aulas
anteriores srp que é o primeiro de um
conjunto de princípios chamados Sid que
você já deve ter ouvido falar
transparência referencial funções de
primeira classe funções de alta ordem e
por fim abstração e acoplamento Então
vamos lá vamos começar falando que são
funções puras uma função pura é aquela
que não causa efeito colateral E aí você
pode estar se perguntando o que é efeito
colateral em funções em programação
efeito colateral Side effect em inglês é
qualquer alteração no estado de um
objeto uma variável de um programa ou do
ambiente externo a esse programa então
alguns exemplos de efeitos col altera
são alterar um atributo de um objeto
salvar ou excluir um arquivo inserir um
registro no banco de dados que também é
uma alteração você tá modificando ali o
estado daquela tabela Onde você tá
inserindo ou lançar uma exceção por
exemplo ao tentar acessar um banco de
dados Você tem uma função que faz acesso
ao banco que faz leitura de dados do
banco a gente sabe que esse tipo de
função pode gerar exceções por quê
porque o banco de dados pode estar fora
do ar pode estar sobrecarregado e não
conseguiu responder e você vai receber
uma exceção de volta dizendo que não foi
possível acessar o banco Se todas as
variáveis que você tem são imutáveis são
totalmente imutáveis apenas o lançamento
de exceções que a gente viu
anteriormente ou alterações que a função
Faça no ambiente é que podem tornar essa
função impura então imutabilidade é o
ponto de partida pra gente conseguir
criar esse tipo de função mas como a
gente viu nas aulas anteriores não tem
como em determinados momentos eu vou
precisar alterar alguma variável e com
efeitos colaterais é a mesma coisa a
gente precisa lançar exceções a gente
precisa fazer alterações em bancos de
dados em arquivos A questão é que quando
eu precisar criar efeitos colaterais eu
tenho que separar esse código de dentro
das minhas funções Então imagina que
você tem que realizar uma série de
cálculos e depois salvar o resultado
desses cálculos no banco de dados os
cálculos eles devem ser funções puras
que vão lá e fazem apenas isso e te
Retornam um resultado sem alterar nada e
você teria uma outra função que vai
pegar o resultado dessa função anterior
e ela sim salvar no banco de dados essa
última função ela seria uma função
impura pelo fato de estar alterando um
ambiente externo que é o nosso banco
além da possibilidade dessa função gerar
exceções se ela não conseguir por
exemplo acessar o banco ou se os dados
que você tiver tentando inserir no banco
sejam dados Inválidos então quando a
gente separa as funções puras de impuras
a gente a gente passa a seguir dois
princípios O primeiro é o separation of
concerns conhecido como sock que é a
separação de preocupações é você Separar
coisas distintas fazer cálculo é uma
coisa salvar dados no banco de dados é
outra coisa completamente diferente
então se são coisas distintas esse
código ele precisa estar separado isso
vai inclusive facilitar o entendimento e
a manutenção do código se você tem uma
função que a única coisa que ela faz é
realizar somas Toda vez que você
precisar realizar uma soma você pode
recorrer a essa função o srp é o s num
conjunto de princípios que a gente chama
de Solid você já deve ter ouvido falar
de Solid pois esse é um conjunto de
princípios bastante famoso e muito útil
se você tiver interesse no assunto tem
uma playlist inteira aqui no canal sobre
padrões de projetos onde eu apresento em
detalhes cada um desses princípios mas
como Solid é um assunto de extrema
importância pra engenharia de software
caso você queira entender mais sobre
esses princípios Eu sugiro esse artigo
chamado os princípios Sid em imagens ele
é um artigo sensacional e é um excelente
ponto de partida para você poder
entender como que cada um desses
princípios funciona e eu vou deixar o
link desse artigo na descrição do vídeo
vamos avançar e agora a gente vai falar
um pouco sobre transparência referencial
o que que é isso é um conceito de
programação funcional que diz que uma
função ou uma expressão ela tem
transparência referencial se em todos os
locais que você tiver usando essa função
ou essa expressão se você tirar a
expressão e colocar o resultado dela no
lugar você não vai alterar o
funcionamento do código Você vai
continuar tendo o mesmo resultado que
você tinha anteriormente vamos lá
entender isso melhor primeiro o porqu
desse termo transparência referencial
algo Transparente é algo que a gente não
percebe a ideia de que toda vez que você
tiver tiver fazendo referência a essa
função você consegue perceber ou
calcular Qual que é o valor que ela
retorna sem ter nenhuma surpresa a gente
vai ter transparência referencial para
uma função ou uma expressão se quando eu
passar um conjunto de valores Ela sempre
me retorne o mesmo resultado então se eu
usar essa função ou essa expressão que é
o que a gente chama de referenciar se eu
passar sempre o mesmo conjunto de
valores o resultado tem que ser o mesmo
para que conjunto É nesse sentido que eu
tô falando que a gente não deveria ter
surpresas ao receber um retorno dessa
função ou dessa expressão Então vamos lá
para alguns exemplos de funções com
transparência referencial aqui eu tenho
uma função soma que ela recebe dois
valores e a única coisa que ela faz é
somar esses dois valores e devolver o
resultado sem fazer nenhuma alteração
então ela não modifica as variáveis que
foram recebidas ela não depende de
ambiente externo como arquivos ou bancos
de de dados e ela também não gera
exceções a segunda função tem as mesmas
propriedades ela vai verificar se uma
pessoa é maior de idade ela também não
altera essa variável que foi recebida no
caso dessa função soma se eu passar os
valores 10 e 2 ela sempre tem que
retornar 12 não interessa quantas vezes
eu faço a referência a essa função com
esses valores o resultado sempre tem que
ser 12 se os parâmetros são os mesmos o
resultado sempre tem que ser o mes mesmo
isso quer dizer que no lugar da chamada
da função da referência da função Se eu
colocar o valor fixo direto o valor que
a função retornaria eu vou ter o mesmo
resultado final Então a primeira linha e
a segunda linha vão ter o mesmo
resultado porque a minha função soma ela
tem transparência referencial então a
transparência referencial ela Visa
garantir clareza simplicidade
previsibilidade e confiabilidade do do
teu código e facilidade para criar
testes porque o código ele é mais
simples uma vez que você não tá
alterando variáveis você não tá fazendo
modificações em arquivos em nada disso
você não tá gerando exceção então o teu
código ele é mais claro e por
consequência ele é mais simples é um
código mais suscinto é um código mais
fácil de você entender uma coisa leva a
outra previsibilidade confiabilidade
porque você sabe que se você informar 10
e 2 o resultado sempre vai ser 12 você
não tem a possibilidade de uma hora você
informar esses valores e ele te retornar
12 e outra hora por exemplo ele te
devolver uma exceção porque ele tentou
acessar um arquivo e o arquivo não
existia por fim se a função é mais
simples se ela não altera estado se ela
não salva dados em arquivo se ela não
altera dados em um banco de dados ou faz
acesso a um banco de dados a gente tem
menos cenários para testar e como essas
funç são mais simples e previsíveis a
gente acaba atendendo a outro princípio
que é o principle of list astonishment
que a gente vai ver a sigla pola é o
princípio do menor espanto ou da menor
surpresa Esse é um princípio de
engenharia de software que é apresentado
em alguns livros como código limpo e diz
que você deve fazer as coisas da forma
que é o mais esperado Então vamos ver
exemplos de funções sem transparência
Essas são funções que podem retornar um
valor diferente a cada vez que são
chamados ou são que lançam exceções ou
que fazem alterações em arquivos em
banco de dados que causam mutabilidade e
aqui a gente tem exemplos clássicos Você
tem uma função que obtém a data e ou a
hora cada vez que você chamar essa
função ela pode te devolver um valor
diferente nesse primeiro exemplo aí é
uma função que te devolve a data e a
hora atual Possivelmente se você chamar
essa função várias vezes cada vez que
você chamar você vai ter um resultado
diferente por mais você saiba que esse é
o comportamento da função o resultado de
fato é meio imprevisível você chamar a
função agora e não olhar no relógio você
não sabe qual valor exato ela vai te
devolver da mesma forma funções que
geram números aleatórios nesse caso aqui
também é uma função em Java ela na
verdade como na grande maioria das
linguagens ela vai te gerar um número
pseudo aleatório e ele é chamado assim
porque existe um cálculo por trás da
geração desses números cada vez que eu
chamar a função ela pode me devolver um
valor diferente e aí por último a gente
tem uma função de salvar um arquivo que
poderia ser também incluir um um
registro no banco de dados Essas funções
elas modificam o estado porque ela vai
modificar o arquivo ou o banco você pode
chamar a função salvar passando o nome
de um arquivo e num momento ela salvar e
talvez daqui a pouco você chama a função
de novo para salvar no mesmo arquivo e
ela dá erro o parâmetro foi o mesmo só
que o arquivo pode ter sido excluído e
por por acaso a função não recria o
arquivo caso ele não exista Então você
não tem a garantia de que a função
sempre vai funcionar da mesma forma com
os mesmos valores de parâmetros mas
Essas funções elas não tão erradas a
gente precisa desse tipo de função só
que elas não vão garantir os benefícios
que a gente falou anteriormente de
simplicidade previsibilidade esse tipo
de coisa a boa notícia é que funções
puras elas já têm transparência
referencial por quê elas não causam um
efeito colateral elas não geram exceções
elas não alteram variáveis não alteram
arquivos nem banco de dados segundo que
imutabilidade é regra a nossa função ela
pode receber uma série de variáveis de
parâmetros que são imutáveis e assim ela
não vai conseguir alterar nem que ela
quisesse só que ela também pode receber
como a gente viu nas aulas anteriores
parâmetros mutáveis E assim se ela
quisesse ela conseguiria alterar esses
parâmetros então mesmo que que tua
função receba uma variável que é mutável
você sabe que você deve evitar alterar
essas variáveis e se sua função é
realmente pura ela vai ter transparência
referencial E com isso eu poderia trocar
a chamada dessa função pelo valor que
ela retorna que eu não vou alterar o
resultado final em linguagens não
funcionais que seriam linguagens que não
t suporte a programação funcional
variáveis elas só armazenam valores você
pode declarar uma variável string para
armazenar um nome ou inteiro para
armazenar uma idade ou Double para
armazenar o peso de uma pessoa então
tudo que você armazena em variáveis são
valores ou objeto que vai ter um
conjunto de valores mas em linguagens
funcionais a gente tem um conceito de
funções de primeira classe ou First
Class functions nessas linguagens
funções passam a ter os mesmos
privilégios que valores têm você pode
armazenar funções em variáveis ou
constantes mesma forma que você armazena
valores função é tratada como um valor
ele é apenas um objeto do tipo function
ou variantes como a gente tem em
linguagens tipadas como Java Mas isso é
assunto para uma próxima aula em
linguagens funcionais tudo que você pode
fazer com um valor você pode fazer com
uma função por exemplo você pode
declarar uma variável para armazenar uma
função passar uma função por parâmetro
para outra função ou fazer uma função
retornar outra esses dois últimos pontos
é o que há de mais útil em programação
funcional isso a gente também vai ver na
prática nas aulas seguintes bom então
chegamos às funções de alta ordem ou
High Order functions Essas são funções
que têm as duas últimas características
que eu acabei de mostrar é uma função
que pode receber outras funções como
parâmetro ou retornar funções que a
gente tá habituado em programação
estruturada e orientada ao objeto é
fazer as nossas funções receberem e
retornarem valores então aqui em
programação funcional a gente tem uma
nova possibilidade que é receber e
retornar outras funções e isso vai nos
trazer um maior nível de abstração
abstração é um conceito lá de
programação orientada a objetos com
código mais abstrato ele é mais genérico
mais flexível vamos pegar aquele exemplo
de soma de números que a gente viu na
primeira aula e o que esse código faz é
realizar a soma do dobro dos números
pares como a gente já sabe o que Filter
map e reduce recebem são funções por que
que eu tenho abstração aqui porque o
Filter ele vai simplesmente filtrar os
dados mas ele não sabe como quem diz o
como somos nós no momento de usar o
Filter Então quando você passa uma
função por parâmetro paraa outra você
tem esse maior nível de abstração por
isso porque a função que você tá
chamando o Filter por exemplo ele
internamente ele não tem implementado a
forma de obter um número par o Filter
ele é uma função reutilizável
absurdamente flexível Assim como as
outras map reduce justamente porque ela
recebe uma função um comportamento por
parâmetro eu que digo pro Filter como
que eu quero que ele filtre os dados que
eu tenho se isso não ficou totalmente
claro como modificar esse exemplo agora
eu quero a soma do triplo dos números
positivos para o vídeo por um instante e
percebe o que que foi que mudou nesse
código viu que a estrutura é a mesma eu
tenho Filter o map e o reduce o reduce
inclusive não mudou absolutamente nada
eu só tive que mudar Qual foi a função
que eu passo pro Filter e qual a função
que eu passo pro map então Essas funções
Filter map e reduce elas são altamente
reutilizáveis com isso além da gente ter
um maior nível de abstração Eu tenho um
menor acoplamento acoplamento é o nível
de dependência abstração a gente
normalmente quer aumentar e o
acoplamento eu quero reduzir Esses são
dois princípios de engenharia de
software muito importantes então quanto
mais acoplado o meu código tiver quer
dizer dizer que mais dependente ele é de
determinadas coisas por exemplo se você
tá usando um serviço de pagamento como
PayPal no seu código você escreveu todo
o código para fazer acesso direto a API
de pagamento do PayPal Então você tem um
altíssimo acoplamento com o PayPal para
você trocar o serviço de pagamento por
qualquer outro você vai ter que mexer em
muito código com funções de alta ordem
que é essa possibilidade de eu passar
funções por parâmetro e retornar funções
a gente consegue reduzir esse
acoplamento Filter e map reduce Eles não
estão acoplados amarrados ali
dependentes de uma função específica a
única coisa que o Filter diz é que eu
tenho que passar para ele uma função que
recebe um valor e essa função tem que
retornar um bullan que é uma condição e
o que eu fiz aqui no Filter foi
exatamente isso eu tenho n que é o
parâmetro que é o valor que a função vai
receber dessa função que eu tô passando
pro Filter e depois da seta eu tenho n
maior do que z0 que é uma condição uma
condição tem um valor lógico Mas isso
não quer dizer que eu tô dependente
dessa função em que verifica se o número
é positivo a gente viu no slide anterior
que eu posso trocar essa função por
qualquer outra desde que eu siga essa
estrutura essa assinatura eu tenho que
receber um valor e devolver um bullan
isso é o que o Filter define as funções
seguintes map reduce cada uma vai
definir uma uma estrutura diferente o
map Eu recebo um valor e eu posso
devolver qualquer coisa que eu queira
então por isso que a gente tem um menor
acoplamento um menor nível de
dependência quando a gente passa funções
por parâmetro para outras funções a
gente tem funções de alta ordem então
para finalizar eu quero que vocês tenham
em mente uma coisa programação funcional
É principalmente sobre produzir software
de maior qualidade usando boas práticas
de programação e engenharia de software
e assim a gente vai conseguir construir
software de mais qualidade com menos
bugs e com muito maior facilidade de
manutenção Então por esse vídeo é isso
eu espero que vocês tenham gostado não
deixem de acompanhar as próximas aulas a
gente vai começar com a parte mais
prática se gostou não esquece de deixar
o seu like e se inscrever no canal se
ainda não é inscrito e qualquer dúvida
posta nos comentários me diz aí você vai
começar a usar programação funcional nos
seus códigos o máximo que você puder até
mais até o próximo vídeo
Посмотреть больше похожих видео
The purest coding style, where bugs are near impossible
COS 333: Chapter 15, Part 1
Rules for Render Logic: Pure Components | Lecture 131 | React.JS 🔥
Low Level Design 105 | Single Responsibility Principle in SOLID | 2022 | System Design
COS 333: Chapter 15, Part 3
FIRST CLASS FUNCTIONS 🔥ft. Anonymous Functions | Namaste JavaScript Ep. 13
5.0 / 5 (0 votes)