Muito interessante. Obrigado. Poderia dar algum exemplo nesse contexto que mostrei no código?
Ambos os exemplos, seja utilizando uma abordagem orientada a objetos (OO) ou uma abordagem funcional (FP), de fato, recorrem a uma técnica similar: a ideia de usar o nome dinamicamente para obter uma referência à classe ou função correta. Isso é uma "gambiarra", mas também é uma demonstração do poder e flexibilidade que linguagens como Python oferecem.
No entanto, o que realmente importa aqui é o princípio subjacente que estamos tentando destacar: a ideia de abstrair a lógica condicional, de modo a tornar o código mais limpo, modular e extensível.
Quando falamos de abstrair lógicas condicionais, não estamos necessariamente falando sobre eliminá-las completamente. Em vez disso, estamos falando sobre movê-las para lugares onde elas fazem mais sentido ou são mais gerenciáveis. Em muitos casos, esta abstração resulta em um design mais limpo e em um código mais fácil de manter.
No entanto, é fundamental reconhecer que, em algum ponto, alguma forma de decisão ou lógica condicional ainda precisará existir. Seja em um dicionário que mapeia chaves a valores, em uma série de if-elif-else, ou em algum outro mecanismo - veja sobre branchless programming - essa lógica estará lá. O que estamos fazendo com essas abordagens é encapsulando, organizando ou distribuindo essa lógica de uma maneira que faça sentido para o problema e que mantenha o código limpo e manutenível.
Claro, vamos lá:
Primeiramentante tenha em mente que estes exemplos, embora simples e didáticos, são apenas ilustrativos e servem para demonstrar os conceitos fundamentais de diferentes paradigmas de programação. Na prática real, onde os problemas são muito mais complexos e multifacetados, os benefícios destas abordagens tornam-se mais evidentes.
OO
class Action:
def value(self):
return None
class CreateAction():
def value(self):
return 1
class ReadAction():
def value(self):
return 2
class UpdateAction():
def value(self):
return 3
class DeleteAction():
def value(self):
return 4
def receiveActionOO(action):
className = f"{action.capitalize()}Action"
actionClass = globals().get(className, Action)()
return actionClass.value()
FP
def create_action():
return 1
def read_action():
return 2
def update_action():
return 3
def delete_action():
return 4
def default_action():
return None
def receiveActionFP(action):
function_name = f"{action}_action"
action_func = globals().get(function_name, default_action)
return action_func()
action = 'update'
value_long = recieveActionLong(action)
value_short = recieveActionsShort(action)
value_OO = receiveActionOO(action)
value_FP = receiveActionFP(action)
print('Valor da ação longa: ', value_long) # 3
print('Valor da ação curta: ', value_short) # 3
print('Valor da ação OO: ', value_OO) # 3
print('Valor da ação FP:', value_FP) # 3
Eu acho que só vale a pena fazer isso se as classes fizerem algum processamento mais complexo. Se for pra retornar sempre o mesmo valor fixo, isso aí é um canhão pra matar mosca.
É bom saber que existe essa alternativa, claro. Mas sei lá, eu prefiro começar simples, e complicar somente se houver necessidade.