Anos atrás, ganhei da minha madrinha um livrinho, a princípio bobo pela simplicidade (acho que ela me presenteava com livros desde antes de antes de eu aprender a ler).
Trata-se do livro “Ideias Geniais”, de Surendra Verma. Ele aborda (pelo menos tenta) princípios, teorias, leis e princípios científicos – do Teorema de Pitágoras à Teoria de Tudo, mas de uma forma muito superficial – é uma blasfêmia falar do “Principia” em uma única página. Mas pela minha fixação no assunto e carinho pela minha adorável madrinha, li o livro inteiro. E eis que deparo com “A Navalha de Ocam”, um princípio que remonta do século 14 e resumidamente diz que “Entidades não devem ser multiplicadas desnecessariamente”, que serviu de inspiração para, entre outras aplicações, o princípio KISS.
![Isaac Newton - Principia](https://static.imasters.com.br/wp-content/uploads/2013/06/800px-NewtonsPrincipia.jpg)
O princípio KISS – de “Keep It Simple, Stupid” – postula que a simplicidade deve ser a palavra de ordem em projetos (de engenharia civil, elétrica, mecânica ou computacional) e que complexidades devem ser evitadas.
Em desenvolvimento de software, arquitetura de sistemas, modelagem de dados, design de websites, enfim, em qualquer segmento, esse princípio deve ser lembrado – aliás, é um mantra que repito para as equipes que lidero.
São inúmeros os exemplos que podemos apresentar para ilustrar os benefícios e aplicabilidades do principio KISS, a saber:
- No paradigma procedural, temos o uso de bibliotecas com funções e procedures pequenas e SIMPLES reutilizáveis
- O simples uso de CSS em um website
- Acredito que a própria orientação a objetos foi motivada pelo principio KISS
Caros colegas, simplicidade está longe de ser sinônimo de facilidade; alias é exatamente o oposto: soluções simples são EUREKAS de criatividade e genialidade.
Alguns anos atrás, num desses trabalhos como arquiteto deparei com um sistema com sérios problemas de performance e manutenção. Diversos eram os problemas, mas o que de fato me chamou atenção e, tive meu momento EUREKA, foi o seguinte: no gerenciamento de eventos em uma agenda. Uma das características é a periodicidade, podendo ser única, diária, semanal e mensal. Suponhamos que na periodicidade semanal, além de informar a quantidade de semanas de ocorrência do evento, seja necessário especificar os dias da semana de ocorrência do evento, por exemplo:
- As aulas do curso de c# ocorrerão a partir do dia 20/08/2013, pelas próximas 4 semanas às segundas, quartas e sextas-feiras.
- As reuniões de acompanhamento do projeto, ocorrerão a partir do dia 01/12/2014, pelos próximos 4 meses.
- A apresentação do projeto será realizada dia 20/12/2013.
Uma modelagem de dados muito utilizada nesse tipo de cenário, (verifique o que tem aí na sua empresa), seria algo semelhante ao apresentado abaixo, ou muito próximo a isso, com uma tabela somente com os dias da semana relacionada à tabela de eventos, e foi exatamente isso que encontrei.
EVENTO_TIPO_FREQUENCIA | Char |
EVENTO_TOTAL_DIAS | Int |
EVENTO_TOTAL_SEMANAS | Int |
EVENTO_TOTAL_MESES | Int |
EVENTO_DIA_SEGUNDA | Bit |
EVENTO_DIA_TERCA | Bit |
EVENTO_DIA_QUARTA | Bit |
EVENTO_DIA_QUINTA | Bit |
EVENTO_DIA_SEXTA | Bit |
EVENTO_DIA_SABADO | Bit |
EVENTO_DIA_DOMINGO | Bit |
Tabela 1 – modelo parcial da tabela de eventos.
Onde o atributo TIPO_FREQUANCIA é definido em um domínio pré-estabelecido, por exemplo [1-único, 2 – diário, 3 – semanal, 4 – mensal].
Os atributos TOTAL_DIAS, TOTAL_SEMANAS, TOTAL_MESES contabilizam o período de ocorrência do evento baseado no tipo da frequência.
E finalmente os atributos DIA_XXX, que especificam os dias da semana de ocorrência do evento.
Essa modelagem é fácil e até mesmo intuitiva, mas gera uma série de problemas, tais como:
- Temos uma quantidade razoável de atributos, em que sempre teremos desperdício de espaço em nosso repositório de dados.
- Toda codificação terá que contemplar todos esses conjuntos de atributos [procedures com muitos parâmetros, classes com todas essas propriedades, métodos de validação e operações de CRUD com vários parâmetros].
- Processo de alteração mais complexo – um evento inicialmente cadastrado como semanal, 4 vezes, às terças, quintas e sábados, ao ser modificado para mensal, 2 vezes, será necessário atualizar todos os atributos.
Momento EUREKA:
Redução drástica na quantidade de atributos na tabela de eventos.
EVENTO_TIPO_FREQUENCIA | Char |
EVENTO_PERIODO | Int |
EVENTO_DIAS_DA_SEMANA | Byte |
Tabela 2 – modelo parcial da tabela de eventos – solução proposta.
O atributo TIPO_FREQUENCIA mantém a mesma definição da solução anterior.
Aqui, o atributo PERIODO armazena o total de ocorrência do evento, seu sentido será dado em função do TIPO_FREQUENCIA.
E, finalmente, a grande simplificação do cenário, em um único atributo, DIAS_DA_SEMANA, do tipo byte, armazenaremos os dias da semana e todas as suas combinações, caso tenhamos uma frequência do tipo semanal. Obviamente ainda teremos “desperdício” de atributos, mas somente um, e ainda apenas para tipo da frequência diferente de semanal.
Como isso é possível??
Lembram do filme “Matrix”, quando o personagem Neo passou a ver o mundo decodificado? Eis o caminho para nossa solução: precisamos recorrer ao cerne do mundo digital – os bits.
Recordar é viver – “Os tipos de dados são formados por conjuntos de bits” – um inteiro tem 4 bytes x 8 bits = 32 bits, um double tem 8 bytes x 8 bits = 64 bits, etc. No nosso caso, onde temos que manipular 7 informações (os dias da semana), a melhor opção é um campo do tipo byte que tem 8 bits – tudo bem, ainda desperdiçamos 1, mas nem tudo é perfeito.
Decodificando um campo byte temos:
0000 0001 | 1 |
0000 0010 | 2 |
0000 0100 | 4 |
0000 1000 | 8 |
0001 0000 | 16 |
0010 0000 | 32 |
0100 0000 | 64 |
Atribuindo um dia da semana para cada valor:
0000 0001 | 1 | Domingo |
0000 0010 | 2 | Segunda-Feria |
0000 0100 | 4 | Terça-Feria |
0000 1000 | 8 | Quarta-Feria |
0001 0000 | 16 | Quinta-Feria |
0010 0000 | 32 | Sexta-Feria |
0100 0000 | 64 | Sábado |
Decodificando os dias da semana:
0000 0001 | 01 ↔ 2 0 | Domingo |
0000 0010 | 02 ↔ 2 1 | Segunda-feira |
0000 0100 | 04 ↔ 2 2 | Terça-feira |
0000 1000 | 08 ↔ 2 3 | Quarta-feira |
0001 0000 | 16 ↔ 2 4 | Quinta-feira |
0010 0000 | 32 ↔ 2 5 | Sexta-feira |
0100 0000 | 64 ↔ 2 6 | Sábado |
Ora, concluímos que o valor associado a um dia corresponde a 2 elevado ao seu “peso”, 2 (dia da semana)
E para combinação de vários dias, como nos exemplos acima?? Simples, é só “ligar” os bits correspondentes a cada dia, vejamos:
Segunda, Quarta e Sexta == 0010 1010 == 2 1 + 2 3 + 2 5 == 02 + 08 + 32 == 42
Terça, Quinta e Sábado == 0101 0100 == 2 2 + 2 4 + 2 6 == 04 + 16 + 64 == 84
Logo, em vez de manipular diversos atributos, propriedades e parâmetros na codificação, calculamos um único valor numérico que representa a combinação de todos os dias da semana e assim manipulamos somente um atributo, simplificando e otimizando nosso trabalho.
Finalmente a expressão para obtenção desse valor será : Valor += 2 (dia da semana) , onde o dia da semana será obtido de sua interface.
E o processo inverso: como recuperar o valor armazenado no repositório de dados e disponibilizá-lo ao usuário? Ora, precisamos desse valor representado em bits novamente, ou melhor, em um conjunto de bits (7), em seu devido estado fundamental – ligado x desligado, mais precisamente devido à interação com a interface, true x false.
Mais uma vez, recorremos à maravilhosa matemática. Nosso algoritmo foi baseado em funções exponenciais, nas quais uma das formas de análise dessas funções é o processo conhecido como fatoração, lembram?
64 | 2 |
32 | 2 |
16 | 2 |
8 | 2 |
4 | 2 |
2 | 2 |
1 |
64 = 2 6
Pois bem, precisamos de um conjunto ou array de bits ligados e desligados, correspondente ao valor armazenado; combinando as operações de fatoração e o resto das divisões sucessivas, teremos exatamente as informações de que precisamos:
42 = ?
O resto da divisão 42/2 = 0 (fatorando = 21)
O resto da divisão 21/2 = 1 (fatorando = 10)
O resto da divisão 10/2 = 0 (fatorando = 5)
O resto da divisão 05/2 = 1 (fatorando = 2)
O resto da divisão 02/2 = 0 (fatorando = 1)
O resto da divisão 01 1 (fim)
E esses “zeros” e “uns” gerados, tomados de baixo para cima, correspondem exatamente ao nosso conjunto inicial de bits (10 1010), complementando-os com zeros à esquerda, bingo: 0010 1010, ou melhor, um array do tipo [false – false – true – false true – false – true –false].
É isso aí, pessoal, o principio KISS é de uma utilidade tremenda em nosso dia a dia, seja implementando, coordenado ou gerindo atividades relacionadas ao mundo de tecnologia. Espero com este artigo ter lhes despertado a pensar de maneira KISS.
Nosso trabalho deve ir muito além de pesquisar códigos ou fórmulas no Google para resolução de problemas. Precisamos, sim, analisar, pensar um pouco e propor soluções da melhor forma possível. Como vimos no exemplo apresentado, a codificação utilizada foi mínima, e aí está o grande mérito da proposta – conseguimos muito com bem pouco, uma amostra das leis natural do mínimo esforço (não em vão, fizemos uso da matemática).
É claro que pensar de maneira a simplificar é ótimo, mas também devemos prestar atenção a Einstein que disse “Tudo deve ser tornado o mais simples possível, porém não mais simples que isso”.
Finalmente, meu muito obrigado à minha madrinha (in memoriam), que desde sempre me estimulou o hábito da leitura e fica a lição: não existe livro “bobo”, sempre tem algo interessante a ser aproveitado.