 | Nível: Intermediário Teodor ZlatanovGold Software Systems
14/Jun/2009 Esta
série em cinco partes
percorre a construção de um Web site simples de compartilhamento de fotos usando Perl e Apache para acessar Simple Storage Service (S3) e SimpleDB da Amazon. Nesta parte, examine o código base integral do site
mod_perl , incluindo como configurar o nível superior, o que fazer com os manipuladores e como configurar dependências externas.
Nesta parte, prepare-se para testemunhar um site
mod_perl integral (somente código; os modelos estão na próxima parte).
Agora, nosso ritmo anteriormente relaxado (um passeio ou meio galope, se preferir) se tornará um galope completo à medida que cavalgamos com nosso cavalo
mod_perl pelas Planícies de Metáforas Filtradas.
 |
Para Obter o Máximo desta Série
Esta série requer conhecimento de nível principiante de HTTP e HTML, assim como conhecimento de nível intermediário de JavaScript e Perl (em um processo
mod_perl Apache). Algum conhecimento de bancos de dados relacionais, armazenamento em disco e redes será útil.
A série fica cada vez mais técnica, portanto, consulte a seção
Recursos se precisar de ajuda com qualquer um desses tópicos.
|
|
Incentivo muito a leitura do código de origem. O site é funcional, mas muitos detalhes não estão integralmente explicados nesta série, pois espero que você os entenda ou possa aprender o que não entendeu.
Sua livraria local ou remota e mecanismos de procura são seus amigos.
Especificamente, configurar um site mod_perl integral e usar o Template Toolkit são tópicos amplos que foram cobertos muitas vezes e, portanto, não são explicados aqui de forma alguma.
A melhor maneira de aprender é trabalhar cada questão e obstáculo até o site estar em execução.
Esta série apresenta o motor, as rodas, o chassi, etc.—fica por sua conta por gasolina e colocar o carro na estrada.
Como antes, uso share.lifelogs.com nesta série como o nome de domínio.
Lembre-se de alterá-lo conforme necessário para seu próprio ambiente.
Configuração de Nível Superior
É necessário ter um servidor Apache funcional com suporte a
mod_perl (para configurar um). Insira a seção a seguir em seu arquivo Apache httpd.conf, conforme mostrado na Lista 1:
Lista 1. Fornecendo suporte mod_perl para arquivo de configuração do Apache share.httpd.conf
<VirtualHost 1.2.3.4:80>
ServerName share.lifelogs.com
DocumentRoot /var/www/html
ErrorLog /var/log/apache/error-share.log
PerlRequire /home/tzz/mod_perl_require_share.pl
<Location />
SetHandler perl-script
PerlHandler SharePerlHandler
</Location>
SetEnv AWS_KEY 'my-AWS-key'
SetEnv AWS_SECRET_KEY 'my-secret-AWS-key'
</VirtualHost>
|
Tudo vive sob /home/tzz, como pode ver.
Coisas importantes aqui:
- Há um log de erros específico (de forma que é possível observar erros com este site em isolamento).
- As chaves de desenvolvedor da Amazon são passadas no ambiente de processo.
Dessa forma, o código de origem Perl não terá as mesmas, caso o código de origem vaze de alguma forma.
(A configuração do servidor da Web geralmente é mais segura do que o código de origem.)
Observe que tudo é tratado através do
SharePerlHandler, todo pedido em
share.lifelogs.com! Provavelmente, isso não é o desejado em um ambiente de produção.
A diretiva PerlRequire simplesmente configurou um ambiente, sem fazer nada de especial.
Novamente, tudo está sob
/home/tzz.
A Lista 2 mostra o arquivo Perl mod_perl_require_share.
Lista 2. O arquivo mod_perl_require_share.pl
#!/usr/bin/perl -w
use strict;
use lib '/home/tzz';
use SharePerlHandler;
1;
|
O Manipulador mod_perl
O manipulador mod_perl está inteiramente no arquivo
SharePerlHandler.pm. Possui diversas seções, de forma geral: configuração, manipulador principal, manipuladores de comentários e fotos, utilitários gerais e utilitários SimpleDB.
Os utilitários gerais e SimpleDB poderiam viver em seus próprios módulos, mas, por questão de simplicidade, deixei tudo em um local.
Os manipuladores de comentários e fotos e as funções de utilitário
SimpleDB são principalmente do script
simple_go.pl (consulte Downloads) com algumas pequenas mudanças.
Vamos iniciar com a configuração. À medida que percorro cada seção, explicarei minhas decisões; com muita frequência, "simplicidade" será a razão por eu ter feito as coisas de determinada maneira.
Criar um bom Web site é difícil, portanto, considere tudo que encontrar aqui como um modelo geral a ser moldado de acordo com suas necessidades e orçamento, em vez de ser um projeto final que pode ser colocado em produção.
O fato de funcionar pode, na verdade, ser uma distração, mas não resisti à tentação de torná-lo funcional.
Configurando Dependências Externas
A Lista 3 mostra a configuração geral para o arquivo SharePerlHandler.pm:
Lista 3. Configuração geral para SharePerlHandler.pm
package SharePerlHandler;
use Apache::Constants qw(:common REDIRECT);
use strict;
use Carp qw/verbose cluck carp croak confess/;
use Data::Dumper;
use Apache::Request;
use Template;
use POSIX;
use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
use MIME::Base64;
use Data::UUID; # generates unique IDs
use lib '/home/tzz/amazon-simpledb-2007-11-07-perl-library/src/';
use Amazon::SimpleDB::Client;
|
SharePerlHandler.pm depende de muito módulos. Primeiro, usa o módulo
strict , que é essencial para boa programação Perl.
Eu não colocaria algo em produção que não executasse sob
use
strict. Além disso:
- Os módulos
Carp fornecem melhores erros.
Data::Dumper é para depuração geral.
POSIX é para muitas funções que descobri que preciso frequentemente.
Digest::HMAC_SHA1 e
MIME::Base64 são para a política de upload do Amazon S3.
- O módulo
Template é o Template
Toolkit, que permitirá criar páginas HTML com algum conteúdo dinâmico rapidamente.
Data::UUID é para gerar IDs exclusivos.
Apache::Request e
Apache::Constants são para interação de
mod_perl com o servidor Apache.
- Por fim,
Amazon::SimpleDB::Client é da Amazon e permite interagir com SimpleDB.
Se não souber como instalar esses módulos a partir de CPAN, isso é feito com
cpan -e 'install MODULE' (se não souber disso, provavelmente, é possível que esteja bem confuso agora...)
.
Não usamos os módulos Net::Amazon::S3 apesar de podermos (na
Parte 2 eu disse que iríamos). Eles simplesmente não foram necessários devido a diversas decisões de arquitetura por questão de simplicidade; saiba mais sobre isso quando eu falar sobre uploads.
A Lista 4 mostra a configuração global para SharePerlHandler.pm.
Lista 4. A configuração global para SharePerlHandler.pm
use constant IMAGE_MODE => 0;
use constant COMMENT_MODE => 1;
use constant VERBOSE => 1; # can also be done through the environment or some other way
my $template = Template->new( {
INCLUDE_PATH => '/home/tzz/templates/share',
RECURSION => 1,
}
);
my $uuid = Data::UUID->new();
|
Constantes serão necessárias para representar o modo de imagem versus o modo de comentário para as operações SimpleDB básicas, portanto, defina-as aqui. A constante
VERBOSE pode ser substituída por qualquer outro método para controlar detalhamento em seu servidor.
Lembre-se, quanto mais dinâmico o controle sobre detalhamento, mais caro é (pois o servidor precisa verificar toda vez).
Em seguida, você obtém um objeto $templates
totalmente novo (que irá carregar modelos de
/home/tzz/templates/share e fará recursão).
Por fim, um gerado de UUID é obtido para ser usado em toda parte.
O Manipulador Principal
Tudo bem, este é principal, o local onde a magia acontece. PRESTE ATENÇÃO!
(Acordado? Bom!) Dê uma boa olhada na Lista 5.
Lista 5. Mais configuração global
sub handler
{
my $r = shift @_;
my $q = Apache::Request->new($r,
POST_MAX => 4096,
DISABLE_UPLOADS => 1);
my $user = (rand 2 > 1) ? 'bob' : 'ted';
# pick a user randomly between bob and ted
# (50% chance each)
handle_photo($q);
# always try to delete, add, or edit a URL
# if it's passed as a parameter
handle_comment($q);
# always try to delete, add, or edit a comment
# if it's passed as a parameter
my $uri = $q->uri();
my $tfile = $uri;
$tfile =~ s,^/,,; # remove the starting "/" in the name if it exists
$tfile =~ s,/$,,; # remove the ending "/" in the name if it exists
$tfile =~ s,/,_,g; # "/" in the file name becomes "_" so all the
# templates can be in one directory
$tfile = 'index' unless length $tfile;
# make the URI "index" if it's
# empty (e.g. someone hit the / URI)
if ($tfile =~ m/\.html$/)
{
$tfile =~ s/html$/tmpl/; # map ANYTHING.html to ANYTHING.tmpl
}
else
{
$tfile .= '.tmpl'; # map ANYTHING to ANYTHING.tmpl
}
my $policy = '';
my $signature = '';
if ($tfile eq 'upload.tmpl')
{
$template->process('policy.tmpl',
{
username => $user,
},
\$policy) || croak($template->error());
my $key = $ENV{AWS_SECRET_KEY};
$policy = encode_base64($policy);
$policy =~ s/\n//g;
$signature = encode_base64(hmac_sha1($policy, $key));
$signature =~ s/\n//g;
}
$q->send_http_header('text/html; charset=utf-8');
my $output = '';
$template->process($tfile,
{
request => $q,
username => $user,
policy => $policy,
signature => $signature,
env => \%ENV,
params => \%{$q->param()},
fimages => sub { return list_simpledb(sprintf('SELECT * from `%s`',
simpledb_image_domain_name())) },
fcomments => \&get_comments,
},
\$output) || croak($template->error());
print $output;
return OK;
}
|
Nossa, é uma função longa. É quase longa demais; provavelmente, eu extrairia as partes que podem ser independentes ("refatore-a", como os jovens legais falam hoje em dia) se precisasse incluir até mesmo um pouco mais de lógica.
Funciona bem para mostrar como pode ser a aparência do manipulador principal, no entanto.
Primeiro a função obtém o objeto do pedido. Configura então um nome de usuário aleatório ("bob" ou "ted"); geralmente, você teria seu próprio modo de obter isso, possivelmente através de cookies ou pode permitir que o Apache trate da autenticação e autorização.
Eu disse na Parte 1 que haveria uma tabela de usuários em SimpleDB, mas isso complicou muito o site, então, a eliminei.
Consultar usuários em
SimpleDB não é simples, pois era necessário fornecer uma maneira para inscrever e gerenciar informações sobre usuários.
Tornou o código muito grande, portanto, perdoe essa omissão
—é definitivamente possível manter a tabela de usuários em
SimpleDB.
Tudo bem, em seguida, você irá querer tratar de parâmetros de fotos ou de comentários. Por exemplo, caso veja o parâmetro
deletecommentid
, você tenta excluir esse ID de comentário. Vamos detalhar os manipuladores de parâmetros de fotos e comentários posteriormente.
Em seguida, é necessário gerenciar o pedido em si. Isso é feito com um mapeamento simples que transforma "any/request/here.html" em
"any_request_here.tmpl" e solicita então esse modelo. Asseguramos que
index.tmpl seja fornecido para o pedido "/".
Quaisquer URIs que não tenham um modelo correspondente não produzirá nenhum dado e, na verdade, emitirá um erro.
Essa não é uma técnica de produção , vamos deixar claro, mas configura um Web site em poucas linhas, portanto, é bastante útil quando o objetivo é brevidade e simplicidade em um demo.
Em seguida, se o arquivo de modelo for "upload.tmpl", você sabe que precisará gerar uma política de upload para S3 e, portanto, faz isso usando o arquivo
policy.tmpl. O nome de usuário é passado para esse modelo, que é muito semelhante àquele na
Parte 2 desta série.
A Lista 6 mostra um modelo de política.
Lista 6. Lista de código de amostra em largura máxima
{"expiration": "3000-01-01T00:00:00Z",
"conditions": [
{"bucket": "images.share.lifelogs.com"},
{"acl": "public-read"},
["starts-with", "$key", ""],
["starts-with", "$Content-Type", ""],
["starts-with", "$success_action_redirect",
"http://share.lifelogs.com/s3uploaded?user=[% username %]"],
["content-length-range", 0, 1048576]
]
}
|
A principal diferença aqui é que em vez de tornar o nome do usuário parte da URL de sucesso, ele é transformado em um parâmetro, pois torna o manipulador de parâmetro de imagem muito mais simples.
Mais sobre isso adiante.
Agora, você assina a política e segue para enviar os cabeçalhos HTTP (bom trabalho aí, Apache!). Em seguida, gere a saída necessária com muitos parâmetros, da seguinte forma:
request, o pedido Apache
username, o nome de usuário aleatório
policy, a política de upload do S3 (poderia estar em branco).
signature, a assinatura da política do S3 (poderia estar em branco)
env, o ambiente de processo (não faça isso na produção!)
params, os parâmetros, por exemplo, a partir de um pedido
POST ouGET
fimages, uma função para retornar todas as imagens
fcomments, uma função para retornar todos os comentários, apontados por ID de imagem
Isso é tudo para o manipulador geral. Toda a magia restante ocorre nos manipuladores de parâmetros de comentários e imagens e nos próprios modelos.
Vamos continuar nossa jornada descendente.
Os manipuladores de imagens e comentários são chamados para cada pedido. Se localizarem parâmetros que parecem aplicáveis, executarão uma operação: incluir, modificar ou excluir uma imagem ou um comentário.
Os modelos, que vamos estudar após
SharePerlHandler.pm, contêm estes parâmetros em formulários
POST .
Não pule adiante, há muito aqui para mantê-lo entretido
—código de má qualidade, arquitetura instável e a esperança de você encontrar um erro que valha a pena postar no Twitter ("haha o @tzlatanov é mto ruim o pior olha esse mapa usado em contexto vazio e ai meu Deus modelos kebrados é claro que ele não é um h4ck3r de vdd mod_perl é tão ultrapassado.").
O Manipulador de Parâmetro de Comentário
A Lista 7 mostra o manipulador de parâmetro de comentário.
Lista 7. O manipulador de parâmetro de comentário
sub handle_comment
{
my $q = shift @_;
my $user = $q->param('user');
my $imageid = $q->param('refimageid');
my $comment = $q->param('comment');
my $refcommentid = $q->param('refcommentid');
my $commentid = $q->param('commentid');
my $deleteid = $q->param('deletecommentid');
my $result;
if (defined $deleteid) # delete
{
$result = delete_simpledb($deleteid, COMMENT_MODE);
}
elsif (defined $commentid && defined $comment) # edit
{
my %q = (
comment => $comment,
);
put_simpledb($commentid, COMMENT_MODE, %q);
$result = get_simpledb($commentid, COMMENT_MODE);
}
elsif (defined $imageid && defined $comment) # new comment
{
my %q = (
image_id => $imageid,
comment => $comment,
);
$q{reply_to} = $refcommentid if defined $refcommentid;
$q{user} = $user if defined $user;
my $id = new_uuid();
put_simpledb($id, COMMENT_MODE, %q);
$result = get_simpledb($id, COMMENT_MODE);
}
$q->param()->{'result'} = $result;
}
|
O manipulador de parâmetro de comentário possui três modos possíveis, dependendo dos parâmetros passados a ele.
Os modos são mutuamente exclusivos. Em cada caso, o parâmetro de consulta
result é configurado de forma apropriada para indicar o êxito se estiver definido.
Assim, os modelos podem verificar posteriormente se está configurado e agir conforme necessário.
À medida que o site cresce, você provavelmente irá querer incluir outros parâmetros, como
last_operation ou
error_message.
Se o parâmetro deletecommentid estiver configurado, o manipulador chama
delete_simpledb com os valores apropriados.
Esse é o modo mais simples incondicional.
O próximo modo modifica um comentário. Não verifica se o comentário existe no momento, portanto, um ID incorreto aqui criaria um novo comentário.
Verificar é fácil, mas caro (é necessário fazer uma chamada extra a
SimpleDB, o que é lento, já que é uma roundtrip HTTP completa mais o tempo de processamento do lado da Amazon).
Observe que, como cada comentário possui seu próprio ID, editar é fácil. Sem registros de comentários individuais, você poderia ter agrupado comentários como um atributo de imagem (uma array de cadeias de caracteres, cada uma um comentário), mas teria sido então muito mais difícil editar ou excluir um comentário individual.
Essencialmente, teria sido necessário implementar sua própria estrutura re registro em um comentário para representar um ID, um usuário de postagem, etc.
O modo de edição é acionado pela presença dos parâmetros de consulta
commentid e
comment , que determinam o UUID de destino de edição e o novo conteúdo do comentário, respectivamente. O resultado é a recuperação do mesmo UUID novamente de SimpleDB, portanto, você poderia verificar aqui se o campo de comentário resultante é o desejado (caso contrário, algo saiu errado).
Não verifico tudo isso aqui por questão de simplicidade.
O modo final, criando um novo comentário, é acionado pelos parâmetros
imageid e comment
. Como opção, aceitará um UUID de referência (quando o comentário é uma resposta a outro) e um nome de usuário (quando o comentário não for anônimo).
Exatamente como o modo de edição, você simplesmente efetua
put_simpledb dos atributos e obtém então os mesmos de volta sem verificar se os campos foram modificados corretamente.
O Manipulador de Parâmetro de Imagem
Esse manipulador é muito semelhante ao manipulador de comentário, portanto, se tiver dormido na seção anterior, volte e preste atenção.
A URL da imagem, se não for passada, é construída a partir da chave e do depósito do S3.
Dessa forma, há uma interface consistente para manipular redirecionamentos com êxito após uploads do S3.
A Lista 8 mostra o manipulador de parâmetro de imagem.
Lista 8. O manipulador de parâmetro de imagem
sub handle_photo
{
my $q = shift @_;
my $user = $q->param('user');
my $name = $q->param('name');
my $bucket = $q->param('bucket');
my $key = $q->param('key');
my $url = $q->param('url');
my $editid = $q->param('imageid');
my $deleteid = $q->param('deleteimageid');
# set the URL from the S3 key and bucket if necessary
if (!defined $url && defined $key && defined $bucket)
{
$url = sprintf("http://%s.s3.amazonaws.com/%s", $bucket, $key)
}
my $result;
if (defined $deleteid) # delete
{
$result = delete_simpledb($deleteid, IMAGE_MODE);
}
elsif (defined $name && defined $editid) # editing an image name
{
my %q = (
name => $name,
);
put_simpledb($editid, IMAGE_MODE, %q);
$result = get_simpledb($editid, IMAGE_MODE);
}
elsif (defined $url && defined $name && defined $user) # adding a new one
{
my %q = (
url => $url,
name => $name,
user => $user,
);
$q{bucket} = $bucket if defined $bucket;
my $id = new_uuid();
put_simpledb($id, IMAGE_MODE, %q);
$result = get_simpledb($id, IMAGE_MODE);
}
$q->param()->{'result'} = $result;
}
|
A exclusão da imagem é acionada pelo parâmetro
deleteimageid . A edição do nome de uma imagem é feita com os parâmetros
name e
imageid . A criação de uma nova imagem é realizada com uma URL, um nome de usuário e um nome de imagem.
O depósito de imagens é opcional e deve aparecer somente se esse manipulador for chamado após um upload bem-sucedido do S3 ser redirecionado para nosso site.
Lembre-se da política, o redirecionamento bem-sucedido do S3 possui o nome de usuário como parte da URL como um parâmetro.
Também terá a chave e o depósito, de forma que tudo que se precisa fazer é criar uma imagem a partir deles.
Funções de Utilitário
Vamos dar uma olhada nas funções realmente diversas.
Lista 9. Funções realmente diversas
sub qlog
{
printf STDERR @_;
print STDERR "\n";
}
sub new_uuid
{
return $uuid->to_string($uuid->create());
}
sub simpledb_image_domain_name
{
return simpledb_domain_name(IMAGE_MODE);
}
sub simpledb_comment_domain_name
{
return simpledb_domain_name(COMMENT_MODE);
}
sub simpledb_domain_name
{
return sprintf "%s.share.lifelogs.com",
(shift == IMAGE_MODE) ? 'share_photos' : 'share_comments';
}
|
qlog é interessante quando você não quer gravar
printf STDERR toda vez. Também grava um término de linha.
Se saída variada tem que ir para o log de erros do Apache é você quem decide.
Além disso:
new_uuid é para gerar um novo UUID.
simpledb_domain_name,
simpledb_image_domain_name e
simpledb_comment_domain_name usam o parâmetro mode (que pode ser
IMAGE_MODE ou
COMMENT_MODE) para fornecer um domínio SimpleDB.
Funções de Utilitário SimpleDB
As funções de utilitário SimpleDB são praticamente iguais àquelas na Parte 3
(simple_go.pl). Faça download das mesmas a partir da seção Downloads
abaixo. Vou listar as mudanças:
get_comments é uma nova função para obter todos os comentários, chaveados pelo ID da imagem e, então, pelo ID do comentário pai ou pela palavra noparent.
qlog é usada em vez de
print e a constante
VERBOSE é usada em vez de
$verbose.
- O serviço é inicializado para cada pedido usando as chaves de ambiente
AWS_KEY e
AWS_SECRET_KEY .
- O modo, como
$mode, é passado em vez de ser global.
- Nos erros, em vez de usar
die(), deve tratá-los da melhor maneira possível.
- O nome de domínio é obtido com
simpledb_domain_name em vez de uma variável global.
- As funções forem renomeadas, pois "get" e "put" não são bons nomes em uma espaço de nomes que não atende a um único propósito, como o antigo script
simple_go.pl fez.
Devo mencionar novamente que esse código aceitará somente valores únicos por atributo.
Se qualquer atributo tiver uma array de cadeias de caracteres, somente uma delas será retornada.
Quando atributos são gravados, somente um valor permanecerá mesmo se houver uma array de valores antes.
O código é significativamente mais simples por causa disso, mas também não é adequado para o uso geral de SimpleDB.
Conclusão
Agora, você realizou um tour do código de um site
mod_perl integral, usando o que gravamos nas Partes 2 e 3 desta
série (os arquivos para download dessas partes estão disponíveis abaixo também).
O site resultante usa o Template Toolkit, S3 e
SimpleDB para fornecer uploads de imagens, navegação (com thread), edição e inclusão de comentário (anônimo ou não) e exclusão.
Na Parte 5, você ficará familiarizado com a versão de modelo do site.
Downloads | Descrição | Nome | Tamanho | Método de download |
|---|
| SimpleDB utility functions | simpledb_utility.zip | 3KB | HTTP |
|---|
| Sample script (from Part 2) | s3form.zip | 2KB | HTTP |
|---|
| Sample script (from Part 3) | simple_go.zip | 4KB | HTTP |
|---|
Recursos Aprender
- Inicie com
"Perl Elaborado: Perl e a Nuvem Amazon, Parte 1"
(developerWorks, março de 2009) para entender os benefícios e desvantagens de usar S3 e SimpleDB da Amazon para construção de Web site. Continue então com a
Parte 2 (abril de 2009) para fazer upload de um arquivo para o S3 a partir de uma página da Web através de um formulário HTML para minimizar a carga no servidor e com a
Parte 3 (junho de 2009) para fazer upload de imagens através de URLs em uma tabela e gerenciar imagens e comentários.
- Detalhes da oferta de serviço e recursos para desenvolvedores estão em Amazon.com:
- Aprenda sobre o incrível
JavaScript MimeType, uma propriedade do objeto navegador, um objeto de nível superior que é a representação de objeto do navegador da Internet do cliente ou do programa navegador da Web que está sendo usado.
-
mod_perl reúne todo o poder de Perl e do Apache HTTP Server.
-
Prototype é uma estrutura JavaScript que facilita o desenvolvimento de aplicativos da Web dinâmicos através de um kit de ferramentas para desenvolvimento orientado por classes e a biblioteca Ajax "mais legal" do mundo.
E há um excelente artigo sobre como usá-lo:
"Developer Notes for prototype.js" de Sergio Pereira.
- Sim, Virgínia, é um serviço baseado na Web e, portanto, pode sofrer
interrupções; uma consideração importante.
-
Na
zona do Linux do developerWorks, encontre mais recursos para desenvolvedores do Linux e verifique nossos
artigos e tutoriais mais populares
.
-
Consulte todas as
dicas do Linux e
tutoriais do Linux no developerWorks.
-
Permaneça atualizado com os
eventos técnicos e Webcasts do developerWorks.
Obter produtos e tecnologias
- Visite CPAN para downloads, listas de módulos e documentação sobre o
Template-Toolkit-2.20, um kit de construção rápida de modelo.
O'Reilly lançou um livro,
Perl Template Toolkit
, escrito pelos principais membros da equipe de desenvolvimento ta tecnologia.
- No site
CPAN (Comprehensive Perl Archive Network)
, é possível encontrar uma quantidade enorme de módulos. E documentação de módulos.
-
S3Fox, o Organizador FireFox do Amazon S3
,o complemento de gerenciamento do S3 para Firefox, coloca um front end de fácil utilização no S3.
-
Com o
software de avaliação da IBM, disponível para download diretamente a partir do developerWorks, construa seu próximo projeto de desenvolvimento no Linux.
Discutir
-
Envolva-se com a
comunidade My developerWorks; com seu perfil pessoal e página inicial customizada, é possível padronizar o developerWorks para seus interesses e interagir com outros usuários do developerWorks.
Sobre o autor  | |  | Teodor Zlatanov surgiu com um Mestrado em Ciências em engenharia da computação da Boston University em 1999. Trabalha como programador desde 1992, usando Perl, Java, C e C++. Seus interesses estão em trabalho em análise de textos de software livre, arquiteturas de banco de dados, interfaces com o usuário e administração do sistema UNIX. |
Avalie esta página
|  |