Try..catch não é anti-pattern tampouco prejudica a legibilidade do código. Mascarar erros é anti-pattern. Usar try..catch em todo lugar é anti-pattern. E se vc pensar em usar try..catch prá escapar de loop, pede as contas agora mesmo. Erros tem que "borbulhar" na stack para serem tratados nos lugares certos. E try..catch é algo a ser usado com moderação, na hora certa, com o propósito certo. Assim como absolutamente tudo na programação, é mais uma ferramenta, não deve ser demonizado só porque tem mané que usa do jeito errado. Sem falar que as alternativas são piores. Por exemplo, o "tratamento" de erros do Golang é lindo quando você tem um programinha bem pequeno, com pouca coisa que pode dar errado. Mas quando a coisa toma corpo e vc tem que lidar com um enorme número de situações imprevisíveis, com tratamento de erros complexos, tratamentos diferentes para erros diferentes... aí meu amigo... você vai ter mais if(err) { ... } do que código de fato. E a legibilidade vai de vasco, fica péssimo de acompanhar até debugando. Experiência própria.
Exatamente... se tu vai colocar um try/catch sem que tua lógica tenha realmente uma ação pra isso, deixa o erro estourar na stack pq em algum ponto do código vai ser vital o tratamento
@@gabriellmatias7203 exatamente. Por que assim voce consegue cascatear a tipagem, assim o compilador/transpilador vai identificar os tipos de retorno e avisar quando falta um tratamento próprio. Ex: Se tu declarar que tua função retorna Int | error, e na função que chama ela tu fizer algo como result + 1, o compilador vai reclamar que esse result pode ser do tipo Error, que não pode ser operado como Int.
Pra quem quiser outras abordagens para evitar o uso de try catchs, recomendo pesquisarem e estudarem sobre Either Monads. É muito fácil de implementar e depois que você começa a de fato usar, não quer mais abandonar. Sugeri a utilização dele para a minha equipe e acabou se tornando um padrão em nossos projetos. Recomendo muito!
O artigo muito taxativo e bom pra pegar dev junior que gosta de hype. Mais um artigo no Medium que busca polemizar. O autor apresenta exemplos baseados em TypeScript. Nesses tipos de linguagem, devido a liberdade da fazer como você quiser, cabe ao programador tomar os seus devidos cuidados. Esse artigo, assim como video, só leva em consideração o mundo da sua linguagem e esse é um detalhe muito importante. Tenta fazer uma requisição web no Java pra ver se ele não te obrigar a usar um try-catch ou um throws na assinatura do método caso o caller vá tratar a exceção. Tem linguagem que não tem pra onde correr. E isso bom na minha opinião. Deixa na mão de um cara iniciante sem supervisão a decisão de como tratar a exceção, logo logo você vai ver o cara fazendo uma requisição sem tratamento de erro ou try catch, ai na primeira coisinha pipoca tudo.
Não são todos os tipos de erro que Java obriga vc a tratar no tempo de desenvolvimento. Em geral, exceções explicitamente definidas tem o requisito de serem tratadas, mas existem erros que são são explícitos ou não tem a obrigatoriedade de se controlar (em geral, RuntimeExceptions e Errors) Aqui, pq try-catch é um padrão ruim para Typescript? Pq vc tá usando um pattern de linguagem sequencial numa linguagem projetada para ser assíncrona (olha como usam async/await toda hora), enquanto Java é puramente síncrona (tirando talvez quando vc estiver usando NIO ou non-blocking APIs)
Toda provocação é válida quando o objetivo é evoluir. Mas sendo bem sincero, houve algus equívocos mais relacionados ao entendimento dos padrões da linguagem do que com o try/catch em si. Desde aninhamentos de try/catches sem um controle de escopo adequado, confusão com tipagem (python tem tipagem forte e dinâmica, inclusive) ou mesmo try/catch só mascarando erro ao invés de tratá-lo. Comparar alguns recursos de uma linguagem compilada com uma linguagem interpretada é como comparar laranjas e maçãs. Dá pra discutir trade-offs e usar isso pra melhorias na linguagem (tipo o type hint do python ou o typescript, meio que feitos para se aproximar de tipagem estática que você elogiou, por exemplo), mas usar uma amostra de código dificulta a discussão e não ajuda a entender o todo. Não subestime a capacidade de um dev cansado de fazer caquinha em Go também. kkkkkk
Discordo. Quem deve tratar os erros é o chamador de nível superior, e não a cadeia de chamadas. Os erros previsíveis que sejam validados via estrutura condicional e borbulhados para cima utilizando throw. Os erros não previsíveis basta deixar as Exception borbulharem naturalmente para cima e lá realizar o tratamento.
sem falar que nao existe necessidade de try-catch dentro de try-catch isso é código de exemplo que nunca passaria numa PR real (se vc ver isso na codeboase do seu trabalho, comece a mandar curriculos imediatamente)
Eu tbm penso assim, mas eu trabalho com java, e isso é padrão, fiquei pensando nesse caso de garantia de retorno de valor ai que o python não tem, pra mim isso deveria lançar a exception pra cima e parar o fluxo mesmo, sem o valor não da pra seguir na execução do fluxo.
@@fabiodosreisvianadasilva6850 mas é justamente isso. Lançar a exception para cima usando o comando "raise" do python, equivalente ao throw. Não adianta a chamada ser obrigada a retornar um valor se esse valor é fictício, fruto de um erro. Melhor propagar a exception e deixar o chamador lidar com o problema.
@@victorbiasibetti Eu entendo que deveria ser desse jeito. Acho que apenas maluco não usa um instanceof para trabalhar as diversas exeções (em vez de colocar um try catch dentro do outro).
Mais ou menos. Javascript por exemplo é meio ruim, mas é inevitável. Um dev bom em javascript consegue fazer aplicações boas mesmo com o JS sendo ruim. Try catch é ruim e é evitável, as linguagens que os devs mais gostam de usar (segundo a pesquisa do stackoverflow) não tem try/catch.
@@GutoGalego Mas quem que usa java script puro man? a maioria dos dev "java script" usam tyepscript, java script praticamente só é usado de forma didatica enquanto o dev ainda ta estudando programação..
Bom, Java tem um handler que me agrada muito. Me ajuda demais. Além de haver um handler (try...catch), temos a cláusula throws, que pode ser fornecida a métodos para informar a chamadas que aquele método pode lançar determinada exceção. A cláusula " throws" é seguida de uma exceção que podemos lançar. O compilador reclama muito quando não tratamos ela no chamador do método, e nem conseguimos rodar a aplicação. Além disso, temos a cláusula " throw", onde podemos decidir lançar uma nova exceção de dentro do método ou de dentro do catch, onde podemos relançar nossa exceção ao nível superior, caso não tenha como nos recuperar de um erro no método. Java nos permite definir vários catchs para um único try, ou então usar um padrão multicatch, onde apenas uma catch pode pegar várias exceções. E o recurso mais legal que amo no java é o try-with-resources, que elimina a necessidade de escrevermos blocos finally para limpar recursos. Claro que nada nos impede de escrever catchs ou finallys em try-with-resources, ele apenas tira essa preocupação. Eu acho que java é extremamente robusto. Me serve e muito pra muita coisa e me ajuda demais com essas operações críticas. Eu trabalho com desenvolvimento de softwares de gestao administrativa e tipo, não posso ter falhas. Então Java me ajuda muito nesse lado. Fora os recursos e o desempenho da linguagem que faz os olhos brilharem 🥹 Aprendam Java, é magnífico!
Só uma observação nesse seu comentário, tudo que você citou aí existe também no C# e algumas outras linguagens tipadas. Não é unicamente do Java. Jamais se apegue exclusivamente a uma linguagem.
Fico feliz de saber que eu já usava o throw só pra ir lancanço o erro pra cima e o try catch apenas na camada de apresentação pra poder saber e localizar o que tinha acontecido
Interessante acompanhar esse assunto. Sou programador Cobol e realmente, GO-TO é uma grande merda que a gente tinha que lidar lá atrás e era muito chato para debugar. Por esse tipo de problemas criou-se uma convenção de não usarmos go-to, ever! E o mais interessante desse vídeo, é que o "como consertar" é exatamente como fazemos no Cobol, para ficar mais legível e evitar bugs. Engraçado que algo que já faziam décadas atrás, estão sugerindo e implementando atualmente(result pattern)... O universo do software é realmente em ciclos né... kkkkk Aliás, parabéns pelo ótimo conteúdo como sempre Galego!
Galego, acho que você errou no comentário sobre o finally do inner_method. É impossível aquela função retornar None, o return type dela pode ser corretamente declarado como int. O finally não tem um return None implicito. Quando o ZeroDivisionError for levantado, ele vai ignorar o except ValueError, pois não é um ValueError, e como não tem mais nenhum except, a exceção vai subir na call stack, porém antes de subir, o finally tem que ser executado. Após o finally ser executado, o erro é re-levantado, sem retornar o None. None nunca é retornado aqui. A não ser que você coloque um return None no finally, mas ai sua função sempre vai retornar None, independente de ter uma exception no try ou não.
Pior do que usar try catch é não usar. Tem programador que se preocupa tanto com a qualidade do código que entrega que até esquece do software que está fazendo.
5:14, A velha pegadinha do strongly typed x dynamically typed. Python é FORTEMENTE e DINAMICAMENTE tipado. Sobre a forma de uso de try/catch isso é uma daquelas coisas que… depende dos cenários (como quase tudo em nossa área). Eu penso o contrário, exceptions não deveriam ser prioritariamente tratadas in-local (exceto se há uma boa razão para isso), até pelo fato de algumas vezes não fazer sentido (out of memory). Na maioria das vezes é melhor deixar propagar e deixar a camada mais acima tratar e lidar com esses erros, talvez tenha algum mecanismo ESPECIALIZADO na camada que trate os cenários de erros. Tentar tratar a maioria ou todas as exceptions no local onde elas ocorrem leva àquele local a ter mais ruído/sujeira de código, aumenta a complexidade, pois em alguns casos no tratamento haverá logging envolvido ou algum mecanismo de tracing e, consequentemente, importação de módulos e código que proveja essas funcionalidades causando aumento do grafo de DEPENDÊNCIAS não essenciais para aquela rotina. Além do ruído e distração causada, há também impacto no refactoring futuro devido às dependências. Propagando para cima é muito mais legível e possibilita uma estratégia muito mais modular e organizada/especializada. Um exemplo bem legal disso é o Django Rest Framework que nas classes de View tem um método onde você registra um manipulador especializado para tratar as exceptions que ocorrem nas chamadas daquele View set (pena que várias pessoas desconhecem). Quanto a forma que o Golang faz… well… sendo um programador de Go também, eu diria que há melhores formas de tratar erros. No final do dia, algumas dessas coisas depende muito da visão de cada sobre design. Desculpa o textão e bom vídeo! ;) P.S.: goto sendo considerado ruim não é consenso. Há cenários onde faz muito sentido do ponto de vista pragmático. Mas eu mesmo não uso (falando em C)
putz. assisti o video todo para descobrir que já é do jeito que eu programo. uso um try catch só nas controller e fazendo ali o tratamento de erro pra retornar ao usuario, e na camada de services fazendo a validação, tratamento, e requisição dos dados e avisando seus respectivos erros com throw error
faço parecido aqui com FastAPI (Python) sempre que tenho alguma exceção eu dou um raise independente da onde esteja rodando, e dai tem um handler global de erro, que retorna o erro pro usuário.
Faço a mesma coisa em Java. Essa é na minha opinião a melhor solução. O Spring tem um recurso chamado Controller advice que permite vc adicionar um ErrorHandler que é executado automaticamente nos controllers. Vc nem precisaria de try/catch
Quem tem problemas em usar try/catch tem que estudar mais sobre tratamentos de erros... Javascript pode até não ser a melhor linguagem, mas tem formas simples de tratar todos os erros. Não é um problema ter blocos try/catch um dentro do outro, mas é necessário fazer o tratamento correto e subir as exceções para o local onde serão processadas, fazendo isso não existe os problemas comentados no vídeo. Tem que saber como a linguagem lida com as exceções e tratá-las.
Legal o conteúdo! Quando trabalho com node, gosto de criar um adaptador de rotas (inverter a dependencia do express por ex) e colocar nele o trycatch. Depois crio classes de erros que eu gostaria de dar throw (BadRequest, NotFound, Conflict, etc...) e faço uma tratativa para enviar um body personalizado pro front. Dessa forma, se receber um erro 500 quer dizer que realmente deu merda, mas como eu tratei lá no route adapter, não vai bugar tudo
Os vídeos desse cara sempre apontam a tecnologia como problemática, quando na verdade é a pessoa que não sabe utilizar. Nos exemplos, temos vários métodos com apenas um try/catch, desse modo, o que esse método "pode" retornar deve ser tipado independente se você usa try/catch ou qualquer outra gambiarra. Você só deve parar de usar try/catch se quiser que sua aplicação estoure erros sem dar contexto pro usuário, e claro, quando você não sabe usar a ferramenta.
É que eu acredito que certas formas de se fazer software são melhores que outras. O cara que criou o Null diz que null foi um erro. As linguagens evoluem e mudam. Python permitia antes mudar o valor de True e False. Agora não pode mais, as coisas evoluem conforme a indústria descobre maneiras melhores de fazer as coisas. Eu acredito que existem maneiras melhores
@@GutoGalego Eu entendi a questão da evolução, as pessoas evoluem e a tecnologia junto com elas. O que eu estou com problema em entender é; como adicionar verbosidade ao algoritmo pode ser melhor do que usar tryCatch. A verbosidade extra pode até tornar o código mais legível, mas o torna menos seguro, afinal, o que você programou ainda está sujeito a erros, erros que o tryCatch poderia tratar ou ao menos te gerar um log. Se o assunto do vídeo é clean code, sinto muito pois entendi errado, achei que era tecnologia defasada.
Bom então vamos fazer o seguinte A partir de agora vc só pode usar assembly, nada de linguagens de alto ou médio nível. Agora, quero ver vc dizer que a culpa é do programador.
@@AlexeiDimitri você esqueceu de dizer que isso é uma suposição? Ou realmente é para eu usar somente assembly? Em qualquer caso, percebe-se que a falta de seguir certas regras, neste caso a gramatica, faz com que o programador cometa erros. Tu quer dizer que assembly é ruim? Independente das habilidades do programador? Por favor, deixe-me entender seu raciocínio neste comentário.
Me tira uma duvida boba mais pra mim e importante (ela vai na contra mao do video com seu raciocionio) 1 - Try-catch sem throw: Se você não usar throw dentro do bloco catch, o erro é capturado e tratado ali mesmo? Se sim o programa continua a execução normalmente após o bloco catch ? 2 - Throw dentro do catch: Se você usar throw dentro do bloco catch, a exceção é lançada novamente e propagada para outros blocos catch mais acima na pilha de chamadas, até que seja capturada novamente ou até que não haja mais blocos try-catch ? 3 - A exceção lançada com throw continuará subindo na pilha de chamadas até encontrar um bloco try-catch que a capture ? Se ele não encontrar, será tratada como uma exceção não capturada e pode terminar a execução do programa chegando ate o main?
pelo menos nas linguagens de JVM (Kotlin e Java) que tenho conhecimento o bloco continua sim, se não houver o throw ou o return o fluxo continua normalmente.
@@Miguel-y4o quando tu passa uma semana criando um componente super customizado , ai vem o QA enchendo o saco por causa da cor do botão , ou não executa a animação que ele queria
Sem mencionar que sair do fluxo principal ou contexto principal é extremamente imperformático, sendo considerado uma má prática por algumas linguagens antigas. É preferível usar return true ou false. Linguagens como Go sanam isso utilizando erro em formato de variável sem sair do contexto ( main ).
Primeiramente se você não tem um fallback que seja um retorno valido, você não deveria capturar e tratar o erro. Se a função que chama não souber tratar o erro, ela deve ser interrompida, assim como todas as funções anteriores. Caso seja uma exceção inesperada deve ser capturada por um handler generico ao invés de matar a aplicação. Caso seja esperada e impossivel de resolver como por exemplo uma requisição http onde um campo do body que deveria ser um numero é uma letra, você deveria capturar, e jogar uma exceção enriquecida com detalhes do problema no contexto dele: (InvalidPhoneException, causedBy IllegalArgumentException). Nessa situação nada além de dar o feedback na response deveria acontecer. então você só vai capturala e tratala na hora que for buildar a response, nesse momento todas as funções anteriores já foram desepilhadas. Caso seja esperada e souber resolver, captura resolve e retorna a solução. A mesma coisa é no Go, se a função que chamou não souber tratar o erro, retorna o erro, para a anterior tentar. O que não gosto do Go é isso, tem que escrever toda vez if (err!=nil ) return err, quando que em outra liguagens é só não capturar o erro, que o comportamento é o mesmo. Existem exceções mas no geral é isso.
Muito bom vídeo, foi uma das coisas que mais gostei em Go quando comecei a alguns anos atrás, é o fato do error não ser um objeto concreto na linguagem, podendo interagir com o tipo dele de forma mais livre, mas ainda assim existe uma espécie de "try/catch" em go. Mesmo em funções que não retornam erros diretamente, existe uma possibilidade de uma exception ocorrer. Se forem funções de pacotes padrões do Go provavelmente o motivo é que parte do processo dessa função está acontecendo fora do escopo em que o runtimer do go pode vistoriar ou acessar, ou se for um pacote criado por você ou pela comunidade, pode ocorrer se a função "panic" for chamada. Basicamente ela é para funcionar de forma similar as outras linguagens, mas no momento em que a exception quebra a pilha e encerra o programa, ela basicamente recebe um any e vai quebrar a pilha de execução inteira e retornar o que ela recebeu como exception, mesmo que nem seja uma, inclusive. Caso esse panic ocorra, vc pode usar o defer juntamente com a função recover para poder fazer algo em cima desse erro que gerou o panic. Eu particularmente acho essa parada de Panic/Recover meio dúbio, mas entendo a necessidade dela na linguagem. De qualquer maneira, a forma padrão de se lidar com erros em Go é como descreveu, e realmente evita bastante esse problemas de Try/Catch.
Falaram mal do GOTO e a solução mais elegante que conheço para erros é vinda justamente da linguagem que mais usa GOTO: BASIC. Algumas versões tem algo simples assim: ON ERROR GOTO LINHA XXXXXX Na primeira linha de seu programa você fazendo isso, desviará qualquer erro para aquela linha (XXXXXX). Lá você põe a rotina que você usará para no mínimo te mostrar o que houve. Sem Try e Catch antes do Try e Catch para saber se houve error no TRY ou no CATCH.... XXXXXXX PRINT #LIN, #ERR, etc... Algo parecido com isso, lhe mostraria a linha onde houve o erro e a mensagem de erro. Simples e funcional.
Muito bom o vídeo, concordo que try catch não é o ideal na maioria das vezes. Mas o que mais me deixa puto é o pessoal falando que o problema não é o try catch, e sim o programador. Pessoal ignora qualquer defeito de uma linguagem falando que a culpa é da pessoa que tá usando, algo que é muito injusto. Se o programador de hoje em dia comete os mesmos erros que o programador de 30 anos atrás, não é a pessoa, é a tecnologia, mas o pessoal não aguenta outros falarem mal da linguagem favorita deles
Tá aí um dos motivos de eu gostar tanto de Go - erros são valores e você é obrigado a tratá-los (além de que fica sempre explícito na declaração de uma função caso ela possa retornar um erro)
sobre python: em resumo sobre os linters se quiser verificar tipos e qualidade de código na hora do desenvolvimento utilize o mypy (se possível strict), e o ruff. Se quiser verificar tipos em execução o pydantic faz o trabalho. python é uma linguagem de tipagem dinâmica e forte.
Mano se tivesse mencionado a questão do uso de memoria para manter a stack trace do erro quando ele é lançado nas camadas mais internas até faria sentido que vc ta falando. O código que vc mostrou tem tantos problemas que eu não acho que é culpa do try/catch kkk. Mas é muito bom o pattern do GO do either ou result.
Ninguém usa try catch dentro de try catch. Geralmente se usa o try catch somente para não quebrar a aplicação com erros desconhecidos e os erros conhecidos são retornados normalmente
Na real é bem comum em frameworks haver um módulo chamado exception handler que visa tratar qualquer exception que subir sem tratamento, tem que haver isso pq chega uma hora que fica repetitivo tratar o mesmo tipo de erro do mesmo jeito em vários lugares
Galera em C usa goto para lidar com exceções. Esse tipo de implementação lembra try/catch apesar do mecanismo de “rewind” ser diferente Além disso, em linguagens que tem a sugar syntax `?` leva a erros mais sutis na hora de debugar o erro no log (devido a falta de trackback)
Try/catch não é péssimo, exceto se você estiver usando ele da forma errada, isto é, pra fazer controle de fluxo de execução (ao invés de usar if's) ou silenciando erros. De igual forma, propagar erros através da call stack não é um anti-pattern, pelo contrário, auxilia ao usuário da sua API tratar o erro na camada de abstração correta.
eu como uso c# nao tenho esse problema, pois é facilmente resolvido entre client e api com, inclusive uso muito return em void para justamente parar a execução de codigo quando algo esta faltando/errado, é so saber usar as ferramentas da linguagem de maneira apropriada
hahah péssimo porque não sabe usar Exceptions hahahaha Muito raro os casos que realmente precise usar try e catch assim. igual falou. Consigo pensar agora quando precisar dar um rollback
Ou vc pode usar "result, _ := divide(10, 0)". Claro que quando vc faz isso as vezes costuma ser com motivo, mas pode acontecer. Acho que Rust lida com erros de uma forma muito mais "chata" mas bem mais efetiva
Esse tipo de coisa acontece pq vc tá pensando de forma sequencial numa linguagem nativamente assíncrona e funcional. Em geral se vc tá usando async/await é pq vc tá fazendo errado. Como vc lida então com exceções e consegue controlar o fluxo de trabalho? Simples, usando Promises e usando máquina de estados. Vc usa os promises para mudar o estado da sua aplicação E a sua aplicação basicamente reage a essas mudanças de estado Como vc faz o usuário participar disso? Sua aplicação mapeia a interface para o estado da aplicação E promises fazem o trabalho de sincronizar o estado local com o estado no servidor. Ë o mesmo motivo pelo qual um programador burro pega um I/O que é assíncrono e dá um jeito de torná-lo síncrono. Vc tá ocupando recursos que não deviam estar travados e deixando a aplicação menos responsiva, pq o thread principal do JS tá esperando o resultado daquele I/O.
Em 5:42: tecnicamente falando, inner_method NUNCA retorna, então não faz definir um return type para ela. Ela SEMPRE vai estourar um ZeroDivisionError e nunca retornar. Se você quiser ser preciso, o correto é definir inner_method como def inner_method() -> typing.NoReturn, ou então, em python3.11+, typing.Never, que são os mesmos tipos utilizados para funções que ficam em loop infinito: def main() -> typing.Never: while True: pass
Uns dizem que não pode usar else, outros try/catch. Qualquer recurso de fluxo de controle que for mal utilizado vai resultar em código ruim e pouco previsível.
De vez em quando a Internet dá uma sequelada, try catch não é nenhum pouco parecido com Goto, que podia avançar, a exception só retorna, ele tá mais pra um if + return implícito, já que de fato retorna um objeto.
Pior que, até no Java, onde tu tem a tipagem certinha e ele obriga a colocar o throws na assinatura do método, todo esse argumento vale, porque pode ter levantado um RuntimeException ou algo assim que não é obrigado no throws. E, pior que, se colocar pra obrigar, quebra tudo kkk
Dê semantica pros errors: validation, error, unexpected, unavailable. Cria uma função pra mapear isso na camada superior e lançar o status correto. Faz mais uma validação pra garantir que os dados vão ser executados corretamente na regra de negocio. Simples assim.
Um dos poucos vídeos que discordo fortemente do galego, esse pattern de result ofusca completamente a stack trace quando um erro acontecer, citando java, tenho a sensação que é como fazer try catch pra lidar com erros ao invés de exceptions Linguagens que já tem algo parecido nativamente ok, como go e rust, mas se não, vejo a aplicação como uma muleta pra uma certa incapacidade de algum sênior em transmitir o conhecimento necessário de estrutura de dados aos mais novos
Eu não sei se é uma boa idéia usar "padrões" para emular comportamentos de outras linguagens ao invés de usar melhor aquilo uma linguagem já oferece de maneira nativa.
Programo em Python e nunca tinha visto esse result pattern mas faco isso instintivamente porque já sofri muito com esse tipo de problema kakaka error_, result = funcao_faz_algo(param) if error_ ....
O exemplo inicial, com um try/catch dentro de outro try/catch não é bom, pois já indica um problema de design, que deveria ser corrigido antes de tudo.
Putz mas aí usando assim, é ruim mesmo. Agora se souber usar, vc padroniza o erro, deixa mais rastreável, evita quebrar a API exceto quando é necessário, e sem 'mascarar' os erros também. Como dizia o grande poeta, "modéstia a parte, código ruim, eu sei fazer muito bem, em em qualquer linguagem, e com qualquer paradigma..."
Nunca gostei de usar try catch como uma estrutura para error handling. Estes dias precisei usa-lo para retornar um objeto diferente caso a API estourasse uma excessão, e para este caso, ele foi bem últil.
Porquê diabos as pessoas não focam em usar Guards para evitar usar Try/Catch? Eu nunca entendi essa tara estranha das pessoas de querer garantir o resultado sem garantir que o processo esteja correto. Try/Catch só se usa em condições que seu código não pode garantir um fator externo como um banco de dados falhar na inserção de dados e mesmo assim você pode usar um circuit-breaker em situações assim(Aqui tem que ter atenção). PS: Leiam sobre programação defensiva.
@@dfeprado Você só aceita que não sabe os detalhes do que você esta programando e também aceita que não testou o seu software adequadamente. Segundo a definição de guards segundo a Wikipedia: "Em programação de computadores, uma "Guard clause" é uma expressão booleana que deve ser avaliada como verdadeira se a execução do programa deve continuar no branch em questão. Independentemente de qual linguagem de programação é usada, uma "Guard Clause", é uma verificação de pré-condições de integridade usada para evitar erros durante a execução."
São estilos diferentes (LBYL e EAFP), mas não quer dizer que é pra garantir um "resultado que encaixe". Em resumo, eu diria que a diferença é sobre tratar a possibilidade de erro antes ou tratar o erro depois, se ele acontecer. O que tem que ser feito com o erro vai ser o mesmo para os dois casos: tratar como deve ser tratado pra cada caso. Essa história de usar o try/catch pra mascarar não é problema de try/catch. É do programador mesmo.
@@alexandreabto Exatamente. Eu prefiro mil vezes considerar usar Try/Catch numa situação onde eu estou querendo salvar um dado num banco de dados e eu não posso garantir que fulano ou beltrano não vá tropeçar nos cabos de energia do servidor e perder conexão do que usar Try/Catch deliberadamente para qualquer função que eu chamar na garantia de que elas não falhem. Com apenas Guards eu consigo esgotar quase todas as possibilidades de erros na função que eu tento executar. Linguagens funcionais tentam lidar tratamento de erro usando guards/pattern matching e torna as coisas tão simples quanto.
Do meu ponto de vista, o problema com o try/catch é o exagero. Eu mantenho sempre um padrão nos meus códigos que é o de deixar quebrar sempre que possível. Eu vou ter apenas no nível mais alto da aplicação, e apenas em casos onde preciso dar rollback em uma transaction do banco e afins, caso contrário, nem isso, deixo pro meu "try catch global" lidar com o erro, registrar logs e retornar uma mensagem de erro adequada ao cliente.
Eu não entendo como seria diferente das linguagens que tem try-catch mas tem null-safety. Porque elas não te deixam retornar null quando a função diz que retorna um valor, mesmo usando try-catch
Eu sempre uso o try-catch. Caso dê algum erro eu aciono minha tabela de logs para salvar a cagada que rolou. Isso simplesmente me salva de ficar procurando erros quando eu recebo algum ticket.
Não gosto da ideia de "misturar" o fluxo de exceção com o fluxo esperado, eu prefiro disparar uma exceção e criar um tratamento isolado para lidar com ela isolando responsabilidades.
Que video incrível. Parabéns! Mas fiquei com uma certa dúvida, qual seria diferença então de usar um - Try Catch ou - Then Catch -> promise().then(...).catch(...) Saberia explicar?
Mesma coisa, basicamente no `then` você está pegando o valor do try, e no `catch` o do próprio catch, porém essa forma de then, catch é meio complicada pois você pode encadear muita coisa aí, e deixar o código difícil de entender.
Try catch é a forma mais atual de se usar, pois no ES6 surgiu o async await, promise.then() era a forma que era usada anteriormente. Se for escolher entre os dois, use async await com try catch
A desculpa é que trabalha cansado? kkk Foi mal, desce não. Se você precisa de uma linguagem para não "te deixar mentir", como você disse, o problema é com você. De toda maneira, se você programa porcamente, seu código será ruim, independente da linguagem. Como resolve isso? Escrevendo testes bem feitos. Isso, sim, vai pegar todos os erros e não deixar você subir código mal escrito para produção.
Não sei se é porque estou muito acostumado a ver try/catch que não vejo as coisas que falou como problema, contando que não se minta o retorno, tenha retorno padronizado e devidamente documentado.
Acredito que você Augusto, talvez tenha se equivocado ao falar que GOTO é uma relíquia, pq no final do dia, if/else/while, todas as operações de controle de fluxo são um mero GOTO, por mais que não "codemos" usando GOTO, quando a linguagem é interpretada/compilada para assembly, o código é transformado para assembly usa os jumps na 'tradução' do código, que são os GOTO, redirecionando o fluxo do código para algum endereço x do Program Counter. Isso falando no nível da CPU! Abraços, me corrija se eu estiver errado.
Acredito que a linha argumentativa foi meio fraca, quanto legibilidade está okay, mas apresentar apenas a ideia deste modo foi muito simplório e no fim só diz que a culpa é do programador sem indicar que existe um problema real que é a perda de performance devido utilização de exceções pra controle de fluxo
Esse exemplo do post já não faz sentido porque o cara botou um try catch dentro de outro só pra mudar a mensagem de log. Se isso não é importante (quase nunca é) vc pode sempre usar apenas um try/catch e o catch ser log generico como "console.error('error', error.toString)" ja que a mensagem do erro ja vai dizer o que aconteceu.
Discordo q seja o try catch. Pois isso varia por linguagem. No próprio Java, que usa try catch, tb te obriga a tratar a exceção se vc chama um método q pode lançar uma exceção, vc soh escolhe se vc vai tratar ou se seu método tb vai explicitamente jogar ela pra cima
Acho que tudo e balanca... nao sou faaaazaaaasssso do try catch mas vc poderiater um try catch e um roll back no catch... agora try catch dntorde try catch dentry d try catch... isso e problema do dev e como ele esquerve o go horse dele, a feramenta e neutra e pode ser bem utilizada... tipo eu usando com um rollback em situacoes especificas.
Eu postei do vídeo, mas tenho uma dúvida um pouco fora do conteúdo, Como eu paro de ser um programado mesquinho, Tipo: sinto que estudo a um tempo e não tenho uma evolução
Poh mano... Tanto o exemplo péssimo de try/catch como o exemplo de solução de uso, são em TS/JS, o que me leva a conclusão, o problema é o noob que escreve igual o exemplo 1 e não a linguagem em si. não importa qual linguagem, se o carra escrever no go horse vai ser ruim de ler de qualquer jeito....
boa, to fechado. fico confuso pq diabos tem gente defendendo try-catch, quase que com um apego emocional 🤔 acho q se a linguagem é precária tipo JS blz, não tem muito o que fazer... Mas dado que a sua linguagem suporta algo mais ergonômico, tipo Result/Either como a gente tem em OCaml/Rust, realmente não tem um argumento plausível para achar que é uma ferramenta boa. Na boa, só vai defender try-catch ou quem nunca viu algo melhor, ou quem tem um filtro baixo pra qualidade de código, falei mesmo kkkkkk 🤷♂️
O problema não é o try catch, MAs sim como você usa. Esses exemplos aí obviamente são um mal uso do recurso, mas não que o try catch seja o problema. O título ficou bem sensacionalista e a explicação bem tendenciosa.
Os argumentos do vídeo estão corretos, porém incompletos (existem ainda mais motivos pq o try catch é ruim). O próprio fato das exceptions serem tratadas dessa forma torna ainda mais difícil de diferenciar quais erros devem ser tratados pela aplicação (erros recuperáveis), dos erros de lógica e bugs (erros irrecuperáveis). E sim, um programador experiente consegue diferenciar e implementar de forma correta, porém, á própria linguagem de programação não o deveria induzir a cometer este tipo de engano. Por isso, eu até argumento que o try catch deveria ser considerado uma feature ruim no design de uma linguagem de programação. Fun fact: um requerimento para ter o try catch é possuir um mecanismo de "unwinding" (_desenrolar_ call stack) o que além de ser difícil de implementar, em linguagens compiladas (Rust, se não me engano, isso acontece no C++ também), o compilador é impossibilitado de fazer algumas otimizações, já é necessário considerar que em "qualquer ponto" a execução pode ser interrompida. Artigo: Unwind considered harmful
Ninguem entendeu o ponto central, não se trata de ser o melhor ou pior, ou condenar try/catch Se trata do ferramental que vai mitigar erros automaticamente, obvios que existem excelentes patterns pra usar com try/catch problema é garantir que os 500 devs numa empresa vao seguir isso Como ele disse, tanto quem ta fazendo, quanto quem ta revisando pode estar cansado e deixar, so vao descorbrir quando o cliente reclamar Sobre o pessoal falando que Go fica muito verboso pra sistemas enormes, na minha opniao nem deveria existir mais sistemas enormes, mesmo se for monolito poder ser feito com arquitetura modular e ddd justamente pra dividir ben o escopo e deixa facil de implementar e manter Pessoal nao percebe o proprio viés, facam como o Galelo e critiquem sua própria stack mesmo gastando e usando ela
Não é péssimo, imagina que você precise usar middlewares ou conexões assincronas, a maioria das libraries q adotam essas técnicas usam try catch não tem como fugir a não ser que você desenvolva todo seu domínio sem nenhuma dependencia ou escolha tudo a dedo isso é loucura. escovação de bit de maluco. O negócio é criar observabilidade com logs em caso de catchs serem estourados...
Try..catch não é anti-pattern tampouco prejudica a legibilidade do código.
Mascarar erros é anti-pattern. Usar try..catch em todo lugar é anti-pattern.
E se vc pensar em usar try..catch prá escapar de loop, pede as contas agora mesmo.
Erros tem que "borbulhar" na stack para serem tratados nos lugares certos. E try..catch é algo a ser usado com moderação, na hora certa, com o propósito certo. Assim como absolutamente tudo na programação, é mais uma ferramenta, não deve ser demonizado só porque tem mané que usa do jeito errado.
Sem falar que as alternativas são piores. Por exemplo, o "tratamento" de erros do Golang é lindo quando você tem um programinha bem pequeno, com pouca coisa que pode dar errado.
Mas quando a coisa toma corpo e vc tem que lidar com um enorme número de situações imprevisíveis, com tratamento de erros complexos, tratamentos diferentes para erros diferentes... aí meu amigo... você vai ter mais if(err) { ... } do que código de fato. E a legibilidade vai de vasco, fica péssimo de acompanhar até debugando. Experiência própria.
Exato! O pessoal reinventa a roda demais.
Comentário cirúrgico!
O comentário que eu não escreveria, mas o comentário que eu precisava.
Exatamente... se tu vai colocar um try/catch sem que tua lógica tenha realmente uma ação pra isso, deixa o erro estourar na stack pq em algum ponto do código vai ser vital o tratamento
Trabalho numa stack em Go gigantesca e a pior parte dela é o Java legado. 🤐
Então o problema não é try catch, por que ele tá por baixo dos panos pra poder retornar o error, mas sim não definir o tipo correto de retorno.
Entao no caso eu colocaria que todas minhas funções podem retornar um tipo primário ou não, e também um erro caso haja um try catch dentro do método?
@@gabriellmatias7203 exatamente. Por que assim voce consegue cascatear a tipagem, assim o compilador/transpilador vai identificar os tipos de retorno e avisar quando falta um tratamento próprio.
Ex: Se tu declarar que tua função retorna Int | error, e na função que chama ela tu fizer algo como result + 1, o compilador vai reclamar que esse result pode ser do tipo Error, que não pode ser operado como Int.
Pra quem quiser outras abordagens para evitar o uso de try catchs, recomendo pesquisarem e estudarem sobre Either Monads. É muito fácil de implementar e depois que você começa a de fato usar, não quer mais abandonar. Sugeri a utilização dele para a minha equipe e acabou se tornando um padrão em nossos projetos. Recomendo muito!
Right!
Obrigada!
Optional em java é parecido
Já já brota algum programador Haskell tentando explicar o que é uma Monada.
Apesar de atualmente trabalhar com node, vou dar uma estudada em Either Monads....
O artigo muito taxativo e bom pra pegar dev junior que gosta de hype. Mais um artigo no Medium que busca polemizar. O autor apresenta exemplos baseados em TypeScript. Nesses tipos de linguagem, devido a liberdade da fazer como você quiser, cabe ao programador tomar os seus devidos cuidados. Esse artigo, assim como video, só leva em consideração o mundo da sua linguagem e esse é um detalhe muito importante. Tenta fazer uma requisição web no Java pra ver se ele não te obrigar a usar um try-catch ou um throws na assinatura do método caso o caller vá tratar a exceção. Tem linguagem que não tem pra onde correr. E isso bom na minha opinião. Deixa na mão de um cara iniciante sem supervisão a decisão de como tratar a exceção, logo logo você vai ver o cara fazendo uma requisição sem tratamento de erro ou try catch, ai na primeira coisinha pipoca tudo.
Não são todos os tipos de erro que Java obriga vc a tratar no tempo de desenvolvimento.
Em geral, exceções explicitamente definidas tem o requisito de serem tratadas, mas existem erros que são são explícitos ou não tem a obrigatoriedade de se controlar (em geral, RuntimeExceptions e Errors)
Aqui, pq try-catch é um padrão ruim para Typescript? Pq vc tá usando um pattern de linguagem sequencial numa linguagem projetada para ser assíncrona (olha como usam async/await toda hora), enquanto Java é puramente síncrona (tirando talvez quando vc estiver usando NIO ou non-blocking APIs)
Toda provocação é válida quando o objetivo é evoluir. Mas sendo bem sincero, houve algus equívocos mais relacionados ao entendimento dos padrões da linguagem do que com o try/catch em si.
Desde aninhamentos de try/catches sem um controle de escopo adequado, confusão com tipagem (python tem tipagem forte e dinâmica, inclusive) ou mesmo try/catch só mascarando erro ao invés de tratá-lo.
Comparar alguns recursos de uma linguagem compilada com uma linguagem interpretada é como comparar laranjas e maçãs. Dá pra discutir trade-offs e usar isso pra melhorias na linguagem (tipo o type hint do python ou o typescript, meio que feitos para se aproximar de tipagem estática que você elogiou, por exemplo), mas usar uma amostra de código dificulta a discussão e não ajuda a entender o todo.
Não subestime a capacidade de um dev cansado de fazer caquinha em Go também. kkkkkk
Discordo. Quem deve tratar os erros é o chamador de nível superior, e não a cadeia de chamadas.
Os erros previsíveis que sejam validados via estrutura condicional e borbulhados para cima utilizando throw.
Os erros não previsíveis basta deixar as Exception borbulharem naturalmente para cima e lá realizar o tratamento.
sem falar que nao existe necessidade de try-catch dentro de try-catch
isso é código de exemplo que nunca passaria numa PR real (se vc ver isso na codeboase do seu trabalho, comece a mandar curriculos imediatamente)
@@victorbiasibetti exato
Eu tbm penso assim, mas eu trabalho com java, e isso é padrão, fiquei pensando nesse caso de garantia de retorno de valor ai que o python não tem, pra mim isso deveria lançar a exception pra cima e parar o fluxo mesmo, sem o valor não da pra seguir na execução do fluxo.
@@fabiodosreisvianadasilva6850 mas é justamente isso. Lançar a exception para cima usando o comando "raise" do python, equivalente ao throw. Não adianta a chamada ser obrigada a retornar um valor se esse valor é fictício, fruto de um erro. Melhor propagar a exception e deixar o chamador lidar com o problema.
@@victorbiasibetti Eu entendo que deveria ser desse jeito. Acho que apenas maluco não usa um instanceof para trabalhar as diversas exeções (em vez de colocar um try catch dentro do outro).
Resumindo, o problema não é o try/catch, mas sim o Dev ruim em estrutura de dados.
isso e o basico de execucao de codigo
Então logo Goto tbm não é 😉
Mais ou menos. Javascript por exemplo é meio ruim, mas é inevitável. Um dev bom em javascript consegue fazer aplicações boas mesmo com o JS sendo ruim.
Try catch é ruim e é evitável, as linguagens que os devs mais gostam de usar (segundo a pesquisa do stackoverflow) não tem try/catch.
Try Catch qnd vc não sabe o que é o erro, quando vc sabe é perfeito.
@@GutoGalego Mas quem que usa java script puro man? a maioria dos dev "java script" usam tyepscript, java script praticamente só é usado de forma didatica enquanto o dev ainda ta estudando programação..
Bom, Java tem um handler que me agrada muito. Me ajuda demais.
Além de haver um handler (try...catch), temos a cláusula throws, que pode ser fornecida a métodos para informar a chamadas que aquele método pode lançar determinada exceção.
A cláusula " throws" é seguida de uma exceção que podemos lançar. O compilador reclama muito quando não tratamos ela no chamador do método, e nem conseguimos rodar a aplicação.
Além disso, temos a cláusula " throw", onde podemos decidir lançar uma nova exceção de dentro do método ou de dentro do catch, onde podemos relançar nossa exceção ao nível superior, caso não tenha como nos recuperar de um erro no método.
Java nos permite definir vários catchs para um único try, ou então usar um padrão multicatch, onde apenas uma catch pode pegar várias exceções.
E o recurso mais legal que amo no java é o try-with-resources, que elimina a necessidade de escrevermos blocos finally para limpar recursos.
Claro que nada nos impede de escrever catchs ou finallys em try-with-resources, ele apenas tira essa preocupação.
Eu acho que java é extremamente robusto. Me serve e muito pra muita coisa e me ajuda demais com essas operações críticas.
Eu trabalho com desenvolvimento de softwares de gestao administrativa e tipo, não posso ter falhas. Então Java me ajuda muito nesse lado. Fora os recursos e o desempenho da linguagem que faz os olhos brilharem 🥹
Aprendam Java, é magnífico!
Só uma observação nesse seu comentário, tudo que você citou aí existe também no C# e algumas outras linguagens tipadas. Não é unicamente do Java. Jamais se apegue exclusivamente a uma linguagem.
@@paulorockz6899 óbviamente, pois c# literalmente copiou Java
Fico feliz de saber que eu já usava o throw só pra ir lancanço o erro pra cima e o try catch apenas na camada de apresentação pra poder saber e localizar o que tinha acontecido
Mano, já acompanho seus vídeos tem um tempo, e tem me ajudado bastante seus conteúdos. Além da didática, a maneira da exposição dos tópicos é ótima!
Interessante acompanhar esse assunto. Sou programador Cobol e realmente, GO-TO é uma grande merda que a gente tinha que lidar lá atrás e era muito chato para debugar. Por esse tipo de problemas criou-se uma convenção de não usarmos go-to, ever!
E o mais interessante desse vídeo, é que o "como consertar" é exatamente como fazemos no Cobol, para ficar mais legível e evitar bugs.
Engraçado que algo que já faziam décadas atrás, estão sugerindo e implementando atualmente(result pattern)... O universo do software é realmente em ciclos né... kkkkk
Aliás, parabéns pelo ótimo conteúdo como sempre Galego!
Galego, acho que você errou no comentário sobre o finally do inner_method. É impossível aquela função retornar None, o return type dela pode ser corretamente declarado como int.
O finally não tem um return None implicito. Quando o ZeroDivisionError for levantado, ele vai ignorar o except ValueError, pois não é um ValueError, e como não tem mais nenhum except, a exceção vai subir na call stack, porém antes de subir, o finally tem que ser executado. Após o finally ser executado, o erro é re-levantado, sem retornar o None. None nunca é retornado aqui.
A não ser que você coloque um return None no finally, mas ai sua função sempre vai retornar None, independente de ter uma exception no try ou não.
Pior do que usar try catch é não usar. Tem programador que se preocupa tanto com a qualidade do código que entrega que até esquece do software que está fazendo.
5:14, A velha pegadinha do strongly typed x dynamically typed. Python é FORTEMENTE e DINAMICAMENTE tipado.
Sobre a forma de uso de try/catch isso é uma daquelas coisas que… depende dos cenários (como quase tudo em nossa área). Eu penso o contrário, exceptions não deveriam ser prioritariamente tratadas in-local (exceto se há uma boa razão para isso), até pelo fato de algumas vezes não fazer sentido (out of memory). Na maioria das vezes é melhor deixar propagar e deixar a camada mais acima tratar e lidar com esses erros, talvez tenha algum mecanismo ESPECIALIZADO na camada que trate os cenários de erros. Tentar tratar a maioria ou todas as exceptions no local onde elas ocorrem leva àquele local a ter mais ruído/sujeira de código, aumenta a complexidade, pois em alguns casos no tratamento haverá logging envolvido ou algum mecanismo de tracing e, consequentemente, importação de módulos e código que proveja essas funcionalidades causando aumento do grafo de DEPENDÊNCIAS não essenciais para aquela rotina. Além do ruído e distração causada, há também impacto no refactoring futuro devido às dependências. Propagando para cima é muito mais legível e possibilita uma estratégia muito mais modular e organizada/especializada. Um exemplo bem legal disso é o Django Rest Framework que nas classes de View tem um método onde você registra um manipulador especializado para tratar as exceptions que ocorrem nas chamadas daquele View set (pena que várias pessoas desconhecem).
Quanto a forma que o Golang faz… well… sendo um programador de Go também, eu diria que há melhores formas de tratar erros. No final do dia, algumas dessas coisas depende muito da visão de cada sobre design.
Desculpa o textão e bom vídeo! ;)
P.S.: goto sendo considerado ruim não é consenso. Há cenários onde faz muito sentido do ponto de vista pragmático. Mas eu mesmo não uso (falando em C)
"raios gamas podem flipar bits" mano imagina o azar do cara investigando bug por isso kkkkk
pior que ja rolou! kkkkk um amigo meu que trabalhava com dispositivos que sao expostos a isso relatou
Foi um exemplo infeliz dele
Para esse tipo de problema vc tem tratamento já no hardware, leia-se ECC
putz. assisti o video todo para descobrir que já é do jeito que eu programo.
uso um try catch só nas controller e fazendo ali o tratamento de erro pra retornar ao usuario, e na camada de services fazendo a validação, tratamento, e requisição dos dados e avisando seus respectivos erros com throw error
@@justrelax6144 MELHOR não usar pelo oq ele explicou
faço parecido aqui com FastAPI (Python) sempre que tenho alguma exceção eu dou um raise independente da onde esteja rodando, e dai tem um handler global de erro, que retorna o erro pro usuário.
Faço a mesma coisa em Java. Essa é na minha opinião a melhor solução. O Spring tem um recurso chamado Controller advice que permite vc adicionar um ErrorHandler que é executado automaticamente nos controllers. Vc nem precisaria de try/catch
@@chlima88 Isso é muito top, deixa o código muito limpo.
@@chlima88 fastify tbm, uso o erroHandler que quando da erro ele executa automatico. Show de mais
Quem tem problemas em usar try/catch tem que estudar mais sobre tratamentos de erros... Javascript pode até não ser a melhor linguagem, mas tem formas simples de tratar todos os erros.
Não é um problema ter blocos try/catch um dentro do outro, mas é necessário fazer o tratamento correto e subir as exceções para o local onde serão processadas, fazendo isso não existe os problemas comentados no vídeo. Tem que saber como a linguagem lida com as exceções e tratá-las.
Legal o conteúdo! Quando trabalho com node, gosto de criar um adaptador de rotas (inverter a dependencia do express por ex) e colocar nele o trycatch. Depois crio classes de erros que eu gostaria de dar throw (BadRequest, NotFound, Conflict, etc...) e faço uma tratativa para enviar um body personalizado pro front. Dessa forma, se receber um erro 500 quer dizer que realmente deu merda, mas como eu tratei lá no route adapter, não vai bugar tudo
Ótimas reflexões. Interessante como um simples try-catch pode gerar discussões.
Em um proximo projeto vou usar alguma variação desse result pattern.
Os vídeos desse cara sempre apontam a tecnologia como problemática, quando na verdade é a pessoa que não sabe utilizar.
Nos exemplos, temos vários métodos com apenas um try/catch, desse modo, o que esse método "pode" retornar deve ser tipado independente se você usa try/catch ou qualquer outra gambiarra.
Você só deve parar de usar try/catch se quiser que sua aplicação estoure erros sem dar contexto pro usuário, e claro, quando você não sabe usar a ferramenta.
É que eu acredito que certas formas de se fazer software são melhores que outras. O cara que criou o Null diz que null foi um erro. As linguagens evoluem e mudam. Python permitia antes mudar o valor de True e False. Agora não pode mais, as coisas evoluem conforme a indústria descobre maneiras melhores de fazer as coisas.
Eu acredito que existem maneiras melhores
Um bom exemplo é typescript. Eu acho que eu não faria código em JS puro pra absolutamente nada, typescript é só melhor na minha visão.
@@GutoGalego Eu entendi a questão da evolução, as pessoas evoluem e a tecnologia junto com elas.
O que eu estou com problema em entender é; como adicionar verbosidade ao algoritmo pode ser melhor do que usar tryCatch.
A verbosidade extra pode até tornar o código mais legível, mas o torna menos seguro, afinal, o que você programou ainda está sujeito a erros, erros que o tryCatch poderia tratar ou ao menos te gerar um log.
Se o assunto do vídeo é clean code, sinto muito pois entendi errado, achei que era tecnologia defasada.
Bom então vamos fazer o seguinte
A partir de agora vc só pode usar assembly, nada de linguagens de alto ou médio nível.
Agora, quero ver vc dizer que a culpa é do programador.
@@AlexeiDimitri você esqueceu de dizer que isso é uma suposição? Ou realmente é para eu usar somente assembly? Em qualquer caso, percebe-se que a falta de seguir certas regras, neste caso a gramatica, faz com que o programador cometa erros.
Tu quer dizer que assembly é ruim? Independente das habilidades do programador? Por favor, deixe-me entender seu raciocínio neste comentário.
Tive alguns problemas com Try Except em um código python por esse exato motivo. Essa abordagem do Go é bem interessante. Obrigado pela dica!
Me tira uma duvida boba mais pra mim e importante (ela vai na contra mao do video com seu raciocionio)
1 - Try-catch sem throw: Se você não usar throw dentro do bloco catch, o erro é capturado e tratado ali mesmo? Se sim o programa continua a execução normalmente após o bloco catch ?
2 - Throw dentro do catch: Se você usar throw dentro do bloco catch, a exceção é lançada novamente e propagada para outros blocos catch mais acima na pilha de chamadas, até que seja capturada novamente ou até que não haja mais blocos try-catch ?
3 - A exceção lançada com throw continuará subindo na pilha de chamadas até encontrar um bloco try-catch que a capture ? Se ele não encontrar, será tratada como uma exceção não capturada e pode terminar a execução do programa chegando ate o main?
pelo menos nas linguagens de JVM (Kotlin e Java) que tenho conhecimento o bloco continua sim, se não houver o throw ou o return o fluxo continua normalmente.
A resposta eh sim para todas as duvidas
9:56 - Trabalha cansado, com 3h de sono, fumando 9 prensados por dia, participando de 5 reuniões por dia, foda
isso pareceu muito específico, você ta bem?
Cara, pior fase da vida é essa ...Passei muito por isso.
Só parar de se drogar, espero ter ajudado 👍
@@chanela6135 Tem razão!
@@Miguel-y4o quando tu passa uma semana criando um componente super customizado , ai vem o QA enchendo o saco por causa da cor do botão , ou não executa a animação que ele queria
Sem mencionar que sair do fluxo principal ou contexto principal é extremamente imperformático, sendo considerado uma má prática por algumas linguagens antigas. É preferível usar return true ou false. Linguagens como Go sanam isso utilizando erro em formato de variável sem sair do contexto ( main ).
Primeiramente se você não tem um fallback que seja um retorno valido, você não deveria capturar e tratar o erro. Se a função que chama não souber tratar o erro, ela deve ser interrompida, assim como todas as funções anteriores.
Caso seja uma exceção inesperada deve ser capturada por um handler generico ao invés de matar a aplicação.
Caso seja esperada e impossivel de resolver como por exemplo uma requisição http onde um campo do body que deveria ser um numero é uma letra, você deveria capturar, e jogar uma exceção enriquecida com detalhes do problema no contexto dele: (InvalidPhoneException, causedBy IllegalArgumentException). Nessa situação nada além de dar o feedback na response deveria acontecer. então você só vai capturala e tratala na hora que for buildar a response, nesse momento todas as funções anteriores já foram desepilhadas.
Caso seja esperada e souber resolver, captura resolve e retorna a solução.
A mesma coisa é no Go, se a função que chamou não souber tratar o erro, retorna o erro, para a anterior tentar. O que não gosto do Go é isso, tem que escrever toda vez if (err!=nil ) return err, quando que em outra liguagens é só não capturar o erro, que o comportamento é o mesmo.
Existem exceções mas no geral é isso.
Muito bom vídeo, foi uma das coisas que mais gostei em Go quando comecei a alguns anos atrás, é o fato do error não ser um objeto concreto na linguagem, podendo interagir com o tipo dele de forma mais livre, mas ainda assim existe uma espécie de "try/catch" em go. Mesmo em funções que não retornam erros diretamente, existe uma possibilidade de uma exception ocorrer. Se forem funções de pacotes padrões do Go provavelmente o motivo é que parte do processo dessa função está acontecendo fora do escopo em que o runtimer do go pode vistoriar ou acessar, ou se for um pacote criado por você ou pela comunidade, pode ocorrer se a função "panic" for chamada. Basicamente ela é para funcionar de forma similar as outras linguagens, mas no momento em que a exception quebra a pilha e encerra o programa, ela basicamente recebe um any e vai quebrar a pilha de execução inteira e retornar o que ela recebeu como exception, mesmo que nem seja uma, inclusive. Caso esse panic ocorra, vc pode usar o defer juntamente com a função recover para poder fazer algo em cima desse erro que gerou o panic. Eu particularmente acho essa parada de Panic/Recover meio dúbio, mas entendo a necessidade dela na linguagem. De qualquer maneira, a forma padrão de se lidar com erros em Go é como descreveu, e realmente evita bastante esse problemas de Try/Catch.
Em basicamente todas as linguagens o erro é um tipo concreto
@@FernandoSilvaSousa acabei esquecendo o NÃO na frase e invertendo a minha colocação, em go, o typo error não é um tipo concreto e sim uma interface
bom vídeo Galego! traz um vídeo ensinando a configurar um ambiente python minimamente decente
Upp
Vai sair, já ta agendado
Falaram mal do GOTO e a solução mais elegante que conheço para erros é vinda justamente da linguagem que mais usa GOTO: BASIC.
Algumas versões tem algo simples assim:
ON ERROR GOTO LINHA XXXXXX
Na primeira linha de seu programa você fazendo isso, desviará qualquer erro para aquela linha (XXXXXX). Lá você põe a rotina que você usará para no mínimo te mostrar o que houve. Sem Try e Catch antes do Try e Catch para saber se houve error no TRY ou no CATCH....
XXXXXXX PRINT #LIN, #ERR, etc...
Algo parecido com isso, lhe mostraria a linha onde houve o erro e a mensagem de erro. Simples e funcional.
5:14 Python tem tipagem forte e dinâmica
Muito bom o vídeo, concordo que try catch não é o ideal na maioria das vezes. Mas o que mais me deixa puto é o pessoal falando que o problema não é o try catch, e sim o programador. Pessoal ignora qualquer defeito de uma linguagem falando que a culpa é da pessoa que tá usando, algo que é muito injusto. Se o programador de hoje em dia comete os mesmos erros que o programador de 30 anos atrás, não é a pessoa, é a tecnologia, mas o pessoal não aguenta outros falarem mal da linguagem favorita deles
Caramba q legal, li sobre isso hj no livro arquitetura limpa do uncle bob, ele cita esse artigo do Dijkstra e fala a respeito. Que massa!
meu deus, esse video caiu como uma luva para mim kkk to começando a POO e try/catch é beem necessario , e to estudando python. mt obrigadaa
Interessante! Estava justamente utilizando try e catch quando o YT me recomendou esse vídeo kkkk +1 inscrito! Sempre muito bom está atualizado
se try/catch é ruim, então como fica o tratamento de excessões?
Muito bom, inclusive outro grande problema é que exceptions sobem o consumo de recursos por carregar a stack trace por N camadas.
Tá aí um dos motivos de eu gostar tanto de Go - erros são valores e você é obrigado a tratá-los (além de que fica sempre explícito na declaração de uma função caso ela possa retornar um erro)
sobre python: em resumo sobre os linters se quiser verificar tipos e qualidade de código na hora do desenvolvimento utilize o mypy (se possível strict), e o ruff. Se quiser verificar tipos em execução o pydantic faz o trabalho.
python é uma linguagem de tipagem dinâmica e forte.
Mano se tivesse mencionado a questão do uso de memoria para manter a stack trace do erro quando ele é lançado nas camadas mais internas até faria sentido que vc ta falando. O código que vc mostrou tem tantos problemas que eu não acho que é culpa do try/catch kkk. Mas é muito bom o pattern do GO do either ou result.
Ninguém usa try catch dentro de try catch. Geralmente se usa o try catch somente para não quebrar a aplicação com erros desconhecidos e os erros conhecidos são retornados normalmente
Tudo depende da lógica que vc tá usando e do fluxo de controle
Na real é bem comum em frameworks haver um módulo chamado exception handler que visa tratar qualquer exception que subir sem tratamento, tem que haver isso pq chega uma hora que fica repetitivo tratar o mesmo tipo de erro do mesmo jeito em vários lugares
Galera em C usa goto para lidar com exceções. Esse tipo de implementação lembra try/catch apesar do mecanismo de “rewind” ser diferente
Além disso, em linguagens que tem a sugar syntax `?` leva a erros mais sutis na hora de debugar o erro no log (devido a falta de trackback)
Try/catch não é péssimo, exceto se você estiver usando ele da forma errada, isto é, pra fazer controle de fluxo de execução (ao invés de usar if's) ou silenciando erros. De igual forma, propagar erros através da call stack não é um anti-pattern, pelo contrário, auxilia ao usuário da sua API tratar o erro na camada de abstração correta.
eu como uso c# nao tenho esse problema, pois é facilmente resolvido entre client e api com, inclusive uso muito return em void para justamente parar a execução de codigo quando algo esta faltando/errado, é so saber usar as ferramentas da linguagem de maneira apropriada
O que eu uso bastante é criar os erros extendendo da class Error pra depois controlar no catch com o instanceof.
hahah péssimo porque não sabe usar Exceptions hahahaha
Muito raro os casos que realmente precise usar try e catch assim. igual falou. Consigo pensar agora quando precisar dar um rollback
Ou vc pode usar "result, _ := divide(10, 0)". Claro que quando vc faz isso as vezes costuma ser com motivo, mas pode acontecer. Acho que Rust lida com erros de uma forma muito mais "chata" mas bem mais efetiva
Esse tipo de coisa acontece pq vc tá pensando de forma sequencial numa linguagem nativamente assíncrona e funcional.
Em geral se vc tá usando async/await é pq vc tá fazendo errado.
Como vc lida então com exceções e consegue controlar o fluxo de trabalho? Simples, usando Promises e usando máquina de estados.
Vc usa os promises para mudar o estado da sua aplicação
E a sua aplicação basicamente reage a essas mudanças de estado
Como vc faz o usuário participar disso? Sua aplicação mapeia a interface para o estado da aplicação
E promises fazem o trabalho de sincronizar o estado local com o estado no servidor.
Ë o mesmo motivo pelo qual um programador burro pega um I/O que é assíncrono e dá um jeito de torná-lo síncrono. Vc tá ocupando recursos que não deviam estar travados e deixando a aplicação menos responsiva, pq o thread principal do JS tá esperando o resultado daquele I/O.
Em 5:42: tecnicamente falando, inner_method NUNCA retorna, então não faz definir um return type para ela. Ela SEMPRE vai estourar um ZeroDivisionError e nunca retornar.
Se você quiser ser preciso, o correto é definir inner_method como def inner_method() -> typing.NoReturn, ou então, em python3.11+, typing.Never, que são os mesmos tipos utilizados para funções que ficam em loop infinito:
def main() -> typing.Never:
while True:
pass
Uns dizem que não pode usar else, outros try/catch. Qualquer recurso de fluxo de controle que for mal utilizado vai resultar em código ruim e pouco previsível.
Eh bem previsível q vai ser ruim, rs
De vez em quando a Internet dá uma sequelada, try catch não é nenhum pouco parecido com Goto, que podia avançar, a exception só retorna, ele tá mais pra um if + return implícito, já que de fato retorna um objeto.
Tá maluco, teu conteúdo é bom demais meu querido
Pior que, até no Java, onde tu tem a tipagem certinha e ele obriga a colocar o throws na assinatura do método, todo esse argumento vale, porque pode ter levantado um RuntimeException ou algo assim que não é obrigado no throws. E, pior que, se colocar pra obrigar, quebra tudo kkk
Dê semantica pros errors: validation, error, unexpected, unavailable. Cria uma função pra mapear isso na camada superior e lançar o status correto. Faz mais uma validação pra garantir que os dados vão ser executados corretamente na regra de negocio. Simples assim.
Um dos poucos vídeos que discordo fortemente do galego, esse pattern de result ofusca completamente a stack trace quando um erro acontecer, citando java, tenho a sensação que é como fazer try catch pra lidar com erros ao invés de exceptions
Linguagens que já tem algo parecido nativamente ok, como go e rust, mas se não, vejo a aplicação como uma muleta pra uma certa incapacidade de algum sênior em transmitir o conhecimento necessário de estrutura de dados aos mais novos
Não oculta, pelo menos em JS é só retornar um new Error()
@@cca9837 mesmo que ele retorne um error, a stack trace vai ser do momento que lançar o erro (throw error) e não do momento que o erro aconteceu
@@allefgaruda o colega acima claramente não sabe o que é o stack trace :x
Eu não sei se é uma boa idéia usar "padrões" para emular comportamentos de outras linguagens ao invés de usar melhor aquilo uma linguagem já oferece de maneira nativa.
Programo em Python e nunca tinha visto esse result pattern mas faco isso instintivamente porque já sofri muito com esse tipo de problema kakaka error_, result = funcao_faz_algo(param) if error_ ....
O exemplo inicial, com um try/catch dentro de outro try/catch não é bom, pois já indica um problema de design, que deveria ser corrigido antes de tudo.
Você tem o melhor canal da bolha, parabéns!
Putz mas aí usando assim, é ruim mesmo. Agora se souber usar, vc padroniza o erro, deixa mais rastreável, evita quebrar a API exceto quando é necessário, e sem 'mascarar' os erros também. Como dizia o grande poeta, "modéstia a parte, código ruim, eu sei fazer muito bem, em em qualquer linguagem, e com qualquer paradigma..."
Nunca gostei de usar try catch como uma estrutura para error handling. Estes dias precisei usa-lo para retornar um objeto diferente caso a API estourasse uma excessão, e para este caso, ele foi bem últil.
Porquê diabos as pessoas não focam em usar Guards para evitar usar Try/Catch? Eu nunca entendi essa tara estranha das pessoas de querer garantir o resultado sem garantir que o processo esteja correto. Try/Catch só se usa em condições que seu código não pode garantir um fator externo como um banco de dados falhar na inserção de dados e mesmo assim você pode usar um circuit-breaker em situações assim(Aqui tem que ter atenção).
PS: Leiam sobre programação defensiva.
Mas isso é óbvio, ele usou try-catch assim só para demonstrar. Realmente try-catch só se usa quando se recebe dados externos.
Tá, e aí você faz o quê quando seu guard falhar?
@@dfeprado Você só aceita que não sabe os detalhes do que você esta programando e também aceita que não testou o seu software adequadamente.
Segundo a definição de guards segundo a Wikipedia: "Em programação de computadores, uma "Guard clause" é uma expressão booleana que deve ser avaliada como verdadeira se a execução do programa deve continuar no branch em questão. Independentemente de qual linguagem de programação é usada, uma "Guard Clause", é uma verificação de pré-condições de integridade usada para evitar erros durante a execução."
São estilos diferentes (LBYL e EAFP), mas não quer dizer que é pra garantir um "resultado que encaixe". Em resumo, eu diria que a diferença é sobre tratar a possibilidade de erro antes ou tratar o erro depois, se ele acontecer. O que tem que ser feito com o erro vai ser o mesmo para os dois casos: tratar como deve ser tratado pra cada caso. Essa história de usar o try/catch pra mascarar não é problema de try/catch. É do programador mesmo.
@@alexandreabto Exatamente. Eu prefiro mil vezes considerar usar Try/Catch numa situação onde eu estou querendo salvar um dado num banco de dados e eu não posso garantir que fulano ou beltrano não vá tropeçar nos cabos de energia do servidor e perder conexão do que usar Try/Catch deliberadamente para qualquer função que eu chamar na garantia de que elas não falhem. Com apenas Guards eu consigo esgotar quase todas as possibilidades de erros na função que eu tento executar.
Linguagens funcionais tentam lidar tratamento de erro usando guards/pattern matching e torna as coisas tão simples quanto.
Do meu ponto de vista, o problema com o try/catch é o exagero.
Eu mantenho sempre um padrão nos meus códigos que é o de deixar quebrar sempre que possível.
Eu vou ter apenas no nível mais alto da aplicação, e apenas em casos onde preciso dar rollback em uma transaction do banco e afins, caso contrário, nem isso, deixo pro meu "try catch global" lidar com o erro, registrar logs e retornar uma mensagem de erro adequada ao cliente.
Eu não entendo como seria diferente das linguagens que tem try-catch mas tem null-safety. Porque elas não te deixam retornar null quando a função diz que retorna um valor, mesmo usando try-catch
Esse principio de "não mentir" um comportamento é semelhante ao principio de substituição de Liskov no SOLID.
Eu sempre uso o try-catch. Caso dê algum erro eu aciono minha tabela de logs para salvar a cagada que rolou. Isso simplesmente me salva de ficar procurando erros quando eu recebo algum ticket.
Não gosto da ideia de "misturar" o fluxo de exceção com o fluxo esperado, eu prefiro disparar uma exceção e criar um tratamento isolado para lidar com ela isolando responsabilidades.
Que video incrível. Parabéns!
Mas fiquei com uma certa dúvida, qual seria diferença então de usar um
- Try Catch
ou
- Then Catch -> promise().then(...).catch(...)
Saberia explicar?
Mesma coisa, basicamente no `then` você está pegando o valor do try, e no `catch` o do próprio catch, porém essa forma de then, catch é meio complicada pois você pode encadear muita coisa aí, e deixar o código difícil de entender.
@@franciscopessoa655 Hmmm, entendi. Valeu meu querido!
Try catch é a forma mais atual de se usar, pois no ES6 surgiu o async await, promise.then() era a forma que era usada anteriormente.
Se for escolher entre os dois, use async await com try catch
Eu gosto muito de Go, mas acho muito estranho usar no Javascript. Gosto da ideia do lint ou algo do tipo mesmo
A desculpa é que trabalha cansado? kkk
Foi mal, desce não.
Se você precisa de uma linguagem para não "te deixar mentir", como você disse, o problema é com você.
De toda maneira, se você programa porcamente, seu código será ruim, independente da linguagem.
Como resolve isso? Escrevendo testes bem feitos. Isso, sim, vai pegar todos os erros e não deixar você subir código mal escrito para produção.
no type script ele reclamaria avisando que o retorno pode ser nulo
Não sei se é porque estou muito acostumado a ver try/catch que não vejo as coisas que falou como problema, contando que não se minta o retorno, tenha retorno padronizado e devidamente documentado.
Acredito que você Augusto, talvez tenha se equivocado ao falar que GOTO é uma relíquia, pq no final do dia, if/else/while, todas as operações de controle de fluxo são um mero GOTO, por mais que não "codemos" usando GOTO, quando a linguagem é interpretada/compilada para assembly, o código é transformado para assembly usa os jumps na 'tradução' do código, que são os GOTO, redirecionando o fluxo do código para algum endereço x do Program Counter.
Isso falando no nível da CPU!
Abraços, me corrija se eu estiver errado.
Na minha opinião a linguagem que melhor lida com esse problema é Rust usando Result pattern + Match pattern
Acredito que a linha argumentativa foi meio fraca, quanto legibilidade está okay, mas apresentar apenas a ideia deste modo foi muito simplório e no fim só diz que a culpa é do programador sem indicar que existe um problema real que é a perda de performance devido utilização de exceções pra controle de fluxo
assistindo o vídeo como se tivesse entendendo alguma coisa ( não entendi nada), mas sabendo que daqui um tempo vou voltar e entender tudo
Esse exemplo do post já não faz sentido porque o cara botou um try catch dentro de outro só pra mudar a mensagem de log. Se isso não é importante (quase nunca é) vc pode sempre usar apenas um try/catch e o catch ser log generico como "console.error('error', error.toString)" ja que a mensagem do erro ja vai dizer o que aconteceu.
1:40 sempre pensei nisso, tava até na dúvida se tinha um try catch reverso, onde a exception vem antes justamente pra facilitar a leitura
afinal, onde caralhos eu trato o erro? lá em baixo ou lá em cima quando borbulhar?
Discordo q seja o try catch. Pois isso varia por linguagem. No próprio Java, que usa try catch, tb te obriga a tratar a exceção se vc chama um método q pode lançar uma exceção, vc soh escolhe se vc vai tratar ou se seu método tb vai explicitamente jogar ela pra cima
como configurar o mypy / linter decentemente? sei lá o que mais você falou
Tive exatamente o mesmo problema em prod por retornar um valor inconsciente em um catch
Conteúdo interessante. Só um detalhe: Python tem tipagem forte. O fato de não precisar declarar o tipo, não torna a tipagem fraca.
Acho que tudo e balanca... nao sou faaaazaaaasssso do try catch mas vc poderiater um try catch e um roll back no catch... agora try catch dntorde try catch dentry d try catch... isso e problema do dev e como ele esquerve o go horse dele, a feramenta e neutra e pode ser bem utilizada... tipo eu usando com um rollback em situacoes especificas.
Em planilhas excel com VBA usamos GOTO até hoje ;)
to na pré-estréia 🤩
Flamewar. Cansado como dito para arguementar com colocação sem sentido que mais adiciona complexidade do que auxilia. :)
Eu postei do vídeo, mas tenho uma dúvida um pouco fora do conteúdo, Como eu paro de ser um programado mesquinho,
Tipo: sinto que estudo a um tempo e não tenho uma evolução
Tu é da banda de Recife (vi postando q tá morando na itália) ? Essa coral aí no braço...
Concordo Andre. O futuro é essa internet paralela
Poh mano... Tanto o exemplo péssimo de try/catch como o exemplo de solução de uso, são em TS/JS, o que me leva a conclusão, o problema é o noob que escreve igual o exemplo 1 e não a linguagem em si. não importa qual linguagem, se o carra escrever no go horse vai ser ruim de ler de qualquer jeito....
boa, to fechado. fico confuso pq diabos tem gente defendendo try-catch, quase que com um apego emocional 🤔 acho q se a linguagem é precária tipo JS blz, não tem muito o que fazer... Mas dado que a sua linguagem suporta algo mais ergonômico, tipo Result/Either como a gente tem em OCaml/Rust, realmente não tem um argumento plausível para achar que é uma ferramenta boa. Na boa, só vai defender try-catch ou quem nunca viu algo melhor, ou quem tem um filtro baixo pra qualidade de código, falei mesmo kkkkkk 🤷♂️
O problema não é o try catch, MAs sim como você usa. Esses exemplos aí obviamente são um mal uso do recurso, mas não que o try catch seja o problema. O título ficou bem sensacionalista e a explicação bem tendenciosa.
Essa forma que mostrou lembra um pouco o Monad Either.
Os argumentos do vídeo estão corretos, porém incompletos (existem ainda mais motivos pq o try catch é ruim).
O próprio fato das exceptions serem tratadas dessa forma torna ainda mais difícil de diferenciar quais erros devem ser tratados pela aplicação (erros recuperáveis), dos erros de lógica e bugs (erros irrecuperáveis). E sim, um programador experiente consegue diferenciar e implementar de forma correta, porém, á própria linguagem de programação não o deveria induzir a cometer este tipo de engano.
Por isso, eu até argumento que o try catch deveria ser considerado uma feature ruim no design de uma linguagem de programação.
Fun fact: um requerimento para ter o try catch é possuir um mecanismo de "unwinding" (_desenrolar_ call stack) o que além de ser difícil de implementar, em linguagens compiladas (Rust, se não me engano, isso acontece no C++ também), o compilador é impossibilitado de fazer algumas otimizações, já é necessário considerar que em "qualquer ponto" a execução pode ser interrompida. Artigo: Unwind considered harmful
Porque caralhs alguém usa try catch dentro de um try catch se ocorrer um erro vai dar na mesma e seria mais fácil tratar esse erro 🤯
Gente, alguma ideia de padrão pra ter esse tratamento de erros melhorado no Kotlin? (Puro ou Android)
Eu sempre uso try/catch, evito usar múltiplos. mais seguro.
Ninguem entendeu o ponto central, não se trata de ser o melhor ou pior, ou condenar try/catch
Se trata do ferramental que vai mitigar erros automaticamente, obvios que existem excelentes patterns pra usar com try/catch problema é garantir que os 500 devs numa empresa vao seguir isso
Como ele disse, tanto quem ta fazendo, quanto quem ta revisando pode estar cansado e deixar, so vao descorbrir quando o cliente reclamar
Sobre o pessoal falando que Go fica muito verboso pra sistemas enormes, na minha opniao nem deveria existir mais sistemas enormes, mesmo se for monolito poder ser feito com arquitetura modular e ddd justamente pra dividir ben o escopo e deixa facil de implementar e manter
Pessoal nao percebe o proprio viés, facam como o Galelo e critiquem sua própria stack mesmo gastando e usando ela
Não é péssimo, imagina que você precise usar middlewares ou conexões assincronas, a maioria das libraries q adotam essas técnicas usam try catch não tem como fugir a não ser que você desenvolva todo seu domínio sem nenhuma dependencia ou escolha tudo a dedo isso é loucura. escovação de bit de maluco. O negócio é criar observabilidade com logs em caso de catchs serem estourados...
Não é só um padrão é code smell