Exemplo de otimização de armazenamento de dados

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (0)  (1)

Caio Azevedo (e-mail) é arquiteto de softwares, especialista em soluções corporativas nos ambientes intranet/internet. Graduado em Ciência da Computação, Mestrando da Escola Politécnica da USP. Certificações Microsoft [MCP, MCAD e MCSD .NET]. Gestor da célula Microsoft da Magna Sistemas Consultoria (www.magnasistemas.com.br).

Olá Pessoal! Esse artigo tem como objetivo propor a solução de um problema no qual deparamos com razoável freqüência, e se você ainda não o teve pela frente, provavelmente ainda o terá especialmente se você desenvolve aplicações comerciais.

Meu grande objetivo com esse artigo, bem mais que propor uma solução, é despertar nos leitores o prazer obtido durante o processo a racionalização e solução otimizada de mais um, dos vários problemas que deparamos em nosso dia a dia.

O Problema

Imaginemos o cenário onde precisamos gerenciar eventos, por exemplo, no desenvolvimento de uma agenda. Uma das características de um evento é sua periodicidade, que pode 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 que o evento ocorrerá, por exemplo:

. As aulas do curso de C# ocorrerão a partir do dia 30/10/2006, nas próximas 4 semanas às segundas, quartas e sextas-feiras.
. As reuniões de acompanhamento do projeto, ocorrerão a partir do dia 01/11/2006, pelos próximos 4 meses.
. A apresentação do projeto será realizada dia 20/12/2007.

Proposta de modelo de dados

Uma modelagem de dados muito utilizada seria algo semelhante ao apresentado abaixo, ou algo muito próximo disso, com uma tabela somente com os dias da semana relacionada à tabela de eventos.

                    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_QUAINTA           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_FREQUENCIA é 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 para cada tipo da freqüência.

E finalmente os atributos DIA_XXX, especificam os dias da semana de ocorrência do evento.

Deficiências

O processo de manutenção dessas informações será deveras penoso sob os seguintes aspectos:

. Temos uma quantidade razoável de atributos, onde sempre haverá desperdício de espaço em nosso repositório de dados.
. A codificação terá que contemplar todos esses 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 tercas, quintas e sábados ao ser modificado para mensal, 2 vezes, serão necessários instruções adiocionais para atualizar todos os atributos.

Sugestão

Nossa solução propõe uma redução drástica na quantidade de atributos na tabela de eventos.

                    EVENTO_TIPO_FREQUENCIA           Char
                    EVENTO_QUANTIDADE_FREQUENCIA           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 QUANTIDADE_FREQUENCIA armazena o total de ocorrência do evento, seu sentido será dado em função do TIPO_FREQUENCIA.

E, finalmente, a grande otimizaçã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, claro, tenhamos uma freqüência do tipo semanal. Obviamente ainda poderemos ter “desperdício” de um atributo, mas somente para o tipo da freqüência diferente de semanal.

Mas como armazenar tantas informações em um único atributo, e do tipo byte?

Recordar é viver – os tipos de dados fundamentais são formados por conjuntos de bits – assim, um inteiro possui 4 bytes x 8 bits = 32 bits, um double possui 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           01
                    0000 0010           02
                    0000 0100           04
                    0000 1000           08
                    0001 0000           16
                    0010 0000           32
                    0100 0000           64

Tabela 3- um byte em bit

Atribuindo um dia da semana para cada valor:

                    0000 0001 01           domingo
                    0000 0010 02           segunda-feira
                    0000 0100 04           terça-feira
                    0000 1000 08           quarta-feira
                    0001 0000 16           quinta-feira
                    0010 0000 32           sexta-feira
                    0100 0000 64           sábado
Tabela 4 - dias e valores correspondentes

Matematizando 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

Tabela 5 - dias e valores correspondentes

Ora, concluímos que o valor associado à um dia da semana corresponde ao número 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 à 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 == 22 + 24 + 26 == 04 + 16 + 64 == 84.

Logo, ao invés 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, onde uma das formas de análise dessas funções é o processo conhecido como fatoração, lembram?        

          64           2
          32           2
          16           2
          08           2
          04           2
          02           2
          01          
Tabela 6 - fatoração de 64 na base 2, 64 = 26

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 resto das divisões sucessivas teremos exatamente as informações 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 = 05)
       O resto da divisão 05 / 2 = 1    (fatorando = 02)
       O resto da divisão 02 / 2 = 0    (fatorando = 01)
       O resto da divisão 01 1             (fim)
Tabela 7 - Combinando, fatoração e resto das divisões

Esses “zeros” e “uns” gerados, tomados de baixo para cima , corresponde 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].

Codificação: Para melhor compreensão de nossa proposta, codificaremos tudo que foi dito até agora.

interface.gif
Interface Sugerida

codigo_1.gif
Valor correspondente aos dias da semana

codigo_2.gif
Array de booleanos correspondente ao valor armazenado

codigo_3.gif
F
inalmente atribuimos ao checkBoxList o resultado do seu array de booleanos

Conclusão

É isso ai pessoal, espero ter atingido meu objetivo, despertando nos caros colegas a sensação de que nosso trabalho deve ir muito além de pesquisar no google códigos para resolução de problemas.

Precisamos sim, analisar as situações, racionalizar os problemas (sem esquecer a intuição) e propor soluções da melhor forma possível. Como vimos, especialmente depois de pronto, a codificação utilizada foi mínima, e é ai que está o grande mérito da proposta, conseguimos muito com bem pouco, em mais uma demonstração da lei natural do mínimo esforço (não à toa, a matemática foi nossa principal ferramenta).

Se vocês concluíram que pequenas idéias (geralmente fruto da imaginação) podem fazer grande diferença em nossas carreiras, já estarei satisfeito, afinal como dizia o grande Albert Einstein, “A imaginação é mais importante que o conhecimento”.

E, finalmente, segue um pequeno projeto utilizado em nosso artigo. Sintam-se à vontade para qualquer esclarecimento/crítica/sugestão.

Download: daysofWeek.zip

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?