CUPID — para codificação alegre - parte 2
Continuação do primeiro texto sobre CUPID
https://www.tabnews.com.br/uriel/os-principios-anti-solid-cupid-primeira-parte-como-tudo-comecou
O que começou como um iconoclasmo alegre, cutucando o urso do SOLID, se transformou em algo mais concreto e tangível. Se eu não acho que os princípios SOLID são úteis hoje em dia, então com o que eu os substituiria? Qualquer conjunto de princípios pode valer para todos os softwares? O que queremos dizer com princípios?
Acredito que existem propriedades ou características do software que o tornam prazeroso de se trabalhar. Quanto mais seu código tiver essas qualidades, mais prazeroso será trabalhar com ele; mas tudo é uma troca, então você deve sempre considerar seu contexto.
Provavelmente há muitas dessas propriedades, sobrepostas e inter-relacionadas, e há muitas maneiras de descrevê-las. Escolhi cinco que sustentam muito do que me interessa no código. Há um retorno decrescente; cinco são suficientes para fazer um acrônimo útil e o suficiente para lembrar.
Vou expandir cada propriedade em artigos futuros para que este não fique mais longo, então, por favor, perdoe-me por não ser mais abrangente.
As cinco propriedades CUPID são:
- Componível: joga bem com os outros
- Filosofia Unix: faz uma coisa bem
- Previsível: faz o que você espera
- Idiomático: parece natural
- Baseado em domínio: o domínio da solução modela o domínio do problema em linguagem e estrutura.
Original
- Composable: plays well with others
- Unix philosophy: does one thing well
- Predictable: does what you expect
- Idiomatic: feels natural
- Domain-based: the solution domain models the problem domain in language and structure
Preâmbulo: há muito tempo… ¶
Você já abriu uma base de código desconhecida e apenas soube como se locomover? A estrutura, a nomeação, o fluxo são óbvios, familiares de alguma forma. Um sorriso aparece em seu rosto. "Eu sei isso!" você pensa.
Tive a sorte de experimentar isso um punhado de vezes ao longo de uma carreira de trinta anos, e cada vez isso me encheu de alegria. A primeira vez foi no início dos anos 1990 – lembro-me nitidamente – quando abri uma enorme base de código C que fazia manipulação complexa de imagens para impressão digital. Havia um bug no Someone Else's Code™, eu deveria rastreá-lo e corrigi-lo. Lembro-me da sensação, como programador novato: uma mistura de pavor e medo de me trair como amador que eu sabia que era.
Meu editor - vi com ctags - me permitiu navegar para as definições de função de sites de chamadas e, em poucos minutos, eu estava mergulhado em um ninho de chamadas, em uma base de código de muitas centenas de arquivos de origem e de cabeçalho, sentindo-me confiante de que sabia o que eu estava olhando. Rapidamente encontrei o culpado, que era um simples erro de lógica, fiz uma alteração, compilei o código e testei-o. Isso tudo sem testes automatizados, apenas usando Makefiles. TDD estava quase uma década no meu futuro e C não tinha esse tipo de ferramenta em nenhum caso.
Eu executei a transformação em várias imagens de amostra e elas saíram parecendo ok. Eu estava o mais confiante possível de que tinha a) encontrado e corrigido o bug, e
b) não introduzido nenhuma surpresa desagradável ao mesmo tempo.
Software alegre ¶
Alguns códigos são uma delícia de se trabalhar. Você sabe como encontrar o que precisa para trabalhar. Você sabe como fazer a mudança que precisa. O código é fácil de navegar, fácil de entender, fácil de raciocinar. Você se sente confiante de que sua mudança terá o efeito desejado, sem efeitos colaterais indevidos. O código te guia , te convida a olhar ao redor. Os programadores que vieram antes de você se preocuparam com a pessoa que viria mais tarde, talvez porque eles perceberam que o programador que veio depois pode ser eles!
Em seu livro “Refactoring”, Martin Fowler diz:
“Qualquer tolo pode escrever um código que um computador possa entender. Bons programadores escrevem código que os humanos podem entender.”
— Refatoração , Martin Fowler com Kent Beck, 1996
Eu li isso no início nos anos 2000 e suas palavras viraram meu mundo de programação de cabeça para baixo. E se uma boa programação for tornar o código compreensível para outros humanos? E se um desses humanos for o eu do futuro? Isso soou como algo para pensar.
Mas enquanto “compreensível” pode ser uma aspiração nobre, não é um nível tão alto! Na mesma época em que Martin estava escrevendo sobre refatoração, o pioneiro da computação
Richard P. Gabriel descreveu a
ideia de código ser habitável:
“Habitabilidade é a característica do código-fonte que permite que [as pessoas] compreendam sua construção e intenções e alterem-no com conforto e confiança.
“A habitabilidade torna um lugar habitável, como o lar.”
— Habitabilidade e Crescimento Parcial 1, adrões de Software P pp. 7-16, Richard P. Gabriel
Isso parece mais algo pelo qual lutar. Quão bom seria se sentir confortável e confiante mudando o código de outras pessoas? E se pudermos tornar o código habitável, que tal alegre? É possível que uma base de código o encha de alegria?
Se você passa seus dias de trabalho programando, navegar e manipular uma base de código define sua experiência de usuário. Você pode experimentar surpresa, frustração, pavor, antecipação, impotência, esperança, alegria, tudo por causa das escolhas que os programadores anteriores fizeram na base de código.
Se assumirmos que é possível que uma base de código seja alegre, cada base de código é seu próprio floco de neve especial, cujo impacto em sua psique é único? Ou podemos articular o que o torna alegre e oferecer um caminho para aumentar a alegria no código que tocamos?
Propriedades sobre princípios ¶
Quando comecei a formular uma resposta aos cinco princípios do SOLID, imaginei substituir cada um deles por algo que achasse mais útil ou relevante. Logo percebi que a própria ideia de princípios era problemática. Princípios são como regras: ou você está em conformidade ou não. Isso dá origem a “conjuntos limitados” de seguidores e aplicadores de regras, em vez de “conjuntos centrados” de pessoas com valores compartilhados.
Em vez disso, comecei a pensar em propriedades: qualidades ou características do código em vez de regras a serem seguidas. As propriedades definem um objetivo ou centro para o qual se mover. Seu código está apenas mais próximo ou mais distante do centro, e sempre há uma direção clara de deslocamento. Você pode usar propriedades como uma lente ou filtro para avaliar seu código e decidir quais abordar em seguida. Como as propriedades do CUPID estão todas inter-relacionadas, é provável que qualquer alteração feita para melhorar uma propriedade tenha um efeito positivo em algumas das outras.
Propriedades das propriedades ¶
Então, como escolhemos propriedades? O que torna uma propriedade mais ou menos útil? Eu decidi três “propriedades de propriedades” que eu quero que as propriedades CUPID tenham. Elas devem ser práticas , humanas e em camadas.
Para ser prático , as propriedades precisam ser:
- fácil de articular: assim você pode descrever cada uma delas em poucas frases e oferecer exemplos concretos e contra-exemplos.
- fácil de avaliar: para que você possa usá-las como uma lente para revisar e discutir o código e decidir facilmente o quanto o código exibe cada propriedade.
- fácil de adotar: para que você possa iniciar um código pequeno e evoluir incrementalmente em qualquer uma das dimensões do CUPID. Não há “all-in” e não há “fracasso”, assim como nunca há um “feito”. O código sempre pode melhorar.
Para o ser humano, as propriedades precisam ser lidas da perspectiva das pessoas, não do código. CUPID é sobre como é trabalhar com código, não uma descrição abstrata do código em si.
Por exemplo, enquanto a filosofia Unix de “faça uma coisa bem” pode soar como o Princípio da Responsabilidade Única, o primeiro é sobre como você usa o código, e o último é sobre as partes internas do próprio código.
Para serem em camadas, as propriedades devem oferecer orientação para iniciantes – o que é consequência de serem fáceis de articular – e nuances para pessoas mais experientes que desejam explorar a natureza do software mais profundamente. Cada uma das propriedades do CUPID é “óbvia” apenas o nome e uma breve descrição, mas cada uma incorpora muitas camadas, dimensões, abordagens. Podemos descrever o “centro” de cada propriedade, mas há muitos caminhos para chegar lá!
Combinável ¶
O software que é fácil de usar é usado, usado e usado novamente. Existem características que tornam o código mais ou menos componível, mas elas não são necessárias nem suficientes para dar garantias. Em cada caso, podemos encontrar contra-exemplos em ambos os lados, então você deve pensar nisso como heurísticas úteis. Mais não é necessariamente melhor; é tudo trocas.
Pequena área de superfície ¶
O código com uma API estreita e opinativa tem menos para você aprender, menos para dar errado e menos chance de conflito ou inconsistência com outro código que você está usando. Isso tem um retorno decrescente; se suas APIs forem muito restritas, você se verá usando grupos delas juntas e saber “a combinação certa” para casos de uso comuns se torna um conhecimento tácito que pode ser uma barreira à entrada. Acertar a granularidade de uma API é mais difícil do que parece. Há um ponto ideal de coesão “na medida certa” entre fragmentado e inchado.
Revelação de intenção ¶
Código revelador de intenção é fácil de descobrir e fácil de avaliar. Posso encontrar facilmente seu componente e decidir rapidamente se é o que preciso ou não. Um modelo que eu gosto - de projetos de código aberto como o venerável XStream - é ter um tutorial de 2 minutos, um tutorial de 10 minutos e um mergulho profundo. Isso me permite investir de forma incremental e mudar assim que descobrir que isso não é para mim.
Mais de uma vez comecei a escrever uma classe dando a ela um nome que revelasse a intenção, apenas para o IDE exibir uma importação sugerida com o mesmo nome. Geralmente acontecia que outra pessoa tinha a mesma ideia, e por acaso encontrei o código deles porque escolhemos nomes semelhantes. Isso não foi apenas coincidência; éramos fluentes no mesmo domínio, o que tornava mais provável que escolhêssemos nomes semelhantes. Isso é mais provável quando você tem código baseado em domínio.
Dependências mínimas ¶
O código com dependências mínimas oferece menos preocupações e reduz a probabilidade de incompatibilidades de versão ou biblioteca. Escrevi meu primeiro projeto de código aberto, XJB, em Java e usei log4j como estrutura de log, log4j quase onipresente. Um colega apontou que isso criava uma dependência, não apenas de log4j como biblioteca, mas em uma versão específica. Nem me ocorreu; por que alguém deveria se preocupar com algo tão inócuo quanto uma biblioteca de log? Então, removemos as dependências e até extraímos um outro projeto que fazia coisas divertidas com proxies dinâmicos Java, que por si só tinham dependências mínimas.
Filosofia Unix ¶
Unix e eu temos aproximadamente a mesma idade; nós dois começamos em 1969, e o Unix se tornou o sistema operacional mais prevalente no planeta. Durante a década de 1990, todo fabricante sério de hardware de computador tinha seu próprio Unix, até que as principais variantes de código aberto, Linux e FreeBSD, se tornaram onipresentes. Atualmente, ele executa quase todos os servidores de negócios, tanto na nuvem quanto em local, na forma de Linux; é executado em sistemas embarcados e dispositivos de rede; ele sustenta os sistemas operacionais macOS(hoje baseado em BSD) e Android; ele ainda vem como um subsistema opcional com o Microsoft Windows!
Um modelo simples e consistente ¶
Então, como um sistema operacional de nicho, que começou em um laboratório de pesquisa de telecomunicações, é copiado como um projeto de hobby por um estudante universitário e termina como o maior sistema operacional do mundo? Há, sem dúvida, razões comerciais e legais para seu sucesso em uma época em que os fornecedores de sistemas operacionais eram tão famosos por suas ações judiciais uns contra os outros quanto por sua tecnologia, mas seu apelo técnico duradouro está em sua filosofia de design simples e consistente .
A filosofia Unix diz para escrever [componentes] que funcionem bem juntos, descritos na propriedade Composability acima, e que façam uma coisa e façam bem. Por exemplo, o comando ls lista detalhes sobre arquivos e diretórios, mas não sabe nada sobre arquivos ou diretórios! Existe um comando de sistema chamado stat que fornece as informações; ls é apenas uma ferramenta para apresentar essas informações como texto.
Da mesma forma, comando cat imprime (concatena) o conteúdo de um ou mais arquivos, grep seleciona o texto que corresponde a um determinado padrão, sed substitui os padrões de texto e assim por diante. A linha de comando do Unix tem o poderoso conceito de “pipes” que anexam a saída de um comando como entrada para o próximo, criando um pipeline de seleção, transformação, filtragem, classificação e assim por diante. Você pode escrever programas sofisticados de processamento de texto e dados com base na composição de um punhado de comandos bem projetados, cada um fazendo uma coisa e bem.
Propósito único vs. responsabilidade única ¶
À primeira vista, isso parece o Princípio da Responsabilidade Única (SRP), e para certas interpretações do SRP há alguma sobreposição. Mas “fazer uma coisa bem” é uma perspectiva de fora para dentro; é a propriedade de ter um propósito específico, bem definido e abrangente. O SRP é uma perspectiva de dentro para fora: trata-se da organização do código.
O SRP, nas palavras de Robert C. Martin, que cunhou o termo, é que [o código]“ deve ter um, e apenas um, motivo para mudar”. O exemplo no artigo da Wikipedia é um módulo que produz um relatório, no qual você deve considerar o conteúdo e o formato do relatório como preocupações separadas que devem viver em classes separadas, ou mesmo módulos separados. Como eu disse em outro lugar, na minha experiência, isso cria costuras artificiais, e o caso mais comum é quando o conteúdo e o formato dos dados mudam juntos; um novo campo, por exemplo, ou uma alteração na origem de alguns dados que afete tanto seu conteúdo quanto a maneira como você deseja exibi-lo.
Origianl > https://dannorth.net/2022/02/10/cupid-for-joyful-coding/
Minha traduão no Dev.to https://dev.to/urielsouza29/cupid-para-codificacao-alegre-parte-2-31mk
Continua - devido a limitação de 2000 caracteres do tabnews continua no proximo post
https://www.tabnews.com.br/uriel/os-principios-anti-solid-cupid-primeira-parte-como-tudo-comecou
https://www.tabnews.com.br/uriel/cupid-para-codificacao-alegre-parte-3