6 pontos por GN⁺ 2025-01-01 | 2 comentários | Compartilhar no WhatsApp
  • Propostas de design de sistemas que começam com “let’s just” geralmente acabam sendo muito mais complexas do que o previsto, e um bom julgamento arquitetural depende fortemente de regras práticas e da compreensão do contexto
  • Estruturas de plugins, adição de APIs e camadas de abstração podem parecer plausíveis, mas na prática precisam lidar ao mesmo tempo com compatibilidade de comportamento, manutenção, segurança, desempenho e demandas do ecossistema
  • Processamento assíncrono, controle de acesso e sincronização de dados parecem temas familiares, mas em ambientes de produto tendem a levar a bugs difíceis de reproduzir, redesenho do modelo de segurança e desafios de sincronização
  • Cross-platform e saídas nativas (native escape) podem ser válidos em produtos iniciais simples, mas, quando os recursos da plataforma e o estado interno divergem, fica difícil manter qualidade e consistência
  • Esses padrões nem sempre estão errados, mas na maioria das vezes não são necessários ou têm alternativas; em vez de abordagens propensas a falhas, é preciso repensar o problema a partir de primeiros princípios (first principles)

Por que “let’s just” é perigoso

  • Propostas que vêm depois de “let’s just” em 9 de cada 10 casos se tornam um trabalho muito mais complexo do que o previsto na sala de reunião
  • A engenharia também tem um caráter de ciência social, então o que funciona é dependente do contexto
  • Quando alguém diz que uma abordagem não funciona, isso costuma ser recebido por engenheiros como um desafio para provar um contraexemplo
  • Grande parte da gestão de engenharia e da arquitetura de software é uma combinação de regras práticas (rule of thumb) obtidas pela experiência e lições aprendidas com dificuldade

“Vamos só torná-lo plugável”

  • Quando uma única implementação parece insuficiente, encaixar uma nova implementação na mesma arquitetura parece permitir que os chamadores da API obtenham melhorias ou novos recursos sem mudar nada
  • Mas, como “a API não é o arquivo de cabeçalho nem a documentação, e sim o próprio comportamento”, quase não existem plugins que simplesmente funcionem
  • O componente mais próximo de um plugin no software moderno é o driver de dispositivo
    • No passado, drivers tinham baixa qualidade de comportamento, algo que deixou de ser aceitável, ou os sistemas operacionais modernos passaram a construir seus próprios drivers
  • Para criar uma estrutura realmente plugável, é preciso projetar uma segunda implementação ao mesmo tempo que a implementação básica; só assim há ao menos uma prova de que funciona uma vez

“Vamos só adicionar uma API”

  • Depois que um produto ou empresa alcança certo sucesso, é comum adicionar uma API dizendo que é preciso “virar uma plataforma e atrair desenvolvedores”
  • Quem fornece a API precisa fazer concessões contínuas entre adicionar funcionalidades e manter compatibilidade e interoperabilidade, e sua liberdade de mudança fica muito reduzida por causa do comportamento existente e das características de desempenho
  • O fato de haver uma API não significa que alguém necessariamente queira usá-la
    • Novas APIs muitas vezes surgem quando o produto quer alguma funcionalidade, mas não a coloca alto o suficiente nas prioridades internas
    • O mercado-alvo pode ser pequeno, verticalizado ou restrito a um domínio específico, levando à expectativa de que parceiros externos preencham a lacuna via API
    • Esses parceiros também têm seus próprios negócios e clientes, então podem não querer resolver o problema adotando mais um produto
  • Tornar-se uma plataforma é um negócio com demanda real significativa, e raramente algumas APIs bastam para criar uma base econômica para terceiros

