“Certas coisas são impossíveis… Até aparecer um ignorante que não está ciente disso”.
Séries temporais – uma sequência de pontos de dados, tipicamente
medidos em instantes de tempo sucessivos espaçados em intervalos de
tempo uniformes.
Existem várias coisas que podem se enquadrar nessa definição. Por
exemplo, as mudanças de temperatura ao longo do dia (digamos, medidas de
hora em hora), a distância da Terra até a Lua (que muda um pouco ao
longo do mês lunar). Até mesmo que partido político detém a cadeira
presidencial após as eleições (que depende da “história” do presidente
anterior etc.). Podemos continuar com a lista de exemplos, até que o
armazenamento do servidor fique cheio. Como você pode ver, os exemplos
acima têm natureza cíclica, mas tudo também é (ou pelo menos tudo) em
séries temporais (claro, dentro de certos divergências).
É da natureza humana querer prever o futuro (embora, às vezes, é
melhor não saber). Estão sendo feitas tentativas de prever, ou vamos
usar um termo mais politicamente correto – previsão, onde determinadas
séries continuarão no futuro. O melhor exemplo podem ser xamãs prevendo a
chuva ou a seca. Atualmente, existem algoritmos complexos (e não tão
complexos) para prever séries temporais (por exemplo, redução de ruído
em processamento de sinal digital). Mas o argumento mais escandaloso e
barulhento está rolando sobre a análise do mercado de ações e previsões.
Muitos de vocês podem ter ouvido falar sobre William Gann – alguns
dizem que ele é um gênio, outros dizem que ele não passa de um
charlatão. Eu, pessoalmente, tendo a tomar o primeiro lado, embora podem
haver fatos dos quais eu não esteja ciente.
Mr. Gann morreu há quase 60 anos. Imagine agora quantas técnicas de
séries temporais de previsão (leia previsão do mercado de ações) já
surgiram e desapareceram. Desde a teoria do caos, mais e mais pessoas
tendem a dizer que “a previsão do mercado de ações é impossível devido à
sua natureza fractal”. Isso faz sentido se você olhar para o problema
pela perspectiva da teoria do caos. Entretanto, não se esqueça de que
essa teoria é aceita como aquela que melhor se encaixa à situação, não
como aquela que a explica completamente. Na minha percepção, essa
pequena diferença deixa um pequeno espaço para esperança.
Bem, já falei muito sobre ciência. Vamos à prática. Vou tentar
simplificar as coisas o máximo possível para demonstrar uma abordagem
mais simples, mas efetiva, do ponto de vista de um desenvolvedor.
Software
Da perspectiva do software, não há muita necessidade de previsões bem
sucedidas – um sistema expert. Pessoas inteligentes usam diferentes
pacotes de software e linguagem de programação voltadas para o
desenvolvimento de sistemas expert, mas sendo um ignorante (como eu
decidi ser neste artigo), decidi usar o que tenho e o que sei –
linguagem C, GCC e editor de texto Geany como uma IDE.
Dados
Existem várias maneiras (gráficas) de representar o mercado de ações/câmbio. O mais conhecido é o candlesticks.
Uma sequência de dados gráficos simples, dos quais cada um deles
representa a variação do preço para um determinado período de tempo
(aberto, alto, baixo e valores próximos). Nós, no entanto, não vamos
levar nenhum deles em consideração. Simplesmente porque não precisamos
deles. Em vez disso, vamos nos concentrar na linha crua de números por
um período determinado (digamos que um ano) medido de hora em hora, o
que nos dá uma sequência de mais de 8 mil itens (só estamos prestando
atenção a um valor – ou aberto, de alta, baixa ou perto).
Se você tentar traçar essa sequência (por exemplo, no Excell), você
vai obter uma linha curvilínea. Dê outra olhada e vai notar que existem
segmentos semelhantes (dentro de certos desvios, é claro). Apenas como
um conjunto de imagens semelhantes, o que criaria uma das melhores
abordagens para reconhecimento de imagem – Redes Neurais Artificiais
(especialmente perceptrons), embora não exista nada de novo no uso de
RNA para análise de mercado ações/câmbio. Existem
toneladas de produtos comerciais de software que proporcionam ao usuário
final diferentes indicadores dizendo a ele/ela se comprar, vender,
manter a posição atual, eu, pessoalmente, não tenho visto um monte de
tentativas para realmente fazer previsões em longo prazo (por exemplo,
24 horas para uma sequência medida de hora em hora). Há também uma
grande incerteza sobre quais dados devem ser usados como entrada de RNA e
quantos dados devem ser alimentados de cada vez. Infelizmente, ninguém
tem a resposta exata para esta pergunsa. É apenas a sua tentativa e
erro. O mesmo se aplica à quantidade de neurônios escondidos no RNA.
Outra grande pergunta é como os dados devem ser pré-processados –
preparados para a RNA. Alguns usam algoritmos complexos (baseados no
Fourier, por exemplo), outros tendem a usar os mais simplistas. A ideia é
que os dados devem estar no intervalo entre 0.0-1.0 e deveriam ser tão
variados quanto possível. Mas lembre-se – se você alimentar a RNA com
lixo, você terá lixo em resposta. O que significa que você tem de
escolher cuidadosamente o seu algoritmo de pré-processamento de dados
(normalização). Eu costumo usar um algoritmo de normalização
personalizado, que é bastante simples. Desculpe desapontá-lo, mas eu não
vou fornecê-lo aqui por enquanto, já que ele ainda não está
completamente definido (embora ele já dê bons resultados).
O ponto principal para este parágrafo é que pré-processamento de dados não é muito importante, é o MAIS importante.
Instrumentos
Minhas soluções de programação para esse problema são bem simples: um
programa de console que lê a entrada (toda a sequência de valores de
preços para o período especificado), treina uma rede neural artificial
(no meu caso, a topologia foi 8x24x1 – 8 entradas, 24 neurônios ocultos e
um neurônio de saída) e, em seguida, produz uma previsão de longo prazo
(pelo menos 7 entradas no futuro), enquanto cada passo da previsão é
feito usando os valores que foram gerados anteriormente.
A RNA é um perceptron simples multicamadas com 8 entradas, 24
neurônios ocultos e um neurônio de saída. Basicamente falando: não
realizamos muitos cálculos nós mesmos. A RNA é uma implementação
perfeita de um paradigma de aprendizagem, capaz de encontrar
dependências e regras escondidas. Portanto, se você me perguntar, não
existe solução melhor do que utilizar RNAs para a previsão de séries
temporais.
Teste
Então, eu implementei uma RNA (em C desta vez, não em Assembly) e
obtive o conjunto de dados (os valores EUR/USD de preço para cada hora
do ano passado). O próximo passo foi fazer uma tentativa e testar em
tempo de execução. Eu decidi fazer isso durante o fim de semana, já que
eu não tinha certeza de quanto tempo seria necessário para treinar a
rede. Surpreendentemente, tive um erro bom após apenas cerca de 30 mil
epochs (alguns minutos). A imagem a seguir mostra o que eu consegui:

previsão EUR / USD
Conjunto de teste – dados não incluídos no processo de treinamento da RNA. Utilizado como um padrão para o cálculo de erro.
Previsão de teste - previsão em dados do passado, que não foram incluídos no conjunto de treinamento.
Previsão real – previsão dos valores futuros. Isso foi feito no sábado pelo menos 24 horas antes da abertura do pregão seguinte.
Dados reais – valores reais obtidos na segunda-feira de manhã cedo após o novo pregão começar.
Como você pode notar, um sistema tão simples foi capaz de prever o espaço entre as duas sessões.
P.S. Embora, este artigo não contenha o código-fonte, nenhuma
descrição de qualquer técnica de programação interessante ou o que quer
que seja, ele mostra que cada problema tem uma solução (não
necessariamente complicada). Na maioria das vezes, a coisa mais
importante é dar uma olhada em um problema com outros olhos.
***
Texto original disponível em http://syprog.blogspot.com.br/2012/09/time-series-analysis-and-forecasting.html
|
jQuery é bacana! Escreva menos, faça mais.

Porém muitos dos desenvolvedores de hoje em dia não levaram a sério a parte do “escreva menos”,
e continuam escrevendo muito e de forma desordenada. Tudo bem, então
aqui vai algumas dicas para melhorar a qualidade dos códigos jQuery.
jsHint
jQuery é apenas uma lib javascript. Logo, todas as boas práticas que
existem para javascript, também existem para jQuery. Começe passando o
teu código pelo jsHint.
Dentre outras coisas, o jsHint vai verificar se você usou um switch na
hora errada, se declarou uma variável que não está sendo usada…
Outras coisas, que nem o jsHint conseguiria te dizer
Agora começa o meuartigo de verdade!
Prefira sempre usar jQuery no lugar de $
Eu, pessoalmente, considero mais legível. Mas além disso, também
estamos evitando de uma maneira muito simples aquele velho problema do
conflito com outras libs que usam o apelido $.
Seria:
jQuery(document).ready(function() {});
No lugar de:
$(document).ready(function() {});
Não procure um mesmo elemento várias vezes no DOM
Coisas como:
jQuery(this).parent('dl').find('dd').eq(0).addClass('active');
jQuery(this).parent('dl').find('dt').text('Ativo');
Poderiam ser simplificadas para:
var $this = jQuery(this),
$dl = $this.parent('dl');
$dl.find('dd').eq(0).addClass('active');
$dl.find('dt').text('Ativo');
Note que se formos usar o DD e esse DT outras vezes nesse escopo,
então vale apena guardar uma variável que aponte para eles também. Isso
também vai melhorar a performance do teu script.
Convencione os nomes das variáveis
É bacana olhar para uma variável e entender logo de cara de onde ela
veio e qual o valor dela. Eu estou adotando o $ antes de começar uma
variável que aponte para um objeto jQuery. Assim como o $this. E deixo
para as variáveis “normais” (arrays, inteiros e strings), uma notação
sem o símbolo $. Dessa forma, quando bato o olho no meu código jQuery,
sei que todas as variaveis com $ no nome, são objetos jQuery.
var $this = jQuery(this),
$dl = $this.parent('dl'),
i = 0,
str = '';
Faça bom uso dos arrays e objetos
Uma cadeia de if/elses ou switchs pode ser evitada se você souber
usar arrays e objetos javascript corretamente. Como por exemplo essa
lista de valores:
var values = [];
values[1] = { '1': '1,90', '6': '1,41', '12': '1,01' };
values[2] = { '1': '2,90', '6': '2,91', '12': '2,01' };
values[3] = { '1': '3,90', '6': '3,41', '12': '3,01' };
values[4] = { '1': '4,90', '6': '4,40', '12': '4,01' };
Tenho quatro “planos”; cada um com três opções de valores: planos
mensais, semestrais e anuais. Se eu fosse fazer isso com if ou switch, o
código ficaria bem ruim.
Separe comportamentos
Essa é uma coisa básica de programação. Divida um procedimento em
várias rotinas menores e escreva pequenas funções que resolvam uma parte
pequena do problema. Juntando todas, você terá resolvido tudo.
Leia este artigo:
Aprendi jQuery e agora?
E para terminar:
Faça bem o básico
É básico indentar corretamente, comentar qnuado necessário e
documentar. Estas são algumas pequenas boas práticas que vão fazer uma
boa diferença nos teus scripts. *** Artigo de William Bruno
|
Nos últimos meses, o assunto BYOD (Bring Your Own Device) tem
sido bastante debatido. Eu, pessoalmente, me envolvi em várias palestras
e reuniões com clientes para debater o tema. Mas observo muitas vezes
que a amplitude do impacto do modelo de consumerização e a consequente
transformação do paradigma de PC (Personal Computer) para Personal Cloud
não tem sido adequadamente percebido. Temos que olhar além do BYOD.
Devemos começar a visualizar o conceito de BYOC, ou Bring Your Own
Cloud.
Sair do conceito de My Documents para My Cloud tem implicações
bastante significativas na maneira de se pensar e usar a computação. A
nuvem pessoal vai transformar (aliás, já está transformando) a nossa
experiência digital. Uma nuvem pessoal é uma combinação de serviços e
aplicações nos quais os usuarios armazenam, sincronizam e compartilham
conteúdo, independentemente de plataforma, tamanho de tela e
localização. É muito mais abrangente que a simples substituição do disco
rígido do PC por armazenamento em uma nuvem. Uma personal cloud passa a
ser o hub digital para as pessoas, onde estarão penduradas a ela(s)
todos os seus dispositivos e conteúdos. Na minha opinião, permite criar a
visão da computação ubíqua.
Uma consequencia direta será o decréscimo da importância individual
dos dispositivos em troca da crescente significância do ecossistema,
cujo centro de gravidade será a nuvem. Daí as guerras pelo domínio do
ecossistema e da nuvem, onde iCloud e os dispositivos Apple ficam de um
lado e os sistemas baseados em Android e Google Drive de outro. Em
terceiro lugar, bem atrás no grid de largada, vem a Microsoft com seu
ecossistema baseado em Windows.
Com a crescente adoção das nuvens pessoais, acredito que nos próximos
anos veremos eclipsar o modelo atual, e mantemos nossos conteúdos em
nossos PCs pessoais, modelo que provavelmente será mantido apenas em
casos muito específicos. Já vemos muita coisa acontecendo com serviços
como DropBox, iCloud e dezenas de outros, conquistando milhões de
usuários. À medida que esses serviços forem gerando confiança, sua curva
de adoção tenderá a se acelerar.
Por outro lado, abre-se todo um novo campo para a criação de
aplicativos inovadores, basseados no conceito de nuvem pessoal e do seu
implicito sincronismo com qualquer dispositivo de acesso, seja ele um
smartphone, um tablet, um laptop ou uma TV.
O grande desafio será adotar o conceito My Cloud nas empresas… É cada
vez mais difícil separar nossa vida pessoal da profissional e, como a
nuvem pessoal passa a ser nosso hub de conteudo, como ignorar essa
tendência dentro das corporações? Uma coisa é armazenarmos em um DropBox
nossas fotos, músicas e vídeos das nossas férias, que pertencem a nós e
a decisão e o eventual risco é nosso. Outra é armazenar nessas nuvens
conteúdo que pertence às empresas para as quais trabalhamos.
Como é impossível segurar o tsunami que já está vindo, as empresas
devem criar políticas de uso das nuvens pessoais, criando mecanismos que
separem conteúdo profissional do pessoal e no caso de conteúdo
profissional garantam que estejam criptografados. Também é possível
criar políticas paliativas que impeçam, pelo menos por enquanto, o uso
de nuvens como iCloud e DropBox para armazenar informações corporativas.
Vale a pena ler este artigo,
que mostra por que a IBM proibiu o uso do DropBox dentro de sua
política de BYOD. Mas, por outro lado, é importante criar alternativas. A
IBM criou um similar a um DropBox interno chamado de MyMobileHube.
Sabemos que dizer não ao movimento de consumerização é absolutamente
inútil. Consumerização vai ganhar sempre. Portanto, a área de TI deve
desenhar estratégias de convivência que permitam, ao mesmo tempo,
oferecer dentro das empresas experiências similares à que os
funcionários têm em casa, mas que garantam um nível de segurança
adequado aos seus requisitos de compliance e auditoria corporativos.
Não é uma tarefa simples, mesmo porque muda o paradigma de domínio e o
controle ao qual a TI está acostumada. Além disso, há uma profusão de
dispositivos chegando a cada mês. O ritmo de inovações é muito
acelerado. Portanto, a política deve ser pragmática, definindo critérios
de aceitação de dispositivos e nuvens pessoais, não ficando presa a
produtos ou a modelos de dispositivos específicos. Manter a política sob
constante atualização e validação. Envolver as áreas jurídicas e de RH
no processo, até mesmo porque em determinadas situações as informações
corporativas que estão em nuvens pessoais podem estar em território
estrangeiro, o que iria contra algumas normas regulatórias de
determinados setores do negócio.
No final, é importante ter em mente que, mal entendemos e absorvemos o
conceito de BYOD, já estamos às voltas como o BYOC. E depois dizem que
ser gestor de TI não é um dos trabalhos mais estressantes que existem… *** Artigo de Cezar Taurion
|
Desenvolvendo um bookmarklet que será executado em dispositivos
iOS? Você provavelmente está procurando uma forma de testá-lo que não
inclui o termo “iCloud”.
A boa notícia é que você pode adicionar seus próprios bookmarks
personalizados e bookmarklets à lista estática do Simulador de bookmarks
do iOS para o testes.
A má é que isso não é nenhum mamão com açúcar…
A boa notícia depois da má é que não é muito trabalhoso e eu vou te ensinar como fazer!
Isso se aplica ao XCode 4.4.1 no Mac OS X 10.8.1.
1) Encontre o plist
A Lista de Propriedades dos bookmarks está dentro do pacote Xcode.
Dispare um terminal e execute este comando para navegar para o seu
diretório:
cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/Applications/MobileSafari.app
Uma vez nesse diretório, execute:
ls -l *Bookmarks*
Você verá vários arquivos, e um deles é chamado de StaticBookmarks.plist.

