sexta-feira, 6 de junho de 2008

"Não concatene Strings dentro de loops"

No post anterior(Reflectir sobre performance(2)), o exemplo utilizado viola esta Regra. Porque, concatenar Strings nesta condição (dentro de loops), faz com que novos Objectos String sejam criados, assim, precisam ser Garbage Collected. A Classe StringBuilder, ao contrário, evita o overhead provocado pela criação de Objectos e o Garbage Collection. Possui,
adicionalmente, a capacidade de desfazer-se do seu buffer original e criar um novo buffer, com o dobro do tamanho, para 'acomodar' a String.
Eu sempre que, ao revisar um código, encontar-me diante de algo que viole uma regra qualquer, aplico o 'fix' para tal violação. Mesmo em particulares situações, que poderia não aplicá-lo. Desta forma, mantenho a conformidade. Para mim, é uma questão de coerência de uma cultura que não a quero perder.

Está é a minha opinião.

Obrigado pelos comentários e,

Até ao próximo post!

Fernando Oliveira
Agap2 Developer
MCTS - .NET Framework 2.0
Web Applications

4 comentários:

Luís de Sousa disse...

Viva Fernando,

bom post :)

Contudo só uma achega, a classe StringBuilder, em minha opinião diminui o overhead, não o elimina.

Eu sei que é um preciosiosmo, só que as alocações de espaço existem sempre, são menos pois como dizes ele multiplica por 2.

Lembro-me dos tempos do C++, de nos aconselharem a alojar memória em multiplos de 2, pois o gestor de memória é mais eficiente nessas situações, aliás, para sermos mais preciosistas, devíamos de alocar memória em múltiplos da dimensão dos registos de uso geral do CPU.

Se tivéssemos registos de 32 bits, pediamos memória em multiplos de 32 bits.

Fiz umas brincadeiras com a classe StringBuilder, para tentar perceber como ela aloca espaço.

Verifiquei, que se pedir uma StringBuilder só com um caracter, que a capacidade da StringBuilder é de 16 caracteres. Se criar uma StringBuilder com 16 caracteres que a sua capacidade continua a ser de 16.
Se criar uma StringBuilder com 17 caracteres a capacidade é de 32 caracteres.

O comportamento é o descrito pelo Fernando, é para o dobro que ela cresce. Quanto à capacidade, ela pelo que vi é uma potência de 2. Pareceu-me também que é um multiplo da dimensão do registo do CPU. (Só que aqui atenção, só vi isto para 32 bits, para 64 bits gostava de ver :) )

Agora sempre que o StringBuilder cria o "novo" buffer, quando esgota o actual, será que o outro buffer não é garbage collected ?

Como prática, sem dúvida que concordo com a sua utilização. :)

Fernando Oliveira disse...

Parabéns Luís,

Pelo bom nível de discussão. continuemos assim e, para melhor!

Abraço.
Fernando Oliveira

Duarte Cunha Leão disse...

Caros colegas, queria deixar uma nota sobre o curso da discussão.

O post original apelava à "performance" do código e o meu comentário foi no sentido de realçar que existem outras variáveis a considerar que afectam a «qualidade» do código. É difícil haver regras absolutas: se uma regra satisfaz um determinado critério de avaliação da «qualidade», pode acontecer que não satisfaça tão bem outro critério que também contribui positivamente para a «qualidade».

Daí que tem que existir um compromisso entre as várias regras que contribuem para a «qualidade» do código, optando-se por satisfazer umas umas vezes e outras outras vezes.
É a vida que funciona assim, não há nada a fazer.

A coerência é muito importante na escrita de código. Mas cuidado. A coerência não é só por si garante de nada. Podemos ser coerentes na aplicação errada de uma regra, ou seja, na aplicação de uma regra que não é adequada para dada situação, não se aplica.

Podemos até ser coerentes no facto de não termos regra nenhuma, tal como fazem muitos programadores (não é algo que seja característico dos programadores, mas sim das pessoas medíocres, em geral).

Devemos ser coerentes, sim, no empenho na ponderação da aplicação das várias regras que conhecemos. Nesse desígnio é importante não nos esquecermos dos pressupostos dessas regras.

Acima de tudo há que não deixarmos de pensar por nós próprios. Sermos caazes de questionar as regras que nos ensinam, assim como, construirmos novas regras.

Fernando Oliveira disse...

Colega Duarte(nome do meu avô :-)),

Antes de mais, obrigado por participar com os seus comentários. São, também, de bom nível.
Quando me refiro a 'regras', são as associadas às best pratices. Portanto, são comprovadamente, funcionais. Agora, quanto as regras, filosoficamente falando, devemos sim, questionar. Porque, as verdades não são absolutas e, existe sempre espaço para melhorar. Por exemplo, com as nossas 'discussões temperadas' com ideias diferentes!

Abraço.
Fernando Oliveira