“Vamos adicionar mais uma abstração”

  • A frase de Butler Lampson, “todos os problemas da ciência da computação podem ser resolvidos com mais um nível de indireção”, contém uma verdade real
  • As falhas geralmente aparecem de duas formas
    • Uma abstração introduzida cedo demais fica na arquitetura como abstração excessiva, sem um plano real de uso
    • Uma abstração adicionada depois pode tornar manutenção, segurança e otimização de desempenho muito complexas
  • O Windows NT tinha desde o início muitas abstrações excessivas que nunca foram usadas de fato
  • Na evolução do Mac OS, houve casos em que uma abstração que inicialmente parecia estranha se mostrou útil duas versões depois; a diferença era a existência de um plano
  • Quando uma abstração posterior é usada apenas em parte do código, muito código deixa de usar a nova abstração, aumentando o ônus de manutenção

“Vamos torná-lo assíncrono”

  • Uma parte considerável dos primeiros 25 anos da ciência da computação foi dedicada a entender e implementar comportamento assíncrono
  • Nos cursos de pós-graduação dos anos 1980, temas como jantar dos filósofos, produtor-consumidor e o barbeiro dorminhoco eram tratados por bastante tempo
  • Hoje, muitos engenheiros lidam com problemas assíncronos de forma amplamente abstraída graças às regras da camada de dados e aos frameworks web
  • Quando se gerencia assincronia diretamente fora de um framework ou da camada de dados, tudo pode parecer funcionar bem no começo, até que um ano depois surjam bugs difíceis de reproduzir
  • Só resta torcer para que esses bugs não sejam problemas de corrupção de dados

“Vamos adicionar controle de acesso depois”

  • O local do controle de acesso já foi objeto de debates teóricos, mas os sistemas atuais vivem em um ambiente muito mais complexo, pois estão sob ataque constante
  • Todos sabem desde o início que segurança é necessária, mas, por causa da velocidade de lançamento no mercado, quase nenhum sistema tem controle de acesso e modelo de segurança totalmente projetados desde o começo
  • Se você não começar pela perspectiva dos clientes e dos atacantes, é difícil criar um design de controle de acesso adequado ao produto
  • A abordagem de encaixar controle de acesso depois pode falhar ou levar a uma situação em que o produto precise ser reescrito no futuro
  • Essa reescrita se torna uma experiência ruim para todos, inclusive para os clientes

“Vamos sincronizar os dados”

  • Em ambientes com vários dispositivos, apps SaaS e armazenamentos de dados, a proposta “vamos só sincronizar os dados” aparece com frequência
  • Como enfatizou Ray Ozzie, pioneiro em client/server e sincronização de dados, sincronização é um problema difícil
  • Em ciência da computação, um problema difícil significa algo muito complicado, com muitos desafios que só podem ser aprendidos pela experiência
  • Mesmo em armazenamentos de dados com semântica completa e transações, a sincronização é difícil; quando entram blobs, dados não estruturados e transformação de dados, a dificuldade aumenta rapidamente
  • Basear uma solução em sincronização de dados quase nunca é a escolha desejada, e é por isso que existem empresas de dezenas de bilhões de dólares sustentadas apenas por sincronização

“Vamos torná-lo cross-platform”

  • Cross-platform é um debate repetido há muito tempo, e sempre há quem diga que o código que criou funciona bem ou cite Unity e jogos como exemplo
  • Dizer que vai tornar algo cross-platform é, na prática, quase como prometer criar um sistema operacional, um provedor de nuvem ou um navegador
  • Cross-platform funciona bem em dois casos
    • Quando a plataforma é nova e simples, por exemplo quando a nuvem está no nível de computação e armazenamento simples
    • Quando a aplicação ou produto é novo e simples
  • Essas condições deixam de valer quando você começa a divergir da plataforma base ou a criar recursos que se expressam de maneiras completamente diferentes em cada plataforma-alvo
  • A Microsoft teve dificuldade em criar o Office para Mac e o Office para Windows com o mesmo código, então fez um fork do código do Office em 1998 e nunca voltou atrás
  • Originalmente, a Microsoft existia como um negócio de criar aplicativos cross-platform, mas isso funcionava bem numa época em que a documentação das APIs de SO tinha cerca de 100 páginas e cada SO derivava do CP/M
  • Texto relacionado: Divergent Thoughts on Cross Platform