Esse é o nosso cara.
2) Obter permissão
O Xcode é de propriedade do usuário root do seu sistema, então você não pode editar o arquivo ainda. Idealmente, você poderia apenas fazer um sudo open StaticBookmarks.plist, mas isso não funciona mais. Acho que o novo versionamento de arquivos em Lion/Mountain Lion quebra isso.
Outro meio para atingir o mesmo fim é tomar posse do diretório MobileSafari.app e seus arquivos, assim:
sudo chown -R `whoami` ../MobileSafari.app
Isso não é o ideal, mas funciona bem o bastante. Há uma boa chance de
que as futuras atualizações do Xcode irão definir a propriedade de
volta a root, mas é mais provável que irão substituir diretamente o StaticBookmarks.plist – nesse caso, você está de volta ao princípio de qualquer jeito.
3) Edite no Xcode
Agora que você possui o arquivo e seu próprio diretório, o Xcode permitirá que você o edite. Abra-o no Xcode desta forma:
open StaticBookmarks.plist
Você deverá ver algo mais ou menos assim:

Propriedade List Editor.
Cada item dentro da chave “Root” é um bookmark. Para adicionar o seu
próprio, basta clicar no botão + ao lado da chave “Root” e adicionar um
item novo do dicionário. Ele deve ter duas chaves de string, uma para o
título do bookmark, e uma para o seu conteúdo.
Quando estiver tudo pronto, adicione o seu próprio bookmark (let). Deve ficar mais ou menos assim:
Push Pop é um bookmarklet pequeno no qual estou trabalhando.
4) Mãos à obra
Inicie o iOS Simulator e você deverá ver seu novo bookmark lá na lista com os outros!

