[DÚVIDA] Como identificar gambiarras no código?
Olá! :wave:Estou criando meu primeiro "projeto" em Python, como já mencionei antes estou inciando pela 5 vez na programação, mas agora é para valer. Para treinar meus conhecimentos adquiridos depois de consumir aulas sobre o tema achei que seria uma boa fazer um projeto simples para praticar, nesse caso escolhi um Pedra, papel e tesoura. Caso alguém se interesse da uma olhada no meu repositório.
Porém, eu gosto de implementar mais features ao script para me desafiar ainda mais e decidi que seria uma boa colocar uma parte com as regras do jogo(vai que alguém não sabe), e nisso pensei em criar um looping que enquanto o usuário não falar que entendeu as regras ele não para de perguntar, mas acontece que eu quero isso de dois modos.
Não vou explicar por agora esses dois modos que iriei fazer, mas sim gostaria de perguntar sobre como que você identifica que está fazendo gambiarras? Tipo, qual a diferença de uma gambiarra e uma lógica alternativa? Consegui fazer esses dois modos, funciona perfeitamente, mas não sei funcionou porque fiz uma gambiarra ou porque utilizei uma boa lógica. Caso alguém queira ler a ideia base do meu projeto código está aqui uma versão de teste que fiz em outro arquivo para ver como ficaria a implementação dessa feature usando Clube da Luta como exemplo:joy:
import time
rules = { # dictionary way
# key : value
"Rule 1": "You can't talk about Fight Club",
"Rule 2": "You can't talk about Fight Club",
"Rule 3": "You can't talk about Fight Club",
"Rule 4": "Only one fight at a time",
"Rule 5": "Only two people fight at a time",
"Rule 6": "No shoes or shirts",
"Rule 7": "Fights continue until necessary",
"Rule 8": "First-time attendees must fight"
}
rule = rules.values()
ask = str(input("$ Do you want to know the rules?(y/n) "))
ask1 = -1
while ask != 0:
if ask != "y" and ask != "n":
ask = str(input("$ Do you want to know the rules?(y/n) "))
if ask == "y" or ask1 == "n":
for value in rules.values():
print(f"* {value}")
time.sleep(1)
ask1 = str(input("$ Did you understand the rules?(y/n) "))
while ask1 != "n" and ask1 != "y":
ask1 = str(input("$ Did you understand the rules?(y/n) "))
if ask == "n" or ask1 == "y":
print("# Welcome to Fight Club")
ask = 0
Gambiarra é um termo amplo, mas eu considero que é qualquer coisa que seja mal feita ou que está longe de ser a solução ideal. É uma daquelas coisas que é meio difícil explicar de forma objetiva, mas vc sabe que é quando vê.
No seu caso, eu não diria que é gambiarra, apenas que dá pra simplificar a lógica e melhorar alguns detalhes.
Por exemplo, vc cria um dicionário com as regras. Mas vc só usa os valores, e em nenhum momento utiliza as chaves. Além disso, elas parecem meio redundantes: toda vez que vc tem chaves do tipo "coisa 1", "coisa 2", etc, é um forte indício de que talvez só precise de uma lista (ou array) dessas "coisas".
Outro detalhe é que input
sempre retorna uma string, então usar str(input())
é redundante e desnecessário.
Quanto aos loops, eu faria diferente, mas aí talvez seja gosto pessoal: eu não gosto muito dessas variáveis de controle ask
e ask1
. E a lógica de pedir pra digitar de novo até que o valor seja "y" ou "n" pode ser movida para uma função, isolando-a do loop principal. Algo assim:
import time
def ask(text):
while True: # enquanto não digitar "y" ou "n", continua o loop
answer = input(text)
if answer in ('y', 'n'):
return answer # return sai da função, devolvendo o valor digitado
rules = [
"You can't talk about Fight Club",
"You can't talk about Fight Club",
"You can't talk about Fight Club",
"Only one fight at a time",
"Only two people fight at a time",
"No shoes or shirts",
"Fights continue until necessary",
"First-time attendees must fight"
]
# só entra no loop se a pessoa quiser saber as regras
if ask('$ Do you want to know the rules?(y/n) ') == 'y':
while True:
for rule in rules:
print(f"* {rule}")
time.sleep(1)
if ask('$ Did you understand the rules?(y/n) ') == 'y':
break # se entendeu as regras, sai do while
print('# Welcome to Fight Club')
Repare na função ask
: eu não preciso colocar a pergunta uma vez antes do while
e outra dentro dele. Basta repeti-lo indefinidamente, até que seja digitado "y" ou "n".
Depois, posso usar essa função para ambas as perguntas (se quer saber as regras, e se entendeu). Note que nem precisa de variáveis auxiliares, posso usar o retorno da função ask
diretamente (eu fiz assim porque o valor não é utilizado mais de uma vez depois disso, mas caso fosse, aí justifica usar uma variável para guardar o valor digitado).
Também mudei a lógica: eu só entro no loop que mostra as regras se a pessoa quiser vê-las. E se a pessoa entendeu as regras, posso interromper o loop.
Já a mensagem "welcome" é sempre mostrada no final, então faz mais sentido deixá-la fora do loop.
Se não quiser mudar para usar while True
e break
, pelo menos mude os nomes das variáveis, pois ask
e ask1
não deixa muito claro o que cada uma é. Poderia ser algo como want_to_know
e understood
, por exemplo.
Outra opção é fazer com que a função ask
retorne True
ou False
, já que a pergunta só admite duas respostas possíveis ("sim" ou "não"). Aí no if
eu nem preciso verificar se é "y" ou "n":
import time
# retorna True se digitar "y" ou False se digitar "n"
# se não for nenhum, pede para digitar de novo
def ask(text):
while True:
answer = input(text)
if answer == 'y':
return True
if answer == 'n':
return False
rules = [
"You can't talk about Fight Club",
"You can't talk about Fight Club",
"You can't talk about Fight Club",
"Only one fight at a time",
"Only two people fight at a time",
"No shoes or shirts",
"Fights continue until necessary",
"First-time attendees must fight"
]
# não precisa mais comparar se é igual a "y"
if ask('$ Do you want to know the rules?(y/n) '):
while True:
for rule in rules:
print(f"* {rule}")
time.sleep(1)
if ask('$ Did you understand the rules?(y/n) '):
break # se entendeu as regras, sai do while
print('# Welcome to Fight Club')
Tem os conceitos de "code smells" e "clean code" que são práticas muito boas pra evitar gambiarras. Com o tempo tu consegue ver que códigos que seguem essas práticas são mais simples de dar manutenção.
Isso é algo um pouco subjetivo. Você pode fazer o melhor código na sua opinião, mas aí outro dev consegue refatorar e simplificar.
Mas com ou sem gambiarra, continua codando. Você já é um vencedor por estar criando algo; porque outros as vezes soh criticam as suas gambiarras e não criam nada.
A gambiarra é um conceito tipicamente brasileiro — reflexo da nossa cultura de resolver problemas com criatividade, mesmo à margem das "regras". Não é apenas um "workaround" (solução ruim) ou um "hack" (solução inteligente): é usar recursos de forma não convencional, subvertendo seu propósito original. Como usar um pedaço de silver-tape para consertar um cano furado: funciona, mas não é recomendado.
O Que Define uma Gambiarra?
- Subversão da Intenção
Uso de elementos fora do propósito para o qual foram criados. Não se trata apenas de "improviso", mas de distorcer a função natural de algo (ex.: transformar uma string em flag booleana para controlar um loop).
Isso é gambiarra. Não é questão de gosto.
- Uso Consciente
Se você sabe que está distorcendo uma ferramenta (e aceita os riscos), pode ser uma gambiarra válida. Se faz sem entender (ex.: misturar tipos de dados por acidente), é erro, não gambiarra.
- Contexto é Tudo
- Em protótipos ou emergências, é sempre gambiarra. Em código de produção, pode ser apenas uma bomba-relógio, não gambiarra.