“Se necessário, deixamos escapar para o nativo”

  • Como cross-platform só funciona bem por um curto período, frameworks e abstrações de API frequentemente oferecem uma saída nativa (native escape)
  • A ideia é permitir chamar diretamente a plataforma nativa para recursos que surgiram com a evolução da plataforma e que o framework ainda não expõe
  • Mas frameworks ou APIs que oferecem abstração mantêm estado interno ou caches
  • Ao chamar diretamente a plataforma nativa, estruturas de dados e estados que o framework desconhece são alterados
  • Alguns frameworks fornecem mecanismos para trocar dados ou estado entre o código de escape e o framework, mas isso se aproxima de uma solução como reintroduzir uma arquitetura do tipo malloc/free na era do gerenciamento automático de memória

Você pode escolher, mas não é o padrão

  • Isso não significa que a resposta para essas abordagens deva ser sempre “não”
  • Em certos contextos, esses métodos podem funcionar
  • Porém, na maioria dos casos, esses padrões não são necessários ou há uma forma melhor
  • Em vez de pegar primeiro padrões de software com alta probabilidade de falha, é preciso resolver o problema a partir de primeiros princípios

2 comentários

 
ndrgrd 2025-01-02

No caso de plugins, o mais importante é projetar a interface filtrando ao máximo apenas os comportamentos essenciais.
Se a interface for criada apenas copiando uma estrutura aproximada do código atual, ela acaba virando uma interface desnecessária que fica presa àquela implementação, e é realmente comum que isso aconteça...

 
GN⁺ 2025-01-01
Opiniões no Hacker News
  • O problema com ideias desse tipo está menos na ideia em si e mais na abordagem ou nas expectativas do tipo “é só fazer” que vêm antes dela
    Por exemplo, se você trata uma API como “só mais um recurso” do produto, dizendo “é só adicionar uma API”, a taxa de sucesso provavelmente será parecida com a de “é só adicionar uma UI”
    Para criar uma boa UI, é preciso cuidado e rigor, além de especialistas na área
    Não há motivo para que outra interface do produto seja diferente; o ponto central não é se a ideia é ruim ou boa, mas que é algo que não deve ser feito no modo ‘é só’

    • Em um emprego anterior, havia uma regra
      A única pessoa que podia dizer “é só” era o desenvolvedor que realmente seria responsável por fazer aquilo funcionar; se outro desenvolvedor dissesse isso, era como se estivesse se voluntariando para assumir a tarefa
      Era uma regra que funcionava bem para nós
    • Concordo. Ao adicionar uma API, não existe “é só”
      Para criar uma API direito, entram muita arquitetura e complexidade
      Se ela não for bem projetada, o cliente pode ter de fazer várias chamadas quando uma só bastaria, ou a API pode ser confusa a ponto de ser chamada de forma errada ou nem conseguir ser usada
      Também são necessárias autenticação e autorização, o que implica configurar OAuth2 ou, no mínimo, ter geração, armazenamento e validação seguros de tokens de API
      Os dados também precisam ser tratados com segurança e, se o desempenho for ruim, o banco de dados pode acabar esmagado pela carga
      Ao adicionar cache, entram a invalidação de cache e a complexidade de servidores e processos para dar suporte a ele
      Sem rate limiting, um cliente malfeito pode ficar martelando a API; se a documentação for ruim, ela praticamente não serve para nada
      Dependendo do caso, é preciso até fornecer SDKs para várias linguagens, e, sem boas mensagens de erro, usuários de primeira viagem não sabem por que a chamada falhou
    • A maioria dos conselhos profissionais se parece com conselhos amorosos
      A pessoa generaliza algo que deu errado para ela, mas isso quase nunca se aplica diretamente a menos que você seja a mesma pessoa em uma situação muito parecida
      Os conselhos que continuam acertando são tão genéricos — “pense com cuidado, tente fazer a coisa certa e reflita sobre os resultados” — que acabam sendo quase inúteis
      Com esse tipo de frase, também não se vendem muito bem posts de blog ou livros
    • A profissão de pré-vendas parece existir quase inteiramente por causa da palavra “só”
      Afinal, é preciso garantir que o cliente não se assuste quando você começar a erguer para fora d’água o restante do iceberg
    • Concordo. O posicionamento do texto teria sido muito melhor se fosse “o que de fato é necessário para fazer ideias de sistemas ‘simplesmente’ funcionarem
      Assim, o texto deixaria de ser sobre possibilidade/impossibilidade e passaria a ser sobre os modos de sucesso e fracasso
      Quando você passa a conhecer os detalhes necessários, fica mais difícil dizer “é só” sem saber o que não sabe
      Dito isso, concordo quase 100% sobre DSLs
      Elas se aproximam de uma complexificação desnecessária e metida a bonitinha; quem estaria qualificado para criá-las deveria ser alguém que já fez uma linguagem de programação bem-sucedida e, incorporando os erros, chegou a atualizar uma segunda edição ou até uma segunda linguagem — e ainda assim errou muita coisa
  • (1) DSLs às vezes funcionam muito bem. Veja https://www.jooq.org/
    (2) O Elastic Load Balancer é um loop de controle que reage à carga de trabalho, e esse tipo de coisa já é uma tecnologia de uso geral
    (3) Na maioria das indústrias, o subprovisionamento é generalizado. Veja https://erikbern.com/2018/03/27/waiting-time-load-factor-and... e https://www.amazon.com/Goal-Process-Ongoing-Improvement/dp/0...
    (4) Detecção de anomalias não é, em essência, um problema de sistemas distribuídos como os outros itens, mas alguém que já se queimou feio pode sentir que precisa disso
    Também é uma área intelectualmente difícil
    O primeiro algoritmo que me pareceu minimamente inteligente foi https://scikit-learn.org/1.5/modules/outlier_detection.html#..., e às vezes funciona como mágica
    Quando apliquei a texto com embeddings baseados em CNN que eu usava em 2018, funcionou bem, mas com SBERT não tive sorte nenhuma

    • Escrevi duas DSLs, uma delas junto com uma equipe, e considero que ambas foram bem-sucedidas
      Resolveram o problema e ninguém reclamou
      Acho que o fator mais importante foi que ambas eram pequenas
      Eram muito parecidas e reutilizavam código
      Uma servia para escrever regras de validação de formulários enormes, e a outra para escrever regras de decisão com base nas respostas dos formulários
      Uma boa DSL permite que alguém que não conseguia fazer algo passe a conseguir
      Uma DSL criada para economizar tempo tem muito menos chance de ser útil, porque é bem provável que na prática não economize tempo
      Em ambos os casos, precisávamos trazer para dentro do programa um comportamento de domínio complexo
      Então é preciso ensinar o domínio ao programador, colocar programador e especialista de domínio para trabalhar juntos, ou ensinar programação ao especialista de domínio
      Se houver muito trabalho, é atraente dar poder às mãos dos especialistas de domínio
      O programador pode fazer outras coisas e o loop de feedback fica mais curto
      Se o domínio for profundo, você provavelmente não vai querer mandar o programador para a escola para aprendê-lo; se for raso, alguém mais barato talvez consiga cuidar disso
      DSLs trazem uma grande carga cognitiva
      Mas, se a alternativa for aprender uma linguagem de programação completa, elas passam a fazer mais sentido
      DSLs para economizar tempo são o caso em que alguém que já sabe programar quer escrever menos código; como a economia é pequena, em geral não valem muito a pena
      Aí, quando um programador precisa mudar alguma coisa, em vez de um código intuitivo ele precisa aprender ou lembrar essa DSL inteira
      Como regra prática mais simples, uma DSL para programadores tem menos chance de ser uma boa ideia do que uma DSL para não programadores
    • jOOQ é um desastre e eu não recomendo a ninguém
      Você escreve consultas SQL, testa em uma ferramenta como o DataGrip e depois passa horas descobrindo como converter aquilo para a DSL
      O problema piora quando se usam recursos SQL “exóticos”, como expressões JSON
      A depuração vira um fluxo de “imprimir o SQL gerado, copiar para algum lugar como o DataGrip, ajustar a consulta e depois descobrir como encaixar isso de volta na DSL”
      É uma perda de tempo enorme
      O principal argumento de venda do jOOQ são as consultas com segurança de tipos, mas isso perdeu importância quando o IntelliJ passou a validar SQL em strings dentro do código contra os dados reais
      O fluxo de editar SQL diretamente e testar logo no banco de dados é simplesmente melhor
      O jOOQ reforça a tese do post original sobre DSLs
    • Tirando coisas como expressões regulares, nunca vi uma boa DSL, e mesmo delas ouvi dizer que muita gente reclama da própria linguagem
      Exemplos de DSLs populares que podem ser consideradas ruins ou próximas de fracassos incluem HCL, E4X, XUL e a linguagem de formatação de strings do Common Lisp
      HCL é a linguagem de configuração do Terraform, e era óbvio desde o início que ela não tratava de um problema muito comum: provisionar equipamentos semelhantes em quantidade definida por uma variável
      As tentativas posteriores de adicionar esse recurso também foram desajeitadas e não resolveram o problema completamente
      E4X era uma DSL de JavaScript para trabalhar com XML; em casos simples, permitia expressar operações com XML de forma mais concisa, mas logo podia virar uma parede de pontuação difícil de ler
      Assim como o LINQ da Microsoft, ela não dava ao autor nenhuma indicação da complexidade computacional do código interno
      No fim, códigos que usavam essa DSL frequentemente eram reescritos de uma forma menos concisa, porém mais fácil de analisar
      XUL era uma linguagem de UI para extensões do chrome do navegador Firefox, e era aceitável para o objetivo de criar extensões do Firefox
      Mas a Firefox também queria vendê-la como tecnologia-base para aplicações internas de empresas, e nessa área ela deixava muito a desejar
      Para fazer coisas simples, eram necessários muitos macetes e contornos
      A linguagem de formatação de strings do Common Lisp é parecida: funciona para problemas pequenos, mas não escala
      Alguns problemas de formatação exigem soluções muito estranhas ou simplesmente não têm resposta, e eu realmente detesto ver código que chama format recursivamente
      No geral, o problema mais comum desse tipo de abordagem é ser improvisada e não escalar bem
      Logo você esbarra em problemas que não consegue resolver direito, e programas grandes escritos em uma DSL muitas vezes são um pesadelo de manter
    • Sempre fico intrigado ao ver aversão a DSLs, até perceber que o que as pessoas criticam não são DSLs em geral, mas DSLs que precisam ser escritas do zero
      Se você coloca uma DSL sobre Lisp, só precisa escrever a lógica de domínio, não a linguagem de base
      A maior parte do trabalho já está feita, e a linguagem é útil desde o primeiro dia
      Quando se faz uma DSL hospedada sobre Lisp, ela pode de fato ser usada; não entendo por que alguém criaria uma nova linguagem do zero só para vê-la murchar e morrer
    • DSLs funcionam bem quando há uma IDE com autocompletar e um loop de feedback rápido ou imediato
  • Todos esses itens têm muitos casos de sucesso
    É difícil usar a palavra “quase” como rota de fuga
    Isso parece apenas pessimismo e cinismo cansado
    Entendo esse sentimento e também já o senti, e às vezes é difícil fazer um engenheiro entusiasmado desistir de uma má ideia
    Mas esse clima me parece tóxico

    • Acho que é só uma forma mais envolvente, digamos, meio caça-cliques, de dizer: “essas coisas são mais complicadas do que parecem de construir direito ou distribuir de forma eficaz”
    • Por trás de muitos desses casos de “sucesso”, há uma equipe de engenheiros curtida em batalha lidando com todos os fracassos daquela ideia
      Loops de controle que disparam para infinito ou para limites máximos/mínimos, caches que não conseguem se recuperar de falhas distribuídas, estado corrompido durante migrações ao vivo, rajadas que causam sobrecarga em momentos inconvenientes, alertas falsos de detecção de anomalias avisando sobre feriados no mundo inteiro, coisas assim
      Sob todas essas ideias há um emaranhado de complexidade que quase todo mundo subestima
    • Concordo em grande parte
      Esta é uma lista de ideias de sistemas que são mais difíceis do que parecem à primeira vista, e que devem ser tratadas com seriedade, não de forma leviana
      Soa vagamente parecido com “parece bom, mas quase nunca funciona”, mas nos detalhes é completamente diferente
      Se você tratar como um problema difícil e investir de acordo, funcionar bem de verdade é um resultado normalmente alcançável
      Quando é uma funcionalidade acrescentada depois, ou quando se presume ingenuamente que é fácil, muitas vezes dá errado
    • Não leio isso como “pessimismo e cinismo cansado”
      Leio como uma discussão sobre engenheiros se dedicando à otimização prematura mesmo sem benefício de negócio
      Isso é realmente muito disseminado no setor: algo que poderia custar menos de um décimo se você tivesse um backup implantável em poucas horas e provisionasse servidores com 200% de sobra acaba virando o projeto e a construção de uma nave espacial redundante de autoescalonamento, porque isso é divertido
      Às vezes essas ideias fazem sentido, mas só depois que passam a ser necessárias
      Não é algo para projetar logo na fase inicial do produto
      São raríssimos os produtos que realmente precisam da escala, disponibilidade e complexidade que essas implementações tentam resolver
    • Acho que Steven não está dizendo que essas coisas são impossíveis, mas que são difíceis e dão errado com frequência incomum
  • Parece que muita gente aqui está tentando encontrar uma função de julgamento sutil para separar as exceções, mas na verdade é simples
    Essas ideias são ótimas quando eu faço, e nunca funcionam como pretendido quando são feitas por algum idiota que veio antes de mim

    • Parece exatamente isso
      E, às vezes, esse idiota que veio antes sou eu mesmo alguns meses atrás
  • Eu também acrescentaria design orientado a domínio a esta lista
    Tentar alinhar a aplicação à estrutura do negócio e, com isso, congelar o desenho do negócio é uma receita para o desastre
    Se o negócio for pequeno ou estiver estagnado, talvez você nem perceba o problema
    Mas, se o negócio tiver sucesso ou crescer, você logo vai se arrepender de ter tentado criar domínios com nomes terrivelmente descritivos, presos a práticas operacionais já ultrapassadas
    Em vez disso, é muito mais flexível projetar em torno de camadas funcionais, do jeito comprovado há décadas, e manter a lógica de negócio, tanto quanto possível, em configurações, linhas de banco de dados e fluxos de trabalho do usuário

    • Você vai se arrepender das duas escolhas
      Você citou como armadilhas do design orientado a domínio a linguagem obsoleta e a baixa reutilização de código e sistemas para novas iniciativas; por outro lado, um design altamente abstrato que coloca a lógica de negócio em configurações, workflows etc. só é flexível quando a organização inteira entende muito bem essa abstração, a configuração e as inúmeras combinações
      Essas combinações rapidamente explodem como um labirinto e criam comportamentos desconhecidos e inesperados dos quais as pessoas passam a depender
      O custo de integração de novos desenvolvedores e de troca da equipe de desenvolvimento também fica difícil de sustentar
      A organização passa a falar duas línguas diferentes
      A maioria das solicitações de funcionalidade que parecem simples por fora vira uma enorme reformulação do sistema se quebrar a abstração, ou então vira “vamos só hackear essa abstração para que isso pareça uma mudança menor e mais segura por enquanto”
      O primeiro caso é sempre muito difícil, mesmo com engenheiros excelentes que entendem completamente o comportamento de todo o sistema e a base de código, além de ótimas práticas e processos de engenharia, e pode levar meses ou anos
      O segundo acontece com mais frequência, e é por isso que projetos “altamente abstratos, em camadas funcionais, baseados em configuração e com lógica de negócio emergente” parecem perfeitos e flexíveis no início, mas acabam virando um “que diabos é isso?”
      Depois que o sistema é implementado, essa lógica de negócio emergente passa a ser a linguagem que todo mundo fala
      Quando a organização fala duas ou três línguas completamente irreconciliáveis entre si, isso é muito doloroso; e, se não houver várias pessoas capazes de traduzir fluentemente entre elas para cima, para baixo e para os lados, você acaba sentindo que deveria ter representado o domínio de forma mais próxima
    • “Torne estados impossíveis impossíveis de representar” também entra aqui
      Se você projeta um sistema de modo que certo estado não possa ser representado pelo tipo, precisa ter certeza de que, durante a vida útil desse design, esse estado será realmente um estado impossível
  • Não entendo bem o item sobre loops de controle que reagem à carga
    Eles são componentes básicos e fundamentais de inúmeros sistemas
    O governador centrífugo de uma máquina a vapor dos anos 1800 ou de um toca-discos Victrola dos anos 1900 também é um loop de controle que reage à carga
    Toda a eletrônica é uma rede de loops de controle que reagem à carga, e o mesmo vale para transmissões automáticas de carros

    • O problema comum é adicionar um loop de controle sem entender bem o sinal, ou adicioná-lo sem considerar outros loops de controle
      Uso de CPU é um exemplo interessante
      Por exemplo, você pode ver um balanceador de carga entre regiões brigando com um mecanismo de rejeição de carga dentro do processo
      Isso acontece porque o sinal do balanceador de carga não reflete a rejeição de carga, ou a reflete de maneira incorreta
      Outro problema é quando um loop de controle que tenta otimizar o resultado local de um serviço prejudica o resultado global
      De modo geral, acho melhor ter poucos loops de controle em posições de grande impacto
    • Não está totalmente claro, mas pode estar se referindo especificamente à carga de CPU
      A carga de CPU tem alguns problemas, como explicado em https://arxiv.org/abs/2312.10172
  • Há um padrão comum nesses problemas
    Todos são preocupações ortogonais que adicionam restrições ao modelo de programação de processamento sequencial de dados com o qual programadores estão acostumados
    A cada restrição adicionada, aumenta aquilo em que todos os desenvolvedores terão de continuar pensando ao desenvolver nesse sistema dali em diante
    É fácil o sistema ficar excessivamente restrito e cair numa situação em que não é possível avançar sem afrouxar algumas restrições
    Mesmo quando não é impossível, fica mais lento
    Porque, a cada vez, o desenvolvedor precisa considerar como um novo recurso interage com APIs que já se prometeu suportar, segurança, sincronização, latência, outras plataformas e código nativo
    Por isso também é possível oferecer suporte a todas essas propriedades
    Por exemplo, se a sincronização transparente de dados for colocada como a proposta de valor central da plataforma, todo desenvolvimento posterior passa a priorizar isso e a evoluir o conjunto de recursos possível dentro dessas restrições
    Esse conjunto de recursos pode não ser exatamente o que o usuário quer, mas é o escopo que ele suporta
    O produto parece atraente para clientes que colocam essa propriedade como o principal critério de compra

  • Já trabalhei em projetos que usavam vários DSLs, cache P2P e paralelismo misto, e todos funcionaram
    Também foram muito divertidos de construir
    Com uma exceção, foram bons investimentos
    O cache P2P não era necessário, então no fim não trouxe muito retorno
    Portanto, dizer que essas coisas quase nunca funcionam é claramente errado
    São complexas, mas essa complexidade traz recursos difíceis de obter de outras formas
    A lição do exemplo do cache P2P é garantir primeiro se o recurso é realmente necessário

  • Fica um pouco estranho de ler, porque já executei com sucesso várias dessas ideias

    • Ou você realmente sabe muito bem o que está fazendo, ou realmente não sabe absolutamente nada
  • “Vamos só sincronizar os dados” é, para mim, a razão de existirem dias difíceis
    Já vi sistemas demais que adicionaram filas, processamento de eventos etc. pensando em algo como “escala de internet”, quando o escopo natural real fica muito abaixo desse limiar
    Essas equipes ou são ingênuas ou, no pior caso, se aproveitam de executivos que não entendem de engenharia para conseguir dinheiro e brincar com esses problemas por diversão

    • Eu li “vamos só sincronizar os dados” como desejar ingenuamente que duas fontes da verdade não se separem enquanto se lê de um lado e se escreve do outro
      Para fazer direito, filas e processamento de eventos são indispensáveis