***
Texto original disponível em http://blog.jerodsanto.net/2012/08/adding-your-own-bookmarks-and-bookmarklets-to-the-ios-simulators-mobile-safari/
|
O Módulo das CSS3 denominado “CSS Values and Units Module Level 3”
atingiu, em 28 de agosto de 2012, o status de Candidata a Recomendação.
Esse módulo destina-se a descrever os valores e unidades aceitas pelas
propriedades CSS, bem como a sintaxe usada para definir tais valores.
O módulo, entre outras novidades, criou três funções CSS destinadas a definir valores. São elas: attr() , calc() e toggle() . Nesse artigo estudaremos a função CSS calc().
Expressões matemáticas
A função calc() permite que se definam valores CSS com
uso de expressões matemáticas, ou seja, o valor adotado para a
propriedade é o resultado de uma expressão matemática.
Os operadores matemáticos válidos são: + (soma), – (subtração), *
(multiplicação) e / (divisão) e as unidades de medida CSS válidas no
cálculo matemático são as unidades para: comprimento, ângulo, tempo,
frequência e números.
O uso dessa função para definir valor CSS permite que se misture
diferentes unidades de medida. Isso não é possível com uso das CSS2.1 e
anteriores.
Vejamos a seguir dois exemplos práticos de uso dessa função:
Exemplo 1
HTML
<div></div>
CSS
body {
margin: 0;
padding: 0;
}
div {
width: 90%; /* para navegadores que não suportam calc() */
width: -webkit-calc(100% - 100px); /* para Chrome */
width: -moz-calc(100% - 100px); /* para Firefox */
width: calc(100% - 100px); /* para suporte nativo */
margin: 0 auto;
height: 200px;
border: 1px solid black ;
background: lime;
}
Nesse exemplo, centramos um elemento na tela e definimos sua largura
total igual a dimensão total da tela menos 100px resultando em um
elemento elástico com margens esquerda e direita constantes e iguais a
50px. Qualquer que seja a resolução da tela as margens laterais
permanecem inalteradas. Lembrar que definir a largura em percentagem
(por exemplo: 90%) sem uso de calc(), como fazemos com as CSS2.1 e anteriores, resulta em margens elásticas (no exemplo: 5% para cada lado) e não fixas.
Veja a renderização do exemplo
mostrado no Exemplo 1. Examine o código fonte da página e também
redimensione a janela do navegador para observar as margens constantes.
Use navegador Chrome ou Firefox, que atualmente suportam essa
funcionalidade com uso de prefixos proprietários. Em outros navegadores a
largura do elemento será 90% com margens elásticas.
Exemplo 2
HTML
<section id="container">
<div></div>
<div></div>
</section>
CSS
body {
margin: 0;
padding: 0;
}
#container {
width: 90%;
height: 300px;
border: none;
background: yellow;
}
div {
width: -webkit-calc(50% - 20px - 2em); /* para Chrome */
width: -moz-calc(50% - 20px - 2em); /* para Firefox */
width: calc(50% - 20px - 2em); /* para suporte nativo */
/* width: 50%; */
margin: 0 10px;
height: 200px;
border: 1em solid black ;
float: left;
background: lime;
}
.dois {
float: right;
background: red;
}
Nesse exemplo flutuamos dois elementos com bordas e margens, dentro
de um container, cada um deles ocupando 50% da largura do container.
Usamos a função calc() para ajustar os elementos no container.
Veja a renderização do exemplo
mostrado em: Exemplo 2. Examine o código fonte da página e também
redimensione a janela do navegador para observar o comportamento dos
elementos. Use navegador Chrome ou Firefox, que atualmente suportam essa
funcionalidade com uso de prefixos proprietários. Observe que sem uso
da função calc() não seria possível obter o efeito. Nas declarações CSS para os elementos div descomente a declaração width: 50%, e observe a renderização.
***
Oferta exclusiva para os leitores iMasters deste artigo: todos os livros do Maujor com 25% de desconto no site da Novatec Editora! Insira o código promocional maujor25 no carrinho de compras para gerar o desconto. (Válido até 01/11/2012) *** Artigo de Maujor
|
Alguns dias atrás uma colega me perguntou qual era o sentido das
propriedades em Python. Afinal, escrever propriedades exige tanto quanto
escrever um getter, ou um setter e elas realmente não adicionam
qualquer funcionalidade – com exceção de não ter que escrever ‘()’ no
acesso.
Superficialmente, esse argumento se atém a comparar uma classe simples implementada com getters e setters, e com propriedades.
Implementadas com getters e setters
>>> class GetSet(object):
... x = 0
... def set_x(self, x):
... self.x = x
... def get_x(self):
... return self.x
...
>>> getset = GetSet()
>>> getset.set_x(3)
>>> getset.get_x()
3
Implementadas com as propriedades
>>> class Props(object):
... _x = 0
... @property
... def x(self):
... return self._x
... @x.setter
... def x(self, x):
... self._x = x
...
>>> props = Props()
>>> props.x = 5
>>> props.x
5
A questão
Na verdade, nós fomos de 196 a 208 chars neste caso de uso simples –
então, por que usamos propriedades em tudo? A resposta é que, neste caso
de uso, nós não usaríamos. Na verdade, poderíamos escrever assim:
>>> class MyClass(object):
... x = 0
...
>>> my = MyClass()
>>> my.x = 4
>>> my.x
4
Eu posso ouvir você gritando: “Mas, não há encapsulamento!”. O que
vamos fazer se precisarmos controlar o acesso à x, torná-lo somente
leitura ou fazer outra coisa com ele? Não vamos ter que refazer tudo
para os getters e setters que evitamos?
Não, nós temos apenas que mudar para a versão apropriada, adicionar o
que desejamos, e não se alterar a interface. A melhor coisa das
propriedades não é que elas substituem getters e setters, é que você não
precisa escrever o seu código à prova do futuro. Você pode começar
escrevendo a implementação mais simples que se possa imaginar, e se mais
tarde você precisar alterar a implementação, você ainda pode fazer isso
sem alterar a interface. Bom, hein?
***
Artigo original disponível em: http://blaag.haard.se/What-s-the-point-of-properties-in-Python/#disqus_thread
|
Quando fazemos uma reflexão sobre o desenvolvimento de sistemas,
supondo desde 1995, podemos observar que o termo evolução está
intimamente ligado a separação entre dados e conteúdo. Vamos voltar a
1995, quando o web estava nascendo e não havia praticamente nada
definido em termos de sites e aplicações web. Neste tempo, o Delphi
ganhava mercado e se tornou, nos anos seguintes, uma boa ferramenta de
desenvolvimento Desktop. Naquela época, o conceito de MVC já era
conhecido e se iniciava um movimento rumo a separação entre duas
camadas: modelo e visão.
Com o passar dos anos, o desenvolvimento web ganhou força e, por
volta do ano 2000, linguagens como PHP e ASP estavam se consolidando no
mercado, sendo que outras surgiriam gradativamente. Independente da
linguagem, o que se pode observar entre os anos de 2000 e 2010 é um
crescimento muito forte do termo MVC. A sigla MVC pregava que o conteúdo
e o modelo de negócios deveriam estar separados em camadas, sendo
controlados através da terceira camada “controller”. Nos dias atuais,
este termo faz parte de qualquer tipo de desenvolvimento web, mas é
importante salientar que, independente da sigla ou conceito, a ideia é
que DADOS e TELAS estejam separados. A evolução aponta nesta direção;
cada vez mais os dados estarão separados da tela que o manipula, da
camada de visualização.
Dada esta introdução, vamos agora ilustrar como uma empresa de
desenvolvimento de software atravessa diversos problemas na criação de
sistemas:
Vamos supor que a empresa entrou em operação em 1995, no começo do
Delphi, e começou bem porque estava usando uma das melhores ferramentas
da época. O sistema em si era criado de forma a ter SQLs nos próprios
formulários (TForm, alguém lembra?), e com isso surgiram os primeiros
problemas daquela época. Como manter o código se tudo estava misturado?
Muitas foram as noites em claro para que os programadores pudessem ter
um software sem bugs para seus clientes.
Com o passar dos anos, o desenvolvimento web ganhou força. Existiam
diversas vantagens em ter um sistema web, e mesmo com poucos componentes
disponíveis, a empresa migrou o sistema para a linguagem PHP 3 (alguém
lembra do .php3?). Veja que a empresa mudou de linguagem e manteve o seu
padrão “despadronizado” de código. Os SQLs que manipulavam dados
estavam misturadas a tags HTML, o que gerou muita manutenção corretiva.
Mais alguns anos se passaram e, apesar da empresa já possuir uma
biblioteca de classes com as regras de negócio do sistema, o mesmo ainda
tinha uma manutenção complexa já que exibir estes dados era complexo.
Apesar dos dados estarem separados do conteúdo, era complexo manter
isso. Então, veio o conceito MVC e de como tudo seria mais fácil se o
padrão fosse implementado. Para se manter no mercado de forma ativa e
competitiva, a empresa decide realizar mais uma migração, saindo do PHP e
utilizando Ruby On Rails como framework, onde tudo está bem separado.
Tudo funciona bem até que a empresa decida implementar uma camada “rica”
na visualização, já que poderia usar componentes mais complexos. Cria
algumas telas em Adobe Flex e tem uma extrema dificuldade em integrá-la
ao Rubi on Rails. Agora, com o Flex em desuso e com a ascensão do HTML
5, a empresa se vê novamente em uma posição onde deverá alterar a
tecnologia para se manter no mercado.
Chegamos então ao atual estágio de maturidade da empresa. Eles
precisam novamente alterar a tecnologia, de forma que a camada cliente
possa mudar sem estar ligada a camada de dados. Veja que a ideia dos
desenvolvedores agora é separar ainda mais o MVC, de forma que os DADOS
sejam trabalhados de forma independente nos mais variados conteúdos
existentes – sejam eles desktop, web ou mobile. Assim como a Web
diminuiu o mercado desktop, o mobile está tomando o espaço do mercado
web, e a empresa quer mudar de forma que esteja preparada para futuras
mudanças no cliente.
Nos dias atuais, o melhor caminho a seguir é realizar uma mudança de
paradigma entre o MVC e sistemas REST. O REST é caracterizado como um
paradigma de desenvolvimento de software semelhante aos webservices, no
qual um serviço (que podemos chamar de API) é fornecido para consumo de
forma independente. Em outras palavras, REST garante que a troca de
dados entre cliente e servidor seja feita de forma atômica, sem
acoplamento entre as partes. Ou seja, o REST é usado para receber uma
requisição HTTP e retornar uma resposta que na maioria das vezes contém
dados.
Sistemas REST costumam possuir uma implementação totalmente separada
entre dados e design, sendo que até o processo de desenvolvimento de
software é separado. Existem diversas características que definem um
sistema como REST, mas vamos nos contentar apenas com o básico por
enquanto, que é o seguinte: um sistema REST recebe uma requisição HTTP
(seja ela GET, POST, PUT, DELETE) e retorna uma resposta em formato de
texto, que neste caso usaremos um formato de dados chamado JSON.
Isso garante que podemos construir um sistema no qual nos preocupamos
apenas com os métodos que manipulam os dados, e depois decidimos quem
vai usar estes dados. Com isso, nosso “núcleo” que manipula dados está
invariável em relação as constantes mudanças de tecnologia em relação ao
cliente. Poderemos usar Apache Flex, jQuery, javaFX, extjs, entre
outros.
Vamos criar a partir deste artigo, uma série de artigos que explicam
na prática como a teoria REST é aplicada, fazendo com que o núcleo que
gerencia dados é o mesmo independente dos seus consumidores. Aguardem! *** Artigo de Daniel Schmitz
|
Há algum tempo, tenho realizado meus projetos usando Virtual Machines
(VMs) e tem sido bem produtivo, além de eu deixar minha máquina
principal livre quando não estou desenvolvendo. Outra vantagem é ter à
mão o SO de produção, com suas dependências e problemas. Vou passar uma receitinha de bolo, levantando um ambiente LAMP em um Ubuntu, conectado com a máquina principal (o que nos permite centralizar o código e testar em diferentes ambientes).
Para dar uma apimentada na receita, vou utilizar Fastcgi e PHP-FPM (vale a pena ir mais a fundo no assunto, começando pelo site do projeto), além de revelar alguns truques que me são muito úteis no dia-a-dia de desenvolvedor.
Ingredientes
- Instalador/pacote do VirtualBox (obtida aqui) – foi utilizada a versão 4.1.8.
- Uma imagem ISO do Ubuntu Server (obtida aqui) – foi utilizada a versão 11.10.
- Conexão com a Internet.
Preparando a forma
Instale o Virtualbox de acordo com seu sistema operacional principal (:D). Caso use Linux,
peço que não utilize os pacotes dos repositórios (obtidas via apt, yum,
zypper, slapt…) – eles geralmente utilizam módulos pré-compilados de
kernel e estes não são atualizados com tanta frequência, ou ignoram o
kernel que você está utilizando, ou ainda te forçam a mudar o kernel que
já está instalado para que você possa usar o VBox; para evitar isso,
instale os pacotes build-essentials, dkms e kernel-headers (ou os
equivalentes para sua distribuição). Se você fizer dessa maneira, o
módulo de kernel do virtualbox será compilado de acordo com seu kernel
e, caso você o atualize, o dkms se encarregará de recompilar o módulo
deixando seu ambiente sempre estável.
Misturando os ingredientes (preparando a VM)
A partir da interface do Virtualbox, clique em New (Ctrl/Cmd + N) para iniciar o Wizard. Acompanhe a sequência de operações:
- Welcome to the New Virtual Machine Wizard[1] – Next (:D)
- VM Name and OS Type – dê um nome para sua máquina, selecione Linux em “Operating System” e Ubuntu ou Ubuntu (64 bit) em “Version”, de acordo com a ISO que você baixou e o suporte que seu computador oferece. Next
- Memory – deixe como está nesse primeiro momento. Next.
- Virtual Hard Disk – deixe como está (Start-up Disk e Create new hard disk selecionados). Next. Isso abrirá um novo Wizard.
- Welcome to the virtual disk creation wizard – Mantenha VDI Selecionado. Next.
- Virtual disk storage details – Dinamically allocated. Next.
- Virtual disk file location and size – Nomeie seu disco (o
default é o nome selecionado para a VM) e selecione o tamanho do HD
virtual. Pela seleção que fizemos no item anterior, mesmo que
selecionarmos 200 GB, não será alocado esse espaço no seu HD físico –
embora eu sempre deixe os 8 GB default, pois utilizaremos o HD físico
como storage principal. Next
- Summary – Create. Finaliza o 2º Wizard.
- Summary – Create. Finaliza o 1º Wizard.
Temos uma máquina virtual agora. Antes de ir ao próximo passo, vamos configurar sua interface de rede – selecione-a e clique em Settings. Vá na área Network. Em Adapter 1, mude a opção Attached to de NAT para Bridge Adapter; expanda a aba Advanced e, na opção Promiscuous Mode, selecione Allow All. Selecione Ok.
Mandando para o forno (instalando o sistema)
Com dois cliques na máquina criada, vamos inicializá-la. Na primeira
vez, como não temos nenhum sistema instalado, o VBox vai pedir que você
informe uma mídia para a instalação.
- First run wizard – Next
- Select Instalation Media – Em “Media Source,” selecione a imagem do Ubuntu que você baixou anteriormente (.ISO). Next
- Summary – Start.
Não vou entrar em detalhes sobre a instalação do Ubuntu Server.
Existe conteúdo na web muito bom que pode te dar mais informações e/ou
tirar dúvidas. Só peço que se atente na hora de dar um nome à maquina
(que será seu hostname – e vamos usá-lo depois de a máquina estar
devidamente “cozida”) e, quando o instalador te pedir para selecionar
dentre alguns templates de máquinas, NÃO
(sentiu o enfoque?) selecionar LAMP Server. Conclua a instalação. Ao
concluir, a VM irá reiniciar – nesse ponto, teremos uma máquina virtual
com Ubuntu Server pronta para uso.
Após retirar do forno (preparação de ambiente)
Durante a instalação, o próprio Ubuntu já realizou a maioria das atualizações – mas não custa fazer um apt-get update; apt-get upgrade. Vamos começar publicando o host dessa máquina na rede (sim, como deixamos ela em bridge, ela tem um ip válido):
# apt-get install openssh-server avahi-daemon
Isso vai instalar o openssh server (sem o qual não poderíamos acessar a máquina, a não ser pela interface da mesma) e o avahi, que, além de outras coisas, usa um recurso de DNS para redes locais. Entre com mais este comando:
# /etc/init.d/avahi-daemon restart
Agora sua VM pode ser acessada externamente pelo
<hostname>.local (não falei que usaríamos o hostname?). Tente dar
um ping ou conectar por ssh a partir de sua máquina local.
Agora vamos instalar o guest-tools. Caso você já seja usuário do
VirtualBox, provavelmente você já fez isso para poder usar os recursos
gráficos de sua máquina real na virtual. Uma das vantagens de ter o
guest-tools instalado na virtual é usar um filesystem especial, o
vboxsf, que permite a você montar um diretório da maquina real na
virtual. Sua instalação é simples de um ambiente gráfico, mas na linha
de comando (que é só o que temos agora) temos uma trilha diferente a
seguir. Antes de qualquer coisa, vamos instalar uns pacotinhos:
# apt-get install make build-essential dkms
Olha o dkms
aí de novo, só que agora para a VM. Esses pacotes serão usados para
compilar os módulos do guest-tools e manter isso atualizado através de
qualquer atualização de kernel que venha a acontecer. Agora, da janela
da máquina virtual, clique em Devices e depois em Install Guest Additions. Em seguida, montamos o “CD” de instalação do guest tools:
# mkdir /mnt/cdrom; mount -t iso9660 /dev/cdrom /mnt/cdrom
Executamos o instalador:
# /mnt/cdrom/VBoxLinuxAdditions.run
Reinicie a máquina virtual. Após isso, da janela da máquina virtual,
clique agora em Machine, depois em Settings e vá até a aba Shared
Folders (ou clique no ícone de pasta no canto inferior direito da
janela). Lá, acesse a opção de Adicionar no lado direito da janela (Add
Shared Folder, [Insert]). Em Folder Path, insira o caminho para seu
diretório de projetos, ou outro que desejar, para compartilhar com a
máquina virtual; em Folder Name, insira o nome para identificarmos o
compartilhamento na máquina virtual – utilizaremos o nome Projects;
marque também a opção Make Permanent e clique em OK.
Agora vamos mudar o fstab para montar nosso diretório de Projetos
real na máquina virtual, sempre. Adicione a seguinte linha em /etc/fstab
(considerando que iremos usar o diretório na VM /mnt/Projects):
Projects /mnt/Projects vboxsf rw,defaults 0 0
E monte então o compartilhamento criado anteriormente:
# mkdir /mnt/Projects; mount -a
Agora verifique o diretório. Esse filesystem virtual vai nos permitir acesso instantâneo de leitura e escrita.
Decorando o bolo (agora o PHP de fato)
Vamos instalar um monte de coisas:
# apt-get install php-pear php5-cli php5-curl php5-dbg php5-dev php5-gd php5-mysql php5-sqlite php5-xsl php-apc php5-fpm apache2 apache2-mpm-event apache2-utils libapache2-mod-fastcgi
Isso instalará o PHP da versão mais estável para a versão corrente do
Ubuntu (quando fiz, estávamos com o PHP 5.3.10 lançado, e o Ubuntu
disponibilizava a 5.3.6), extensões GD, Mysql, SQLite, XSL, APC,
PHP-FPM, o Apache, seus módulos utilitários, fastcgi e o MPM event.
Ele é um módulo MPM experimental no Apache 2.2, variante do MPM worker.
Temos 4 tipos: event, worker e prefork e itk. Na instalação
tradicional, é utilizado o prefork, que nos permite utilizar o PHP no
apache como módulo nativo – o que nos impede de usar o fastcgi. No
modelo que acabamos de instalar, o Apache funcionará muito mais próximo
de outros webservers de mercado, como o nginx. Caso não queira arriscar
um módulo experimental, troque apache2-mpm-event por apache2-mpm-worker
no comando de instalação acima – em uma máquina virtual para uso de
pesquisa, você não terá problemas com qualquer um dos dois – ou aguarde o
Apache 2.4 e suas novidades.
Sinta-se à vontade para fazer o ajuste fino que precisar (ou que já esteja acostumado a usar) na instalação do PHP (a configuração padrão fica em /etc/php5).
Eu ultimamente tenho usado o seguinte template de caminho para meus projetos:
/var/lib/<vendor>/<project>/<version>/
Onde <vendor> é o dono do projeto, <project> seu nome ou
id e <version> é a versão (Dãã). Nesse último item, eu faço um
“truquezinho”: não aponto o diretório web diretamente para uma versão,
mas para um link simbólico “current” – este sim é mapeado pelo Apache
para publicar. Se for necessário realizar uma troca de versão, ou
atualização da mesma, eu nem encosto no servidor web. Dando um exemplo
de como fica:
/var/lib/duodraco/teste/12.2
/var/lib/duodraco/teste/current -> /var/lib/duodraco/teste/12.2
Vamos configurar um virtualhost no Apache apontando para um diretório
web nessa estrutura. Criem um arquivo /etc/apache2/sites-available/test
com o seguinte conteúdo (trocando obviamente o endereço pelo que você
vai utilizar):
<VirtualHost *:80>
DocumentRoot /var/lib/duodraco/teste/current/web
ServerName dev.local
<Directory /var/lib/duodraco/teste/current/web>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
FastCgiExternalServer /var/lib/duodraco/teste/current/web/php5.external -host 127.0.0.1:9000
AddHandler php5-fcgi .php
Action php5-fcgi /usr/lib/cgi-bin/php5.external
Alias /usr/lib/cgi-bin/ /var/lib/duodraco/teste/current/web
</VirtualHost>
Note as ultimas 4 linhas dentro da tag VirtualHost. Elas adicionam um
manipulador virtual para que o Apache, ao receber requisições que devam
ser tratadas pelo PHP, direcione-as para o FastCGI, que no nosso caso é
gerenciado pelo FPM. Agora desabilitamos o site default, habilitamos o
teste e ativamos o módulo Actions:
# a2dissite default; a2ensite teste; a2enmod actions
Em seguida, reiniciamos o Apache e o fpm:
# service apache2 restart && sudo service php5-fpm restart
Crie e edite o arquivo /var/lib/duodraco/teste/current/web/index.php e insira o seguinte conteúdo:
<?php
echo "Hello World!";//Só para falar que estamos fazendo um hello world mesmo
phpinfo();
Agora acesse http://<hostname>.local/ pela maquina real e voilá. Dê uma olhada na informação gerada pelo phpinfo e note que o Server API é FPM/FastCGI.
Como queremos que isso seja um ambiente de desenvolvimento, vamos instalar o xdebug:
# pear update-channels
# pecl install -a xdebug
O PECL irá baixar e compilar o xdebug para você. No fim da
instalação, você deve adicionar o xdebug à configuração do PHP. Para
isso, crie o arquivo /etc/php5/conf.d/xdebug.ini e insira o seguinte
conteúdo nele:
zend_extension="/usr/lib/php5/20090626/xdebug.so"
Geralmente, os tutoriais dizem para reiniciar o apache… mas estamos usando o FPM, lembram? Basta executar:
# /etc/init.d/php-fpm/restart
Confira novamente o index de nosso projeto e você verá o xdebug no seu devido lugar. Agora faça a sintonia fina dele para seu uso.
Bom, enquanto estávamos preparando a receita, deixamos um
compartilhamento ali prontinho para brincarmos, certo? Digamos que em
sua “real machine” você tenha um diretório com um projeto “teste2″… o
que aconteceria com a nossa virtual machine se executássemos os
seguintes comandos?
# ln -s /mnt/Projects/teste2 /var/lib/duodraco/teste/development
# rm /var/lib/duodraco/teste/current
# ln -s /var/lib/duodraco/teste/development /var/lib/duodraco/teste/current
Sim, você tem o seu projeto da maquina real, na virtual, acessível
pela real (e por qualquer máquina em sua rede). Utilize seu IDE ou
editor preferido no SO principal para editar o projeto e deixe bancos de
dados, Apache e outras coisas que ocupam memória e processamento no
sandbox da máquina virtual.
Ao terminar uma versão, crie uma cópia, aponte o “current” para essa cópia e mostre a seu cliente, gerente
ou mesmo colega de trabalho sem encostar no /etc/hosts da sua máquina
real. Quando estiver desenvolvendo novamente, troque o link. Quando não
estiver mexendo no projeto, desligue a VM, encerre a IDE e tenha a
máquina para mais coisas… nem passa pela minha cabeça que muita gente
deixa o MySQL e o Apache da máquina rodando enquanto tenta jogar no
computador.
Sei que o artigo ficou meio extenso, mas queria passar um ambiente não tão básico para desenvolvimento – com a apimentada
citada. Temos alguns outros truques ainda para falar como git, jenkins,
mongodb … e este artigo serve de base para eles. Até o próximo.
PS: Gracias ao Mr @alganet – sem o qual eu não teria páprica para a receita. *** Artigo de Anderson Casimiro
|
Da última vez, sugeri sobre o uso de sequências De Bruijn
para acelerar a iteração de conjuntos de bits. É um velho truque que
(eu acho) foi descoberto por programadores de xadrez em nos anos 60 (eu
realmente preciso de uma referência para isso).
É um clássico que gera um código elegante e quintessencial, mas
realmente precisa de uma explicação paralela do que está acontecendo.
O problema
Para um número binário, escreva uma função que determina o número
zeros perdidos, ou seja, quantas vezes você pode dividir esse número por
2 sem resto.
A implementação trivial é esta:
let rec ntz n =
let rec loop acc n =
if n land 1 = 1
then acc
else loop (acc+1) (n lsr 1)
loop 0 n
É surpreendente saber que é possível encontrar a resposta sem fazer loop.
O menos importante
Se você observar o problema, rapidamente vai perceber que não há apenas um 1 que importa. O menos significativo.
Ele pode ser isolado da seguinte forma:
lso = n land ((lnot n) + 1)
ou (menor)
lso = n land (-n)
Vejamos alguns exemplos de números de tamanhos de byte
n |
bin(n) |
bin (lnot n) |
bin (-n) |
lso |
2 |
0000 0010 |
1111 1101 |
1111 1110 |
0000 0010 |
7 |
0000 0111 |
1111 1000 |
1111 1001 |
0000 0001 |
40 |
0010 1000 |
1101 0111 |
1101 1000 |
0000 1000 |
48 |
0011 0000 |
1100 1111 |
1101 0000 |
0001 0000 |
Vamos fazer uma volta agora com teoria dos gráficos.
Gráficos De Bruijn
A coisa importante para lembrar é como você constrói esse gráfico. O exemplo a seguir é um gráfico
de (2,3). Você começa com um vértice 000. Então, a partir de um
vértice, você desloca ou um 1 ou um 0, e desenha uma borda para o nó de
resultado. Itere e pare quando você tiver todos eles.
Assim, após a primeira etapa, você tem isto:

E no próximo passo você tem

E o gráfico fechado é:

Sequências De Bruijn
A sequência De Bruijn é apenas um atalho para um caminho Hamiltionian
(um caminho que visita cada vértice de uma vez) por meio de um gráfico
De Bruijn. Um exemplo desse um caminho para o gráfico completo acima é:
000 -> 001 -> 010 -> 101 -> 011 -> 111 -> 110 -> 100 -> 000
Uma representação compacta para esse caminho pode ser gravada
anotando o ponto de partida e as escolhas feitas em cada ponto. O
exemplo produz a seguinte sequência:
00010111
Ao deslizar pela sequência, um bit por vez com uma janela de 3 bits,
cada uma das oito possíveis sequências de três dígitos aparece
exatamente uma vez.
n |
index |
000 |
0 |
001 |
1 |
010 |
2 |
011 |
4 |
100 |
7 |
101 |
3 |
110 |
6 |
111 |
5 |
O truque
A tabela acima mostra que em cada nó a quantos passos você está da fonte do gráfico. Então, se você multiplicar a sequência com o least significant one ou o nosso número, podemos usar a tabela para saber quantas trocas tivemos.
Por exemplo: 00010111 * 0010000 = 00101110000. Você mantém a sequência de 8 bits 0111000 que está mais à direita.
Ao olhar para a sequência de 3 (= 8-5) bits 011 da extrema esquerda,
que você encontra deslocando cinco posições para a direita, você vê que
eles estão no índice 4 na tabela. Portanto, o número tem 4 zeros à
direita.
Resumo
Para encontrar o número de zeros perdidos para um número de 8 bits, você precisa
- De uma sequência De Bruijn de 8 bits: debruijn = 00010111
- De uma tabela de 8 entradas pré-computadas 0,1,2,4,7,3,6,5
- Da seguinte fórmula:
lso = n & (-n)
ntz = table[(lso * debruijn) >> 5]
Versão de 64 bits
Se você quiser fazer isso para 64 bits, você tem que seguir
exatamente o mesmo raciocínio. Você precisa de uma sequência debruijn de
64 bits (há 2^26 delas), e uma tabela pré-computada de tamanho 64.
#define DEBRUIJN 0x22fdd63cc95386dULL
static uint32_t table [64] ;
void inittable (){
uint64_t db = DEBRUIJN ;
int i ;
for (i=0 ; i < 64;++ i ) {
table [db >> 58] = i ;
db = db <<1;
}
}
uint32_t ntz ( uint64_t n){
n &= −n ;
n ∗= DEBRUIJN ;
n >>= 58;
return table [n] ;
}
Utilização em bitsets
Suponha que você esteja representando um bitset como um array de
palavras de 64 bits. Ao iterar, você desliza através das palavras, e se
um bit é 1 você faz a sua coisa. Se o resto das palavras através das
quais você está deslizando contém apenas zeros, você está desperdiçando
esforço. Conhecer o número de zeros perdidos permite calcular o último
índice para o loop sobre os bits de uma palavra.
Um olhar sobre uma biblioteca padrão aleatória
Java
Existe uma classe java.util.BitSet que tem estado na
biblioteca padrão java desde a versão 1.0. Já que o código é aberto,
podemos inspecioná-lo. Vamos dar uma olhada.
O iterador usa
Long.numberOfTrailingZeros(word)
e a implementação é:
public static int numberOfTrailingZeros(long i) {
// HD, Figure 5-14
int x, y;
if (i == 0) return 64;
int n = 63;
y = (int)i; if (y != 0) { n = n -32; x = y; } else x = (int)(i>>>32);
y = x <<16; if (y != 0) { n = n -16; x = y; }
y = x << 8; if (y != 0) { n = n - 8; x = y; }
y = x << 4; if (y != 0) { n = n - 4; x = y; }
y = x << 2; if (y != 0) { n = n - 2; x = y; }
return n - ((x << 1) >>> 31);
}
(você pode ler o código fonte completo aqui: Long.java)
Se divirta!
***
Texto original disponível em http://blog.incubaid.com/2012/01/24/number-of-trailing-zeroes/
|
Falem o que quiserem, mas não há nada melhor para explicar um
determinado conceito do que um diagrama visual. Por isso mesmo, separei
aqui oito diagramas que vi lá no site do LukeW, sobre os fundamentos da experiência do usuário, em formato PDF. Aproveite!
- Os Elementos da Experiência do Usuário (Jesse James Garrett)
Modelo conceitual dos elementos envolvidos na concepção de experiências de usuários. - Ciclo de Experiência do Usuário (Jess McMullin)
A experiência do usuário não é uma simples ação, é um ciclo interligado
que tenta satisfazer as esperanças, sonhos, necessidades e desejos. - Processo de Design Centrado no Usuário (John J. Stickley)
Diagrama criado para comunicar o processo de design do SCM User Experience Group’s. - O Cosmos da Experiência do Usuário (Javier Cañada)
Uma representação cartesiana da área da UX. Como em mapas antigos, esta é uma representação bastante subjetiva e pessoal. - Processo de Design (Erin Malone)
Baseado em diagramas criados por equipes de UI Design da America Online. Revisado e editado por Erin Malone para o Instituto de Arquitetura de Informação em setembro de 2003. - Fluxo do Design da Experiencia do Usuário (Erin Malone)
Um fluxo mapeando as etapas e resultados do projeto através das áreas de UI / IA / UX. - “Exemplo de encontros” para Arquitetura de Informação (Miyuki Shimbo)
Cartaz ilustrando as etapas do processo de Arquitetura de Informação (e comparando-os com a relação do namoro). - Um Modelo de Experiência do Usuário (Userfocus)
Apesar de ser um diagrama simples, abrange todas as atividades realizadas pelos profissionais de UX.
*** Artigo de Edu Agni
|
A programação em par
é uma prática um tanto quanto controversa, e altamente ágil
contra-intuitiva. Em poucas palavras, são duas pessoas que trabalham na
mesma coisa, usando apenas um computador, ao mesmo tempo. Parece loucura
que isso funcionaria de fato, muito menos ser melhor do que dois
programadores trabalhando separadamente. Mas de alguma forma ela
funciona.
Estamos usando essa técnica há algum tempo, e tenho notado alguns benefícios interessantes que gostaria de compartilhar.
Eliminando dialetos
Se você pedir a 10 pessoas para escrever um pequeno parágrafo sobre
uma ideia específica, provavelmente receberá 10 resultados muito
diferentes. De fato, isso provavelmente seria verdade mesmo se você
tivesse especificado exatamente o que queria que a pessoa escrevesse
(tudo – desde quantas frases deveriam ser utilizadas até as estruturas
gramaticais permitidas).
O mesmo vale para os programadores. Os devs possuem seus próprios
estilos de escrita de código, não importa a linguagem. Eles diferem em
nomes de variáveis e nomes, preferências para construções específicas de
fluxo de controle, comentários de estilos etc. Resumindo, os devs
possuem seus próprios dialetos.
Esses dialetos são especialmente perceptíveis quando um único dev
trabalha exclusivamente em uma parte específica de uma grande base de
código. Ler módulos diferentes em um código fonte é como ir a uma
excursão no campo e ouvir tudo com sotaques diferentes.
Claro, existem coisas que você pode fazer para tentar minimizar essas
diferenças (coisas como padrões de codificação e convenções de
nomenclatura). No entanto, acho que a maioria dos devs tem dificuldade
em seguir as convenções de nomenclatura quando são deixados à sua
própria sorte. É muito fácil recorrer ao seu dialeto quando ninguém está
olhando.
Comece a trabalhar em par (pairing). O pairing é quase
surpreendentemente eficaz em eliminar dialetos de dev e em obter um
código inteiro para ler a base como se fosse escrito por um único
programador. Aparentemente, é muito mais difícil injetar seu próprio
estilo no código quando alguém assume o teclado a cada poucos minutos.
Reduzindo a complexidade
Muitos devs amam a complexidade. Mais perturbador, muitos se sentem
obrigados a, desnecessariamente, introduzi-la no código que escrevem. O
mais preocupante de tudo é que poucos têm a autoconsciência para
perceber o que estão fazendo antes que seja tarde demais. Então, os
códigos fontes em todos os lugares estão repletos de versões diferentes
de uma máquina de Goldberg.
O fato é que, quando o código está apenas na sua cabeça, ele
normalmente parece muito simples. As condições de limites e os casos
extremos são examinados rapidamente, saltos esquisitos de lógica não
parecem tão estranhos, as construções complexas parecem simples, e assim
por diante.
A programação em par te obriga a explicar suas
ideias de design aparentemente racionais para outro ser humano. Na
maioria das vezes, o próprio ato de explicar para alguém o ajuda a
perceber que algo está errado. E, se isso não o faz, um olhar intrigado
ou um cético “OK…” do seu par provavelmente o fará.
Pensamento final
As duas razões mais comumente aceitas para programação em par são
promover propriedade compartilhada e forçar revisões de código
contínuas. São benefícios importantes com certeza, mas a programação em
par também ajuda de outras maneiras. Você já notou algum que você
gostaria de compartilhar?
***
Texto original disponível em http://tatiyants.com/benefits-of-pair-programming/
|
O que mais vejo em listas de discussão da área de segurança e
ouço de meu alunos e pessoas que assistem minhas palestras é a seguinte
pergunta: qual é a melhor certificação na área de segurança da
informação? Há outras variantes sobre o mesmo tema, mas é sempre alguém
querendo saber qual é a melhor certificação para se obter tanto para
quem está entrando nessa área, quanto para quem quer crescer ainda mais.
Por conta de tantas dúvidas sobre o mesmo assunto, ainda mais na área
de S.I., pensei em escrever esse artigo para clarear um pouco mais a
questão.
Primeiro, vou tentar elencar as certificações mais importantes para o
mercado nesse momento, tanto para quem pensa em enfrentar o mercado
tupiniquim, quanto para quem pensar em buscar outras oportunidades ao
redor do mundo. Afinal, certificação reconhecida apenas nacionalmente,
em plena era da globalização, é pura perda de tempo. A maioria das
certificações que procurarei abordar, são vendor neutral, mas algumas
fugirão dessa regra, por mais que eu me esforce.
Um exemplo disso, são as certificações da CISCO. Por mais que
queiramos fugir, a CISCO ainda detém uma imensa fatia do mercado de
equipamentos de redes e infraestrutura. E esse fabricante, por saber o
quanto a segurança de uma infraestrutura é importante para uma
organização, desenvolveu um currículo bem interessante para os
profissionais que já trabalham com CISCO e possuem pelo menos o CCNA.
Partindo dessa certificação básica desse vendor, o profissional pode
decidir por especializar-se em segurança de infraestrutura de redes,
seguindo o padrão CISCO com as certificações CCNA Security, CCNP
Security e CCIE Security.
Essas certificações são bem interessantes quando pensamos no
profissional que atua como analista de infraestrutura e deseja migrar
para a área de segurança. Mas e para o profissional que administra
redes? As certificações LPI, voltadas para Linux são muito boas,
principalmente quando culminam na LPI 303, cujo foco é segurança em
servidores Linux. A LPI 303 aborda temas que possibilitam o profissional
que atua com Linux realizar o hardening e proteger seus servidores de
acessos indevidos e ataques remotos e locais. Os temas abordados
englobam desde criptografia de disco, à VPN e monitoramento com Nagios.
Eu costumo inclusive brincar que se uma empresa quer um profissional
com conhecimento de infra e administração de redes, é só ver se o
profissional tem o conhecimento prático e vivencial que é pedido para
uma certificação LPI e CISCO conjugadas. Mas vamos em frente, pois o
nosso foco aqui é segurança… E só falamos de quatro certificações até
agora.
Quando alguém me pergunta qual a melhor certificação para conseguir
entrar no mercado de SI, prontamente digo: ISO 27002. Essa é bem básica,
fácil de tirar e precisa constar no currículo de todo profissional de
segurança da informação. Mas deve-se ficar bem claro que, junto dessa
certificação, o profissional deve ter um conhecimento extenso sobre a
norma ISO 27001, para saber o porque de muita coisa da 27002. Mas ainda
assim, essas certificações ainda são para níveis de gestão e consultoria
apenas, sem conhecimento técnico muito forte como pré-requisito.
Outra certificação para quem já tem um pé em segurança, atuando com
alguns controles, como administrador de redes ou analista de infra (onde
em muitas empresas é esse o profissional que faz tudo), é a Security+,
da CompTIA, que aborda diversos temas sobre segurança e precisa da
comprovação de dois anos de atuação na área. Considero essa certificação
como um nível intermediário, preparatório para outras mais complexas.
Continuando ainda no nível de gestão, temos a CISM (Certified
Information Security Manager), criada pela ISACA, que tem como foco os
profissionais que atuarão como gerentes de SI, tomando as decisões mais
burocráticas e de nível de gestão que envolvem a segurança em uma
organização.
Da ISACA também, com um bom nível de importância no mercado, temos a
CISA (Certified Information Systems Auditor), que possui um foco em
auditoria, controles e segurança. Se o profissional pretende seguir o
rumo da auditoria em TI e SI em geral, essa é uma certificação
obrigatória.
Partindo agora para uma outra empresa certificadora, onde se
encontram atualmente as certificações mais requisitadas pelo mercado de
segurança: a (ISC)². Cito três certificações como as mais interessantes
para os profissionais que já atuam na área, mas precisam de um respaldo
maior para ascenderem em suas carreiras: SSCP, CSSLP e CISSP.
A primeira dessas certificações, SSCP (Systems Security Certified
Practitioner), tem como foco profissionais que atuam como analistas de
segurança, administradores de rede e sistemas. A prova engloba parte dos
domínios existentes no CBK (Common Body Knowledge), e que também fazem
parte dos domínios cobrados na prova para a CISSP. É interessante para
os profissionais que estão iniciando em segurança, que não se sentem
seguros para realizar a prova para CISSP já de início, mas querem uma
certificação respeitada internacionalmente na área.
Já a CSSLP, Certified Secure Software Lifecycle Professional, é uma
das primeiras certificações no mundo a abordar o tema desenvolvimento
seguro. Não há foco na codificação, ou limitação no que diz respeito às
linguagens que suporta, pois é mais global, focando em todo o ciclo de
produção de um software e validando em cada ponto, os princípios de
segurança existentes.
Há pouquíssimos profissionais dessa área no mercado atualmente, e é
uma excelente oportunidade para quem trabalha com desenvolvimento e quer
migrar para segurança da informação, pois permitirá coadunar sua
experiência prévia com os novos conceitos aprendidos sobre segurança, e
de uma maneira que está de acordo com as necessidades atuais do mercado.
Agora, chegamos na certificação mais importante para o mercado de
segurança: a CISSP. Devemos manter em mente que ela não é uma
certificação técnica e nem tem esse objetivo. No entanto, ela requer um
conhecimento bem amplo quanto as soluções existentes nos diversos
domínios do CBK desenvolvido pela (ISC)². Tais domínios abordados na
prova são:
- Access;
- Control;
- Application;
- Development Security;
- Business;
- Continuity and Disaster Recovery Planning;
- Cyptography;
- Information;
- Security Governance and Risk Management;
- Legal;
- Regulations, Investigations and Compliance;
- Operations;
- Security;
- Physical;
- (Environmental) Security;
- Security;
- Architecture and Design;
- Telecommunications;
- Network Security.
A prova era aplicada apenas em papel e em inglês. Mas em setembro de
2011 elas passaram a ser aplicadas em português, e partir de outubro de
2011, elas também passaram a ser realizadas em alguns centros
credenciados pela VUE e Prometric.
Essas duas decisões foramo importantes para, em primeiro lugar, focar
a avaliação nos domínios, e não no nível de proficiência que o
profissional tem da língua inglesa. E em segundo, porque antes haviam
poucas vagas nas poucas vezes em que a prova era aplicada aqui no
Brasil, inclusive forçando os profissionais se deslocarem para São
Paulo, gastando com deslocamento e hospedagem para realizar a prova, e
ainda assim corriam o risco de não conseguir vagas para a prova, já que
sempre eram poucas. E uma das coisas interessantes é que antes era
necessário aguardar algumas semanas, e agora com a prova no formato
eletrônico, o resultado sai assim que o candidato finaliza a prova.
Agora, quem quiser realizar essa prova, prepare-se para a maratona;
pois são em média 250 perguntas, mas sem uma solução muito definida do
tipo “qual a flag de resposta quando é enviado uma pacote com a flag
null ativa para uma porta aberta?”. Na prova da CISSP, as questões são
sempre contextualizadas, cobrando uma solução que melhor se encaixe
naquele cenário específico. Por isso, alguns anos de experiência na área
de segurança, além de ser um dos pré-requisitos para obter a
certificação, também auxiliará o profissional à responder as questões de
forma mais concisa e coerente.
Essa certificação, CISSP, é pré-requisito para quem quer sair do
Brasil e conseguir uma vaga lá fora na área de segurança da informação. E
aqui no Brasil, como ainda são poucos os profissionais com esse
certificado, ainda é possível conseguir bons salários comparados com
outras áreas de atuação em nosso país (faixa salarial de R$10 mil a R$20
mil dependendo do nível de gestão em que o profissional atue). Para
quem quiser saber um puco mais sobre os domínios abordados nas provas
das certificações da (ISC)², é interessante acessar esse link.
Agora vamos partir para certificações mais técnicas, e analisar
algumas das oferecidas pela SANS, EC-Council, ISECOM, Offensive Security
e Immunity.
A SANS, através da entidade certificadora, conhecida como GIAC
(Global Information Assurance Certification), oferece dezenas de
certificações para a área de segurança da informação. Vou falar apenas
de algumas delas.
As certificações oferecidas pela SANS são altamente reconhecidas no
mercado internacional, mas ainda estão em processo de valorização aqui
no Brasil. Portanto, se quer uma certificação conceituada e tem como
objetivo sair do Brasil ou atuar em uma multinacional, as certificações
GIAC são uma excelente pedida.
Elas são agrupadas em categorias, que são as seguintes, atualmente:
- Security Administration;
- Audit;
- Management;
- Operations;
- Software;
- Security and/or Secure Coding;
- Forensics;
- Legal;
- Expert.
Entre essas categorias, podemos contar com dezenas de certificações,
as quais destaco a seguir como sendo as mais interessantes na parte
técnica referente à segurança, de acordo com a área de atuação desejada
pelo profissional.
- Para quem atua ou quer atuar com resposta à incidentes:
GCIA – GIAC Certified Intrusion Analyst
GCIH – GIAC Certified Incident Handler
- Para quem deseja atuar com teste de invasão e avaliações de segurança:
GPEN – GIAC Penetration Tester
GWAPT – GIAC Certified Web Application Penetration Tester
GAWN – GIAC Assessing Wireless Networks
- Para quem deseja atuar com forense computacional e análise de malware:
GCFE – GIAC Certified Forensic Examiner
GCFA – GIAC Certified Forensic Analyst
GREM – GIAC Certified Reverse Engineering Malware
Desde 2005 surgiu uma controvérsia com relação às certificações da
SANS, mas nada que comprometesse sua credibilidade no mercado. Essa
organização decidiu facilitar o processo de obtenção de suas
certificações criando dois níveis, o Silver e o Gold. Para tirar uma
certificação no nível Silver, basta o profissional realizar as provas de
múltiplas escolhas necessárias para aquela área específica. No entanto,
se o profissional quiser ser um certificado Gold, ele precisa finalizar
o desafio prático apresentado, para comprovar sua aquisição de
conhecimento aplicado à situações práticas.
A Ec-Council, outra entidade que oferece certificações para a área de
segurança, também possui reconhecimento internacional – inclusive com a
chancela do Pentágono (órgão de defesa americano). Suas certificações
têm ganhado um reconhecimento maior no mercado brasileiro e possuem um
foco mais técnico do que gerencial. Apesar da Ec-Council oferecer mais
de uma dezena de certificações, vou abordar apenas quatro delas, com
foco mais técnico e próximo das necessidades de um profissional de
segurança. São elas: ECSA, CEH, LPT e CHFI.
Para quem está iniciando em segurança, está bem cru mesmo e quer
entender o que um analista de segurança faz e quais suas atribuições,
aconselho a certifica ECSA (Ec-Council Security Analyst), que aborda os
temas básicos da atuação com segurança da informações e os controles de
segurança que precisam ser implementados, para tornar uma infraestrutura
mais segura. Agora, não esperem demais dessa certificação, pois ela é
inicial e introdutória no assunto de segurança, não sendo indicada para
profissionais que já atuem na área e tenham experiência de alguns anos.
Para quem quer algo um pouco mais aprofundado, a CEH (Certified
Ethical hacker) é mais interessante, pois já aborda a questão das
avaliações de segurança, como teste de invasão e auditoria de segurança
em redes e sistemas. É reconhecida internacionalmente, mas na minha
opinião peca por não ter uma avaliação prática, com desafios do tipo
“capture the flag”. Entretanto, ainda assim é uma certificação
interessante que força o aluno a estudar bastante os conceitos de
segurança e testes.
Atualmente, reunindo a certificação ECSA e CEH, caso o profissional
tenha experiência e atuação com testes de invasão, ele pode reunir as
documentações comprobatórias necessárias de sua experiência e requerer à
Ec-Council a certificação LPT (Licensed Penetration Tester), que
certifica o profissional como sendo um pentester reconhecido por uma
organização internacional, a Ec-Council.
Confesso que dessas certificações da Ec-Council, aqui no Brasil só vi
em vagas de empregos, a solicitação da CEH e da CHFI, a próxima a ser
comentada.
A CHFI (Certified Hacking Forensic Investigator) já possui um foco
bem específico, que é a forense computacional. É bem interessante o
conteúdo cobrado, desde que o profissional saiba como aplicá-lo, pois
como todas as outras provas da Ec-Council, é tudo teórico com múltiplas
escolhas. No entanto, o nível técnico dessa certificação é superior aos
das citadas anteriormente, pois pressupõe um conhecimento prévio do que é
abordados nas três certificações anteriores. Afinal, como um
investigador poderá encontrar indícios se não conhece como deve ser um
ambiente seguro, como normalmente ele pode ser comprometido, e quais as
ferramentas e métodos utilizados numa invasão? Logo, podemos assumir que
a CHFI é uma reunião dos conhecimentos necessários para as
certificações anteriores mais o conhecimento investigativo necessário
para a recriação de cenários complexos através da descobertas de
indícios e evidências, em sistemas Windows, Linux, MAC, imagens,
roteadores, redes, e etc.
As três organizações restantes, ISECOM, Offensive Security e
Immunity, oferecem poucas certificações, mas nem por isso são menos
importantes.
A ISECOM é responsável pela manutenção e suporte à OSSTMM, uma
metodologia internacionalmente aceita como muito adequada para a
realização de testes de invasão. O que é interessante é que essa
metodologia foi tão bem aceita no mercado, que estuda-se a possibilidade
de transformá-la em uma norma ISO, específica para os testes de
segurança. Portanto, qualquer uma das duas certificações dessa entidade,
OPSA e OPST (OSSTMM Professional Security Analyst e OSSTMM Professional
Security Tester), é interessante para quem quiser já estar preparado
para essa mudança radical, tornando essa metodologia um padrão adotado
internacionalmente.
A primeira certificação OPSA é mais voltada para analistas de
segurança, administradores de rede com foco em segurança e CSO’s, que
precisam ter um conhecimento mais aprofundado que a média sobre uma
metodologia de testes de segurança, mas sem necessariamente precisar
realizar esses testes ou avaliações de forma mais especializada.
Já a OPST, tem um foco mais aprofundado, na realização de testes de
segurança, fazendo com que essa seja a escolha mais acertada para os
profissionais que atuem diretamente realizando essas avaliações e
investigações, tais como Pentesters e Investigadores Forense.
Agora, na área de segurança, apesar de ainda não ter o devido
reconhecimento do mercado aqui no Brasil, as certificações que realmente
atestam se o profissional está pronto para atuar na prática com testes
de invasão são: OSCP e OSCE. Sem desmerecer as demais certificações,
acredito que essas duas são as que mais se aproximam de um ambiente real
encontrado por um profissional ao realizar um testes de invasão.
O foco de ambas as certificações é comprovar na prática a aquisição
dos conhecimentos transmitidos ao estudante ao longo do período que o
mesmo tem acesso ao LAB, fornecido pela Offensive Security, organização
mantenedora do Backtrack (distribuição sobre a qual toda a certificação é
baseada).
A diferença entre ambas certificações, OSCP (Offensive Security
Certified Professional) e OSCE (Offensive Security Certified Expert),
está no treinamento que é realizado e na prova que culminam esses
treinamentos. Para a OSCP, o treinamento realizado é o PWB (Pentesting
with Backtrack) com duração de 30, 60 ou 90 dias de acesso – depende de
quanto o aluno quiser pagar pelo tempo de acesso ao LAB. A prova é
exclusivamente prática, onde o aluno tem 24h corridas para realizar a
entrada na rede cedida para avaliação pela Offensive Security e alcançar
os objetivos propostos, de acordo com os conteúdos estudados e
praticados no LAB.
E para alcançar a OSCE, o aluno precisa se inscrever no treinamento
CTP (Cracking the Perimeter), que funciona nos mesmos moldes do PWD, com
acesso ao LAB por um determinado número de dias, acesso à apostila e
vídeos com as técnicas explicadas detalhadamente, que culminarão numa
avaliação bem mais avançada que a primeira: 48h corridas para a
realização das práticas com um relatório final de tudo o que foi feito.
Nesse nível, o aluno não apenas empregará técnicas de exploração, mas
analisará vulnerabilidades, como elas poderão ser exploradas e precisará
desenvolver seus próprios exploits para explorar as vulnerabilidades
encontradas (um adendo: os exploits desenvolvidos precisam ser enviados
ao final da avaliação).
Portanto, deve estar claro para vocês porque essas certificações
ainda não possuem o devido reconhecimento no mercado de segurança, pois
para dominar o processo de testes de invasão e testes de segurança no
nível solicitado por essas certificações, o profissional precisa ter um
nível técnico bem alto.
A certificação que deixei para o final, não é a menos importante, mas
sim a mais trabalhosa de se conquistar, pois demanda um nível técnico
razoavelmente alto para o que a certificação se propõe.
Essa certificação é a NOP (Network Offensive Professional), criada
pela Immunity Sec., desenvolvedora do Immunity Canvas e Immunity
Debugger (importantes ferramentas para profissionais de segurança).
Em primeiro lugar, a prova é de graça, e não se paga nada para tirar a
certificação, a não ser a passagem de avião para os EUA. A partir daí,
na sede da Immunity, o postulando terá pouco mais de 30 minutos para
fazer o seguinte: receber dois PE’s (executáveis em Windows) com
vulnerabilidades, que deverão ser detectadas através do processo de
debugging e fuzzing, utilizando ferramentas da própria Immunity, como é o
caso de seu Debugger. Detectando as vulnerabilidades, é necessário –
dentro do prazo estipulado (lembre-se, pouco mais de 30 minutos no
total) -, desenvolver um exploit que faça a exploração dessa
vulnerabilidades e alcance um determinado resultado como definido pelos
aplicadores da prova.
Através dessa pequena análise de algumas das certificações
existentes, podemos perceber quantas possibilidade temos diante de nós. A
escolha de qual certificação é melhor, sempre vai depender da área onde
o profissional deseja atuar, bem como a empresa onde já trabalha ou
busca uma vaga.
Obviamente que a maioria dessas certificações é barata e pode ser
tirada facilmente. Algumas são mais fáceis, como citadas ao longo do
texto, mas outras demandam meses de preparação, mesmo que o profissional
já atue na área e tenha alguns anos de experiência. No entanto, mesmo
que o tempo e dinheiro empregados sejam em grande quantidade algumas
vezes, podem acreditar: vale muito à pena. Mas obviamente que vale mais
ainda à pena, quando o profissional além do papel timbrado, tenha a
prática e vivência necessárias para impor-se no mercado como
profissional respeitado e que realmente sabe o que está fazendo.
Espero que, de alguma forma, esse artigo possa ter tornado o caminho
de vocês em busca das certificações em segurança, ainda mais claro. *** Artigo de Luiz Vieira
|
O problema N+1
É mais fácil descrever o problema N+1 através de exemplo. Dê uma olhada no seguinte trecho de PHP em app hipotético de blog:
<?php
/**
* @var Solar_Sql_Adapter|Zend_Db_Adapter
* $sql An SQL database connection object.
*/
// 1 query to get 10 blog posts.
$stmt = 'SELECT * FROM posts LIMIT 10';
$posts = $sql->fetchAll($stmt);
// 10 queries (1 per blog post) to get
// the comments for each post
foreach ($posts as &$post) {
$stmt = 'SELECT *
FROM comments
WHERE post_id = :post_id';
$bind = array(
'post_id' => $post['id'],
);
$post['comments'] = $sql->fetchAll(
$stmt,
$bind
);
}
Temos um conjunto mestre de linhas (as postagens do blog), mas
precisamos ainda buscar muitas linhas de comentários para cada artigo do
blog. Para fazer isso, nós fizemos um loop pelo conjunto mestre de
linhas e lançamos uma query para cada um. Isso leva a várias linhas de
comentários para esse artigo do blog.
Esse é o problema N+1. Para construir uma lista de 10 registros,
emitimos 11 queries : uma para o conjunto mestre de 10 registros, em
seguida, mais 10 (N) queries para buscar os comentários. Se também
precisássemos obter várias tags para cada postagem, seriam mais 20, 10
queries para os comentários, e um adicional de 10 queries para as tags,
num total de 21 queries para a construção de 10 registros.
Isso pode rapidamente se tornar um problema de desempenho, mesmo para
pequenos conjuntos de dados com muitos relacionamentos. É especialmente
ruim quando você precisa buscar, por exemplo, cinco conjuntos
adicionais de dados relacionados para um conjunto mestre de 40 mil linhas. Haverá uma query para obter o conjunto mestre de 40 mil linhas, mais 5 queries por linha para os dados relacionados, para 200.001 queries no total.
A solução
Existem pelo menos duas maneiras de resolver o problema N+1 e reduzir o número de queries de forma dramática.
Uma maneira é escrever uma query que une os comentários para os posts
em um único conjunto de resultados maciços. Vamos ver uma ou outra
repetição dos posts do blog, de modo que seria necessário percorrer o
conjunto de resultados, escolher as mensagens distintas e reter os
vários comentários para cada um. Existem vários inconvenientes:
- É difícil fazer LIMIT/OFFSET no conjunto mestre de linhas que desejamos recuperar.
- Recebemos de volta um resultado de grandes dimensões a partir do
banco de dados com muita informação repetida. Para extrair os dados
relacionados, precisamos percorrer o conjunto de resultados no PHP e
descartar as partes repetidas das linhas, mantendo o controle de quais
foram repetidas e os que são novas.
- Se tivermos dois ou mais relacionamentos um-para-muitos, torna-se
difícil construir a query e, em seguida, escolher independentemente do
conjunto de resultados nos objetos de seu domínio. O problema de
repetição a partir do ponto 2 torna-se exponencialmente mais
problemático.
Em vez disso, sugiro uma maneira de resolver o problema N +1 que é
mais fácil de implementar e mais escalonável em vários relacionamentos
um-para-muitos. Após termos query para o mestre
conjunto de linhas, nós emitimos uma única query adicional para obter
todas as linhas relacionadas em uma tentativa, e depois uni-las para o
conjunto mestre em um loop PHP. O que segue abaixo é uma versão
reescrita do exemplo anterior, utilizando a técnica de query-and-stitch:
<?php
/**
* @var Solar_Sql_Adapter|Zend_Db_Adapter
* $sql An SQL database connection object.
*/
// 1 query to get 10 blog posts.
$stmt = 'SELECT * FROM posts LIMIT 10';
$rows = $sql->fetchAll($stmt);
// Find the ID of each post and key a
// $posts array on them.
$posts = array();
foreach ($rows as $post) {
$id = $post['id'];
$posts[$id] = $post;
}
// 1 additional query to get all
// comments for all the posts.
$stmt = 'SELECT *
FROM comments
WHERE post_id IN (:post_ids)';
$bind = array(
'post_ids' => array_keys($posts),
);
$rows = $sql->fetchAll($stmt, $bind);
// Stitch the comment rows into the posts.
// It is easy to find the right post for
// the comment, because we have keyed the
// posts on their ID.
foreach ($rows as $comment) {
$id = $comment['post_id'];
$posts[$id]['comments'][] = $comment;
}
Temos agora um loop adicional no código PHP em comparação com a
solução original. Em compensação, nós salvamos nove queries adicionais;
passamos de 11 (1 para as postagens e 10 para os comentários) para 2 (1
para os posts e 1 para os comentários).
Estendendo a solução
Nós podemos adicionar quantas linhas de muitos relacionamentos
quisermos usando a mesma técnica. Por exemplo, se nós também
precisássemos buscar várias tags em um relacionamento muitos-para-muitos
para cada post, desejaríamos fazer algo mais ou menos assim:
<?php
/**
* @var Solar_Sql_Adapter|Zend_Db_Adapter
* $sql An SQL database connection object.
*
* @var array $posts The master array of
* posts, keyed on their IDs.
*/
// 1 query to get all tags through the
// association mapping table.
$stmt = 'SELECT
posts_tags.post_id AS post_id,
tags.*
FROM tags
JOIN posts_tags
ON posts_tags.tag_id = tags.id
AND posts_tags.post_id IN (:post_ids)';
$bind = array(
'post_ids' => array_keys($posts),
);
$rows = $sql->fetchAll($stmt, $bind);
// Stitch the tags into the posts.
foreach ($rows as $tag) {
$id = $tag['post_id'];
$posts[$id]['tags'][] = $tag;
}
Na solução original, teríamos tido um único loop no código PHP, mas um total de 21 queries. Com query-and-stitch,
temos 3 loops, mas apenas 3 queries. O desempenho dos múltiplos loops
de PHP é praticamente garantido para ser melhor do que o desempenho de
21 queries.
Automatizando a solução
A técnica query-and-stitch é aplicável em qualquer contexto, seja uma
base de código nova ou uma herança, usando um framework ou não. No
entanto, em algum momento, vamos querer generalizar a técnica para que
possamos envolvê-la em uma classe para reutilização.
Na verdade, muitos ORMs fazem query-and-stitch nos bastidores quando você pede para incluir uma relação em um eager-fetch no conjunto mestre de linhas. Utilizar um ORM é uma forma de automatizar o problema N+1.
Apesar disso, muitos desenvolvedores de PHP não gostam de ORMs. Depois de ter desenvolvido um sistema ORM robusto com Jeff Moore,
estou totalmente familiarizado com as vantagens e desvantagens
envolvidas na utilização desse método. Eles podem ser opacos, ineficazes
ou imprevisíveis em casos extremos, e quase sempre exigem que você
aprenda uma maneira especial de construir suas solicitações de
recuperação. (Isso pode ser tanto por uma linguagem do tipo SQL ou por
um determinado conjunto de métodos e propriedades informacionais.) Mesmo
assim, você pode não estar totalmente isolado do problema N+1,
especialmente se os registros lazy-loads do ORM em um loop onde você não tenha feito um eager-fetch nos dados necessários.
Ao analizar o problema N+1 combinado com as vantagens e desvantagens
do uso de ORMs, ocorreu-me que o centro do problema N+1 não é o uso do
SQL. O problema é o empacotamento dos resultados em seus objetos de
modelo de domínio. Com isso em mente, eu reuni uma versão inicial de um
pacote data-marshaling chamado Aura.Marshal que utiliza a técnica stitch acima.
O pacote é muito limitado em seu escopo. Tudo o que ele faz é pegar conjuntos de resultados e reuni-los em objetos de modelo de domínio. É completamente independente de camada de acesso a banco de dados; você pode usar as funções PHP MySQL, PDO, Solar SQL, Zend DB,
ou qualquer outra coisa. Quando você define as relações de domínio em
um tipo de gerenciador e, em seguida, alimenta os tipos com os
resultados de queries próprias, Aura.Marshal vai ligar os objetos para você, utilizando a técnica stitch
descrito acima. Isso ajuda a fornecer uma forma automatizada de evitar
N+1, enquanto nos dá total controle sobre as queries sendo usados para
recuperar os dados que precisamos.
Conclusão
Espero que a técnica de query-and-stitch e ajude-o a resolver seus próprios problemas N+1.
***
Texto original disponível em http://phpadvent.org/2011/a-stitch-in-time-saves-nine-by-paul-jones
|
Neste artigo, abordarei o backup e a recuperação do MBR em Linux.
Este tipo de backup é especialmente útil a usuários que têm vários
sistemas operacionais instalados em um mesmo computador (multi-boot). A
recuperação do MBR a partir do backup pode também ser utilizada para
eliminar alguns tipos de vírus que afetam o MBR, como alguns bootkits,
ou, ainda, para recuperar o MBR caso ele venha a ser corrompido,
alterado ou mesmo perdido.
Em sistemas multi-boot, tendo o backup do MBR previamente feito e
atualizado, é possível instalar ou reinstalar o MS-Windows após os
outros sistemas operacionais, não sendo necessário instalá-lo primeiro
para evitar que ele sobrescreva o MBR, impedindo a inicialização do
computador a partir de outros sistemas operacionais.
1. O MBR
O MBR (Master Boot Record ou, em português, Registro Mestre de
Inicialização) corresponde aos 512 bytes armazenados no primeiro setor
do HD master do computador. Resumidamente falando, são os primeiros 512
bytes do HD master. O MBR armazena, estruturadamente, os seguintes
dados:
- Os primeiros 446 bytes armazenam o Setor de Boot;
- Os 64 bytes seguintes armazenam a Tabela de Partições do HD;
- Os 2 bytes finais são reservados para Assinatura.
Ao ligar o computador, o sistema realiza, nesta ordem, os seguintes passos:
- Executa um teste automático dos componentes eletrônicos da placa-mãe
do computador, este teste chama-se POST (Power On Self Test);
- Carrega dados do BIOS (Basic Input Output System) e faz a reprogramação do suporte de I/O;
- Lê o MBR e executa o carregador de boot (boot loader) registrado nos
primeiros 446 bytes do MBR; o carregador de boot inicializará o sistema
operacional adequado, ou o selecionado pelo usuário em computadores com
multi-boot.
2. Problemas mais frequentes relacionados ao MBR
Os problemas mais frequentes que afetam o MBR são:
- Infecção ou corrupção do MBR em virtude da ação de vírus fazendo,
muitas vezes, com que o seu HD pareça estar em branco (parecendo uma
perda total dos dados armazenados no HD) ou impedindo a inicialização do
sistema; há também um tipo especial de vírus, conhecidos como bootkits,
que ficam gravados no MBR e podem ser inicializados antes do sistema
operacional da máquina, permanecendo em execução após a inicialização do
sistema operacional, e sendo mais difíceis de detectar;
- Crashs do MBR que ocorrem, em muitos casos, devido a quedas de energia elétrica;
- Modificação do Setor de Boot do MBR quando da instalação do
MS-Windows em computadores com multi-boot, impedindo o boot a partir de
outros sistemas operacionais previamente instalados no mesmo computador.
3. Backup do MBR em Linux
O backup do MBR deve ser feito sempre em uma mídia externa. O mais
comum é fazê-lo em um pendrive. Nunca faça e/ou mantenha o backup do MBR
no próprio HD da máquina, pois, em caso de problemas com o MBR, o seu
backup não terá nenhuma utilidade!
Mantenha o seu backup do MBR atualizado. Sempre após reparticionar o
seu HD (ou excluir alguma partição existente), redimensionar partições
existentes, reformatar alguma partição com um tipo de sistema de
arquivos diferente do anterior ou, ainda, instalar ou reinstalar algum
sistema operacional ou carregador de boot, teste para verificar se tudo
está funcionando conforme o planejado e, em caso positivo, faça ou
atualize o backup do MBR do computador.
O backup do MBR pode ser feito a partir do Linux já instalado em seu HD ou a partir de um Live CD da distro Linux
de sua preferência. Neste último caso, não será necessário instalá-lo
no computador, bastando apenas inicializar o computador a partir do Live
CD.
Para fazer o backup do MBR em um pendrive, no Linux, siga os seguintes passos:
- Abra o Terminal;
- Logue-se como usuário root utilizando o comando su;
- Digite e execute um dos seguintes comandos, conforme o tipo do HD master de seu computador:
# dd if=/dev/sda of=/media/USB/MBR.bkp bs=512 count=1
# dd if=/dev/hda of=/media/USB/MBR.bkp bs=512 count=1
Pronto! O backup do MBR de seu computador já está salvo no pendrive.
Importante! Note que, em minha máquina, o backup do
MBR (arquivo MBR.bkp) foi salvo no pendrive montado no ponto de montagem
(diretório) /media/USB/. Verifique, em seu computador, a localização
correta do ponto de montagem (diretório) de seu pendrive.

Se você quiser verificar o tipo de arquivo gerado pelo processo de
backup do MBR, utilize o comando a seguir (não é necessário estar logado
como usuário root para executar este comando):
$ file /media/USB/MBR.bkp
Veja a saída do comando file sobre o arquivo de backup do MBR gerado
em minha máquina, na qual tenho dual-boot com os sistemas operacionais openSUSE Linux e MS-Windows Server 2003:

4. Recuperação do MBR com Linux em Live CD
Para recuperar o MBR de seu computador, após ocorrer algum problema
com o mesmo, será necessário inicializar a máquina a partir do Live CD
da distro Linux de sua preferência e ter em mãos a mídia externa, um
pendrive, no qual está salvo o backup mais atualizado do MBR.
Após inicializar a máquina a partir do Live CD do Linux, e ter
montado o pendrive contendo o backup do MBR, execute os seguintes
comandos para recuperar o MBR de seu computador:
- Abra o Terminal;
- Logue-se como usuário root utilizando o comando su;
- Digite e execute um dos seguintes comandos, conforme o tipo do HD master de seu computador:
# dd if=/media/USB/MBR.bkp of=/dev/sda
# dd if=/media/USB/MBR.bkp of=/dev/hda
Pronto! O MBR de seu computador já está recuperado. Agora,
reinicialize a máquina a partir do HD (não do Live CD do Linux) e
verifique se o boot, ou multi-boot, do sistema está funcionando
corretamente e se todas as partições do HD foram detectadas com sucesso.
Importante! Note que, em minha máquina, o backup do MBR (arquivo
MBR.bkp) foi salvo no pendrive montado no ponto de montagem (diretório)
/media/USB/. Verifique, em seu computador, a localização correta do
ponto de montagem (diretório) de seu pendrive, bem como o nome correto
do arquivo de backup do MBR salvo no pendrive.

5. Instalação do MS-Windows após o Linux em computadores com multi-boot
Quando o MS-Windows é instalado ou reinstalado após outros sistemas
operacionais em um computador com multi-boot, a instalação do MS-Windows
simplesmente sobrescreve o Setor de Boot do MBR, registrando o seu
próprio carregador de boot, impedindo que computador boot a partir dos
sistemas operacionais previamente instalados.
Para instalar ou reinstalar o MS-Windows após o ter Linux previamente
instalado em um mesmo computador e poder continuar utilizando o
multi-boot para escolher qual sistema operacional será utilizado, siga
os seguintes passos:
- Faça o backup do MBR;
- Instale ou reinstale o MS-Windows mesmo após ter o Linux instalado na máquina;
- Reinicialize o computador a partir do Live CD do Linux e recupere o
backup do MBR, executando no Terminal do Linux, como usuário root, um
dos comandos abaixo, conforme o tipo de HD master de sua máquina:
# dd if=/media/USB/MBR.bkp of=/dev/sda bs=446 count=1
# dd if=/media/USB/MBR.bkp of=/dev/hda bs=446 count=1
- Reinicialize normalmente o computador a partir do HD;
- Caso o carregador de boot (de multi-boot) anterior à instalação ou
reinstalação do MS-Windows não liste o MS-Windows, basta entrar no
Linux, que estava previamente instalado em sua máquina, e instale ou
atualize a configuração do carregador de boot (de multi-boot) do Linux,
geralmente o GRUB, para que o MS-Windows seja detectado e adicionado à
lista de opções de sistemas operacionais bootáveis do carregador de boot
(de multi-boot).
Pronto! Você já tem o MS-Windows instalado ou reinstalado e o computador em multi-boot.
Importante! Estes procedimentos são válidos se você
somente instalar ou reinstalar o MS-Windows, não são aplicáveis caso
altere o layout (esquema de particionamento) do HD da máquina. Note que,
em minha máquina, o backup do MBR (arquivo MBR.bkp) foi salvo no
pendrive montado no ponto de montagem (diretório) /media/USB/.
Verifique, em seu computador, a localização correta do ponto de montagem
(diretório) de seu pendrive, bem como o nome correto do arquivo de
backup do MBR salvo no pendrive. *** Artigo de Roberto Rodrigues Junior
|
O PHP 5.4 introduziu várias otimizações de desempenho. Uma
delas não foi muito discutida na comunidade PHP, mas pode afetar o
desempenho do seu código, dependendo da forma como você o escreve.
Leia este artigo para saber mais sobre essa otimização menos conhecida do
PHP 5.4 e o que você precisa fazer para fazer com que o seu código PHP
aproveite essa otimização para rodar mais rápido gastando menos memória.
O artigo também fala sobre uma especulação de que o PHP 6 e o
Zend Engine 3 podem, no futuro, usar tipos de variáveis declaradas
explicitamente e valores de retorno de função para gerar o código que
faz os aplicativos PHP rodarem muito mais rápido.
Os prós e os contras de uma linguagem de programação dinâmica
Como todos sabemos, o PHP é uma linguagem dinâmica. A maioria dos
desenvolvedores PHP aproveita essa característica, pois ela torna a
programação mais descontraída e flexível.
Na prática, isso significa que você não precisa declarar
antecipadamente os vários recursos que precisa usar, por exemplo, os
nomes e os tipos de variáveis, como você tem que fazer em linguagens
estáticas.
É claro que a programação dinâmica tem um preço. Se não souber
antecipadamente os tipos de variáveis, não é possível fazer todos os
tipos de otimizações que você poderia se os tipos de variáveis fossem
corrigidos e conhecidos.
Variáveis de classe dinâmicas
No PHP, as classes podem ter um número variável de variáveis. Apesar
de você poder declarar as variáveis que você sabe que serão necessárias,
você também pode atribuir valores dinamicamente às novas variáveis que
não foram previamente declaradas.
Isso significa que o mecanismo de execução do runtime do PHP precisa
levar em conta essa possibilidade para gerenciar o acesso aos valores de
variáveis de classe. Na prática, isso significa que, internamente, as
propriedades variáveis de classe precisam ser armazenadas numa estrutura
de dados dinâmica, que pode ser expandida conforme necessário.
A classe de otimização de acesso às variáveis do PHP 5.4
Rasmus Schulz (não é o criador do PHP, Rasmus Lerdorf) é um
desenvolvedor dinamarquês que não muito tempo atrás levantou a
preocupação de que o PHP poderia rodar mais rápido se ele fosse
executado sobre um mecanismo compilador JIT.
Mais recentemente, ele levantou outra preocupação
na lista interna de e-mails de discussão do PHP sobre a quantidade
excessiva de memória usada na criação de muitos objetos de uma mesma
classe. Sua alegação era que isso era devido ao fato de que para cada
objeto PHP foi criada uma estrutura de dados dinâmica (tabela hash) para
armazenar as propriedades de cada variável de classe.
Isso faz sentido se o PHP estiver esperando que a lista de variáveis
de classe mude durante o tempo de vida de cada objeto. Mas se a lista de
variáveis nunca, mudar será um desperdício de memória, pois diferentes
objetos de uma mesma classe terão a mesma lista de variáveis, portanto, a
classe poderia usar a mesma lista de propriedades, se ela tiver sido
armazenada em uma estrutura de dados mais eficiente compartilhada por
todos os objetos de uma mesma classe.
Foi quando o desenvolvedor Português Gustavo Lopes explicou
que a partir do PHP 5.4 as propriedades dinâmicas de tabelas hash serão
criadas somente se as variáveis forem adicionadas dinamicamente a
objetos em tempo de execução.
Além disso, Tom Boutell concluiu
na mesma thread de discussão que depois de executar uma atualização de
script de teste com base no previsto inicialmente por Rasmus Schulz,
usando apenas variáveis de classe pré-declaradas, o script não só usa
muito menos memória, mas também funciona 20% mais rápido.
Até agora, deveria estar fácil para você entender que deve evitar o
uso de variáveis de classe que não foram declaradas explicitamente na
declaração da classe. Isso significa que você deve declarar todas as
variáveis de classe, mesmo se não tiver definido um valor inicial.
Apesar de declarar explicitamente todas as variáveis de classe ser
uma prática comum, alguns desenvolvedores não o fazem para todas as
variáveis de classe que irão usar, especialmente se forem privados e não
precisarem ter um valor inicial.
Os ganhos dessa otimização são apenas perceptíveis se você precisar
criar muitos objetos da mesma classe em um script PHP. Se você criar
apenas alguns objetos de uma classe, você pode não notar muita
diferença.
Futuras otimizações de tipo de variável do PHP 6
Essa otimização do PHP 5.4 trabalha tornando mais eficiente a
pesquisa de variáveis de classe pelo nome em tempo de execução, porque,
quando uma classe é carregada, já sabemos quais são todas as suas
variáveis, assumindo que nenhuma variável dinâmica será adicionada mais
tarde.
Mais otimizações poderiam ser feitas se o mecanismo do PHP também
conhecesse o tipo de variáveis e valores de funções de retorno a fundo.
Isso é particularmente verdadeiro, não na versão atual do Zend Engine,
porque ela trabalha ao interpretar os opcodes compilados do Zend, mas
quando se usa um mecanismo compilador PHP JIT (Just In Time).
Pelo que sei, há pelo menos três compiladores JIT PHP: Facebook
HipHop PHP, Phalanger e Quercus, que usariam o mecanismos de compilação
do .NET e do Java JIT. Pode haver outros que eu não conheço, mas
suponho que todos eles giram em torno dos mesmos conceitos.
Os compiladores JIT estão pelo menos a uma geração à frente da Zend
Engine 2 usada na série PHP 5.x desde 2004. Os compiladores JIT podem
fazer o PHP rodar mais rápido gerando e executando o código de máquina
nativo otimizado para a CPU atual.
Atualmente, os mecanismos do compilador JIT tentam adivinhar a
variável e os tipos de valor de retorno de funções a partir do contexto
de código PHP para tornar o código de máquina gerado mais eficiente. Por
exemplo, considere o seguinte código:
$ length = strlen ($ string);
strlen é uma função que sempre retorna um inteiro. Portanto, o compilador JIT pode declarar uma variável tipo integer, pois é certo que será sempre um inteiro. Esse tipo de adivinhação de valor é chamado de inferência de tipos.
Quando o tipo de uma variável não pode ser adivinhado com certeza, os compiladores JIT usam variáveis de um tipo chamado variant.
O uso de variáveis variant é muito menos eficiente porque as
operações com essas variáveis podem exigir muitas conversões de tipo,
pois não podemos assumir que tipo é o valor atual armazenado naquela
variável. Isso significa que o código compilado JIT vai usar mais código
de máquina nativo, mais memória, mais ciclos de CPU, portanto, menos
desempenho.
Nos casos em que o compilador JIT não for capaz de adivinhar os tipos
de variáveis do contexto, seria útil se o programador dissesse
explicitamente qual é o tipo variável. Isso não só tornaria o código
gerado mais eficiente, mas tornaria eventualmente a compilação JIT mais
rápida, já que o compilador JIT não precisaria fazer suposições sobre o
tipo de variável.
Declarações variáveis de classes digitadas poderiam ter esta aparência:
public integer $ l = 0;
Tradicionalmente, os desenvolvedores do core PHP têm sido relutantes
em aceitar qualquer movimento no sentido de um tipo mais estrito de
variável da linguagem PHP.
Mas a ideia que eu estou propondo aqui não é tornar o PHP uma
linguagem fortemente tipada. A ideia é permitir que os desenvolvedores
de PHP opcionalmente declarem expressamente o tipo, pelo menos de
algumas variáveis, para que os compiladores JIT possam fazer um melhor
trabalho gerando código de máquina nativo mais eficiente em menos tempo.
A declaração de variável e tipos de valores para PHP5.x/Zend Engine 2
dificilmente pode ser útil devido à natureza dinâmica da Zend Engine 2.
No entanto, para um eventual PHP 6 com base no Zend Engine 3 com
suporte para compilação JIT, quaisquer dicas do tipo que o código PHP
pode passar para o mecanismo JIT ajudarão a tornar o código PHP
compilado muito mais eficiente.
Até onde eu sei, os planos para PHP 6 e Zend Engine 3 não são
públicos, se é que eles existem. Mas não é nem cedo nem tarde para
discutir o que eles serão. Eles podem muito bem resolver essa questão de
eficiência, tendo em vista os benefícios de os compiladores JIT.
Desconfio que a comunidade PHP vai falar sobre esses assuntos cada vez
mais, porque parece ser o próximo passo lógico. Vamos ver.
Conclusões
Para ser preciso, a otimização do PHP 5.4 não era segredo. O fato é
que ela não foi muito comentada entre os desenvolvedores externos do
core do PHP.
Quanto às especulações sobre PHP 6 e Zend Engine 3 mencionadas acima,
se elas já foram discutidas entre os desenvolvedores do core PHP,
pelo menos para mim elas são realmente confidenciais, então minhas
especulações são apenas palpites sobre o que eles podem vir a ser e, na
minha provavelmente nem tão humilde opinião, deveriam ser.
De qualquer forma, uma vez que a otimização foi introduzida no PHP
5.4, essa é mais uma razão que pode convencê-lo a atualizar, caso você
esteja se perguntando se realmente vale a pena. Em todo caso, você
sempre deve avaliar cuidadosamente os prós e os contras da atualização
para o PHP 5.4 antes de decidir fazê-la.
Então, o que você acha? Você está disposto a atualizar para os
benefícios e outras otimizações do PHP 5.4 ou ainda tem preocupações que
o impedem de atualizar?
E quanto às especulações sobre PHP 6 e Zend Engine 3? Você acha que o
tipo de declaração de variáveis e funções seria algo que você usaria
para tornar executar o PHP mais rápido?
***
Texto original disponível em http://www.phpclasses.org/blog/post/187-The-Secret-PHP-Optimization-of-version-54.html
|