Olá, pessoal! No artigo de hoje, vou mostrar como criar o relacionamento oneToMany/ ManyToOne de uma forma bem simples. Afinal, quem nunca passou por algum tipo de problema ao criar esse tipo de relacionamento? Algo como de não criar a FK e só persistir uma das tabelas etc. Vou focar em como definir os relacionamentos no nível do código e, para isso, teremos code apenas para o objetivo do artigo. A minha intenção é evitar que os artigos fiquem grandes e cansativos.
RequiredVou presumir que, se você está lendo este artigo, é porque já trabalha com o Hibernate e agora precisa fazer um relacionamento entre as suas tabelas. Então, parte da configuração do framework, ou explicação dos métodos serão omitidos - qualquer dúvida consulte artigos anteriores que publiquei no iMasters e veja como ter o ambiente funcionando. A classe DAO nos códigos é quem possui o trabalho de persistência, mas ela não é requerida para o que vamos fazer neste artigo, pois você pode obter o begin(), save(), commit() etc do Hibernate por diversas formas. É preciso ter o Hibernate 3.x e o MySql 5. OneToManyO relacionamento OneToMany é bem usado e são poucas as vezes que de fato não precisamos tê-lo. Acredite, se não precisou até hoje, espere mais um pouco que essa necessidade vai aparecer. Vamos tirar a vantagem dos Annotations e veremos @OneToMany e @ManyToOne, ao invés dos .hbm. Como exemplo, existem vários cenários para exemplificar esse tipo de relacionamento, tais como: um time de futebol tem vários jogadores e uma infraestrutura tem vários servidores; porém, um jogador só pode jogar em um time (ou não. Depende da regra de negócio, e esse é segredo!), e um servidor está em uma infraestrutura. Note: Há casos que um jogador joga em mais de um time, então temos o ManyToMany. Para criar esse tipo de relacionamento, temos que identificar o ponto chave do relacionamento entre as classes. Para um time de futebol, por exemplo, temos que saber que há uma lista dos jogadores que pertencem ao clube, uma vez que um time pode ter de 0 a X jogadores (mesmo sem jogadores ele pode ser considerado um time de futebol, mas está sem dinheiro e demitiu todos os jogadores). Eu costumo chamar de HAS-AN List something (tem uma lista de alguma coisa). A seguir, temos a class bean que representa o Team (por boas práticas, ela não deveria fazer o extends DAO, porém fiz aqui para facilitar e trazer sentindo às invocações do Hibernate que temos no code). @Entity
public class Team extends DAO{
@Id
@GeneratedValue
private long id;
@Column
private String nameTeam;
private List<Player> players;
Usando @OneToManyAgora vamos usar o relacionamento apropriado para a classe. A seguir, temos o code atualizado: @Entity
public class Team {
private String nameTeam;
@OneToMany(mappedBy = "team", targetEntity = Player.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Player> players;
- MappedBy: informamos o nome da variável de instância que vai indicar a quem aquele One pertence, ou seja, um jogador; e ele deve dizer a qual time este está associado;
- TargetEntity: informa qual a entidade estamos associando;
- FetchType.Lazy: foi escolhido por performace;
- cascade: ALL para permitir alterações em todos os relacionamentos.
Pronto, agora já podemos dizer que o TEAM tem muitos jogadores (uma lista ). Usando @ManyToOneNa classe que representa o MANY (do manyToOne), que nesse caso é a Player, teremos uma anotação @ManyToOne na variável de instância que representa o TEAM. @Entity
public class Player {
@Id
@GeneratedValue
private long id;
private String nickName;
@ManyToOne
@JoinColumn(name="team_id")
private Team team;
@JoinColumn: informamos o nome que terá o FK. Ao rodar o código main na class Team: public static void main(String args[]) {
Team team1 = new Team();
team1.setNameTeam("São Paulo");
Player jogador1 = new Player();
Player jogador2 = new Player();
jogador1.setNickName("Rogerio Ceni");
jogador2.setNickName("Luiz Fabiano");
jogador1.setTeam(team1);
jogador2.setTeam(team1);
begin();
getSession().save(team1);
getSession().save(player1);
getSession().save(player2);
commit();
}
Talvez você tenha pensado que apenas um save() seria necessário, mas não é; pois precisamos colocar a instância dos players com a session, para que este se torne um objeto persistente. Do contrário, o Hibernate não tem o poder de persistir no banco. O resultado: 

O team do São Paulo tem dois jogadores. Observe que o ID do team aparece na table do Player(team_id). Assim, sabemos a qual time este pertence. Erros comuns durante a programação:- Esquecer de associar as instâncias envolvidas no relacionamento. Se eu esquecer de dizer a qual team um jogador pertence, não teremos o resultado esperado, e o resultado na sua tabela será NULL, caso seja permitido esse valor na coluna;
- Não salvar as instâncias que serão persistidas é outro erro comum. Quem está fazendo pela primeira vez acredita que dar um save apenas na classe que representa o One (team) é o suficiente e por alguma mágica o Hibernate vai saber quais as outras instâncias devem ser persistidas. Aí vem a pergunta: como o Hibernate vai saber se você não transformou o “objeto java”, criando em um objeto-persistent?
Espero que tenham gostado do artigo. Até a próxima!
|
Hoje em dia torna-se difícil conseguir acompanhar todas as evoluções tecnológicas. Mesmo reduzindo o espaço de procura a apenas temas relacionados com a nossa área - suponhamos Java e ciência da computação - as novas frameworks, ferramentas, papers e notícias obrigam a atenção contínua. Eu pessoalmente tenho cada vez mais dificuldade em reservar tempo para ler as feeds RSS ou tentar ler o que as várias pessoas que sigo partilham no Twitter.No entanto, também são necessários os conceitos base. Fora o ensino superior e certificações, livros são um recurso essencial que me parecem que, hoje em dia, muita gente despreza. E estou falando daqueles em papel, não dos pdfs que se baixam da net. Foi com esta ideia que decidi juntar uma lista de 10 livros que considero essenciais para um programador Java - i.e. que contêm a matéria mínima que gostava de ver nos membros das minhas equipes de desenvolvimento. Alguns destes podem ser substituídos por outros, pois trata-se de escolhas pessoais, mas os temas e áreas abrangidos penso serem extensivos. Lembro que é uma lista de livros técnicos, não se focando no desenvolvimento das chamadas "soft skills". Fica a lista: Escrito pelos criadores da linguagem, serve tanto como livro de introdução a Java como também de excelente referência para manter por perto. Cobre desde as áreas básicas da linguagem até I/O, threading e acima de tudo as collections, para as quais é muito útil como referência. Escrito pelo Joshua Bloch, Effective Java é provavelmente o melhor livro sobre Java que já li. Está organizado em 78 itens e cada um é uma boa prática, por exemplo, "Preferir composição no lugar de herança", "Evitar Finalizers" ou "Preferir anotações a padrões de nomenclaturas". Em cada um destes pontos, o autor discute os diversos ângulos da questão aprofundadamente e com justificações que demonstram um conhecimento extremo da plataforma. Além disso, o estilo de escrita é facílimo de ler. Eu demorei duas noites a ler o livro todo. "Concorrência é difícil", é uma das mensagens principais deste livro. O autor do livro, Brian Goetz, parte deste princípio para demonstrar como evitar as principais falhas quando se desenvolve software concorrente em Java. Os bons e maus exemplos são demonstrados facilmente com snipplets de código com smileys negativos e positivos, o que ajuda a memorizar os padrões. Além de explicar os principais problemas de concorrência - live locks, dead locks, race conditions etc. - são explicadas detalhadamente as novas estruturas de dados para suporte à concorrência introduzidas no Java 5 e 6. Depois de ler este livro estou usando estas estruturas mais e mais vezes, e também construindo em cima delas conforme vou compreendendo como funcionam internamente. Sim, coloquei aqui um livro de matemática! Todos estudamos matemática, mas por vezes a dificuldade reside em encontrar aplicações para o que aprendemos. Este livro ensina conceitos matemáticos que são facilmente mapeados para problemas informáticos com os quais nos encontramos no dia-a-dia. Também são conceitos que nos ajudam a perceber melhor os diferentes algoritmos. Este não foi o primeiro livro de algoritmos que comprei nem é considerado o "standard". O primeiro que comprei - e que, sinceramente, nunca consegui ler todo - foi o Introduction to Algorithms. Além de grosso, tem uma abordagem extremamente acadêmica e formal. Por outro lado, este, The Algorithm Design Manual, é bastante acessível e completo. Os exemplos não estão escritos em Java mas vale pela quantidade e pela forma como são explanados os algoritmos. Cobre a maioria das áreas esperadas num livro para iniciantes/intermediários: estruturas de dados, algoritmos de pesquisa, grafos, programação dinâmica, combinatória, geometria, conjuntos e outras áreas. Decidi incluir um outro livro de algoritmos, desta vez em Java. Escrito pelo Robert Sedgewick, que já tinha escrito a mesma versão do livro para C++ no início dos anos 90, o livro serve de excelente fonte de referência para se ter no local de trabalho e consultar rapidamente quando necessário. Está dividido em cinco partes, separadas ao longo de dois volumes - Fundamentos, Estruturas de Dados, Ordenação e Pesquisa, no primeiro volume; e Grafos, no segundo volume. Conhecimento sobre design patterns - especificamente GoF neste caso, mas também hoje em dia padrões de arquitetura ou mesmo os Core J2EE patterns da Sun - é essencial para o profissional que trabalhe em linguagens orientadas a objetos. Isto pode ser provado tipicamente na entrevista de emprego, já que no mínimo uma perguntinha de padrões é sempre feita (dica: se te perguntarem para dizerem um padrão de desenho que conheçam, NÃO respondam Singleton!). Tal como o já citado Effective Java está para o Java, este livros está para a profissão de desenvolvimento de software. Os autores tentam cobrir as áreas que apenas se aprendem com a experiência profissional como um conjunto de boas práticas a seguir. Tanto para profissionais com pouca experiência - que vão aprender algumas boas dicas - como para profissionais com extensiva experiência - que vão rever no livro muita coisa pela qual passaram, mas agora organizada e esquematizada -, este livro prova-se uma leitura útil e bastante agradável. Refactoring, refactoring, refactoring! Atualmente, a grande maioria dos profissionais sabe o que é refactoring, mesmo que não o pratiquem tanto assim. Mas é extremamente estranho como um conceito tão simples não tinha sido esquematizado corretamente antes deste livro. Pode-se pensar que não é necessário ler um livro sobre refactoring, pois na prática temos IDEs que nos ajudam a fazer grande parte do trabalho. Mas quando se olha para o projeto numa perspectiva macro, o refactoring não é assim tão simples. Este livro ajuda a reprogramar a nossa cabeça para estar constantemente em modo refactoring. Embora o título o possa fazer entender, este livro não é exclusivamente sobre metodologias ágeis. A verdade é que conjuga a enumeração de múltiplas metodologias ágeis com princípios de desenvolvimento de software como orientação a objectos e UML. Ao contrário de outros livros sobre metodologias ágeis, o autor - que é um dos signatários iniciais do Agile Manifesto - não tenta puxar por nenhuma metodologia, embora fale mais de eXtreme Programming - TDD, refactoring, pair programming. É esta perspectiva integrada de agile + tecnologia que torna este livro num recurso essencial. 11 - Bônus - livro de Python/Ruby/Haskell/Scala/Groovy/Clojure ou outra linguagemEsta lista é focada em Java e, exatamente por causa disso, aconselho a se aprender pelo menos uma outra linguagem, esteja esta disponível para a JVM ou não. Aprender linguagens novas faz que sejamos melhores programadores. Especialmente agora com o renascimento de linguagens funcionais, também pode vir a ser uma vantagem profissional. Certamente esqueci-me de outros livros importantes, mas estes são aqueles que considero poderem contribuir muito para a qualidade que um profissional pode vir a atingir. Aceito recomendações para outros livros! artigo publicado originalmente no iMasters, por Ruben Badaró
|
Irei iniciar uma série de artigo para ensinar como construir um site usando Web Forms com a nova versão ASP .NET 4.5 e o Microsoft Visual Studio Express 2012 for web usando a linguagem VB .NET. Estou me baseando integralmente na série de artigos disponíveis no site e irei reproduzir a versão para VB .NET deste link com algumas modificações que serão feitas à medida que formos construirmos site. Para acompanhar os tutoriais você deverá possuir instaladas as seguintes ferramentas: Você pode baixar a aplicação completa que iremos desenvolver aqui neste link. Obs: A nossa aplicação será um pouco diferente e estará traduzida para o idioma Português usando a linguagem VB .NET. Dessa forma, esta série de artigos é um bom ponto de partida para você que está começando a estudar ASP .NET e quer rapidamente criar seu próprio web site. Nesta primeira parte você irá criar, revisar e executar o projeto padrão no Visual Studio Express 2012 for Web, que permite a você se familiarizar com os recursos do ASP.NET. Além disso, você irá se familiarizar com o ambiente do Visual Studio Express 2012 for Web.
O que você vai aprender: - Como criar um novo projeto Web Forms.
- A estrutura de arquivos do projeto Web Forms.
- Como executar o projeto no Visual Studio Express 2012 for Web.
- As diferentes características de aplicativo padrão Web Forms.
- Algumas noções básicas sobre como usar o ambiente Visual Studio Express 2012 for Web
Integralmente baseado no artigo original (com algumas alterações e portado para a linguagem VB .NET). Criando um novo projeto (ASP .NET 4.5)Abrindo o Visual Studio Express 2012 for Web, você já verá o novo estilo visual adotado pelo Visual Studio com a nova logomarca para refletir o design do Metro. Nota: Metro é um nome de código interno para uma tipografia baseada em linguagem de design criada pela Microsoft. Foi criado para uso em seu sistema operacional móvel Windows Phone 7 – uma versão feita especialmente com a família de fontes Segoe. A interface foi confirmada para o Windows 8, e também será utilizada no Xbox 360 criando se assim uma única linguagem visual entre os produtos Microsoft.

Abra o menu File e clique em New Project (Fig 1.0) ou na página inicial (Start Page) clique no link – New Project…(Fig 2.0).
 
Selecione o template Visual Basic (ou Visual C#) -> Web; Selecione o template ASP .NET Web Forms Application; Informe o nome do projeto WingTipsToys e clique no botão OK (Obs.: Eu estou usando o nome da solução conforme o artigo original). 
Após alguns segundos, será criado um projeto com uma estrutura básica contendo pastas e arquivos e apresentado na janela Solution Explorer. Abaixo vemos a solução exibida na janela Solution Explorer e a página Default.aspx exibida no modo Design: 
Podemos identificar as seguintes áreas no IDE: - Janela Solution Explorer - Exibe a solução, os projetos e seus respectivos arquivos e pastas;
- Janela de Propriedades - Exibe as propriedades do componente selecionado;
- Janela de Documentos - Exibe o arquivo selecionado;
- ToolBox - Exibe os controles disponíveis conforme o componente selecionado;
- Tab de visões do Documento - Permite selecionar os modos de exibição do arquivo selecionado.
Você pode alternar para o tipo de exibição Source ou no modo Split permitir a visualização dos dois tipos: Design e o seu respectivo Source. Na janela Solution Explorer, podemos gerenciar os arquivos do projeto. Vamos dar uma olhada nas pastas que foram adicionadas à sua aplicação no Solution Explorer. O modelo de aplicativo web acrescenta uma estrutura de pasta básica: 
O Visual Studio cria algumas pastas e arquivos iniciais para o seu projeto. Entre os arquivos, destacamos os seguintes: Arquivo | Propósito | Default.aspx | Geralmente é a primeira página a ser exibida quando a aplicação for executada no navegador (você pode alterar este comportamento). | Site.Master | Uma página que permite que você crie um layout consistente e use um comportamento padrão para as páginas em seu aplicativo. | Global.asax | Um arquivo opcional que contém o código para responder em nível de aplicação e sessão de eventos gerados pelo ASP.NET ou por módulos HTTP. | Web.config | O arquivo de configuração da aplicação. |
Executando a aplicação no seu navegador web padrão pressionando CTRL+F5, será apresentada a seguinte tela: 
Há três páginas principais nesse aplicativo Web padrão: default.aspx (Home), About.aspx e Contact.aspx. Cada uma dessas páginas pode ser alcançada a partir da barra de navegação superior. Há também duas páginas adicionais contidas na pasta Account – a página Register.aspx e Login.aspx. Elas permitem que você use os recursos de membership (associação) da ASP.NET para criar, armazenar e validar as credenciais do usuário. O recurso membership ASP.NET armazena as credenciais de seus usuários em um banco de dados criado pela aplicação. Quando os usuários efetuarem o login, o aplicativo vai validar suas credenciais através da leitura desse banco de dados. A pasta Account do projeto contém os arquivos que implementam as várias partes do membership: registro, login, alteração de senha e autorização de acesso. Além disso, o ASP.NET Web Forms suporta as autenticações OAuth e OpenID. Essas melhorias permitem que os usuários se autentiquem usando credenciais existentes, a partir de contas, tais como Facebook, Twitter, Windows Live e Google. - O OpenID é um protocolo descentralizado e simples para “Single Sign On” (SSO) e gestão de identidades digitais na web.
- O OAuth é um protocolo aberto para definir padrões de acesso a dados das APIs de serviços web.
|
Conceito: O que são os Web Forms ?O ASP.NET Web Forms são páginas que são baseadas na tecnologia Microsoft ASP.NET, na qual o código que é executado no servidor dinamicamente gera a saída de página Web para o navegador ou dispositivo cliente. Uma página ASP .NET Web Forms automaticamente renderiza o HTML compatível com o navegador para características como estilos, leiaute etc. Os Web Forms são compatíveis com qualquer linguagem suportada pelo CLR – Common Language Runtime – da plataforma .NET, como o Microsoft Visual Basic e a Microsoft Visual C#. Além disso, os Web Forms são construídos sobre os recursos da plataforma .NET, que oferece benefícios como um ambiente gerenciado, segurança de tipo e herança. Quando uma página ASP .NET Web Forms roda, ela passa por um ciclo de vida em que se realiza uma série de etapas de processamento. Essas etapas incluem inicialização, instanciamento de controles, restauração e manutenção do estado, a execução de código manipulador de eventos e a renderização. À medida que você se familiarizar mais com o poder do ASP.NET Web Forms, é importante que você entenda o ciclo de vida da página para que você possa escrever o código no estágio do ciclo de vida apropriado para o efeito que pretende obter. Quando um servidor Web recebe uma solicitação para uma página, ele encontra a página, processa, envia para o navegador e depois descarta todas as informações da página. Se o usuário solicita a mesma página novamente, o servidor repete toda a sequência, reprocessando a página a partir do zero. Dito de outra forma, um servidor não tem memória das páginas que foram processadas – as páginas não possuem estados (stateless). O framework ASP .NET automaticamente lida com a tarefa de manter o estado de sua página e seus controles, e isso lhe fornece formas explícitas para manter o estado de informações específicas do aplicativo. Nota: O ASP .NET oferece 3 modelos para desenvolvimento web : ASP .NET Web Forms, ASP .NET MVC e ASP .NET Web Pages. Antes de concluir este primeiro artigo, eu gostaria de chamar a atenção para dois novos recursos integrados ao Visual Studio Express 2012 for Web: - SQL Server Express LocalDB
- HTML5
1- SQL Server Express LocalDBSQL Server Express LocalDB é uma versão leve do SQL Server que tem muitas características de programação de um banco de dados SQL Server. O SQL Server Express LocalDB é executado no modo de usuário e tem uma instalação rápida sem a necessidade de configuração. No Microsoft SQL Server, o banco de dados ou qualquer código Transact-SQL podem ser movidos de SQL Server Express LocalDB para o SQL Server e SQL Azure, sem quaisquer passos de atualização. Então, o SQL Server Express LocalDB pode ser usado como um ambiente de desenvolvimento para aplicações que utilizem todas as edições do SQL Server. O SQL Server Express LocalDB permite recursos como procedimentos armazenados, funções definidas pelo usuário e agregados, Integração com NET Framework, tipos espaciais e outros recursos que não estão disponíveis no SQL Server Compact. 2- HTML 5O template ASP.NET Web Forms Application usa o HTML5, que é a versão mais recente da linguagem de marcação HTML. O HTML5 suporta novos elementos e funcionalidades que tornam mais fácil a criação de sites. Por exemplo, a aplicação Wingtip Toys usa HTML5 na master page (página mestra) Site.Master para criar uma barra de navegação, colocando uma lista de links dentro do elemento <nav>. Você pode facilmente modificar o elemento nav na página Site.Master para criar navegação para seus próprios aplicativos web. Os Elementos HTML5 adicionais no modelo de aplicação ASP.NET Web Forms incluem <header>, <rodapé>, <article>, <seção> e <hgroup>. - O elemento <header> envolve um grupo de ajudas à navegação.
- O elemento <rodapé> normalmente contém informações como quem foi o autor da seção, informações de copyright e links para documentos relacionados.
- O elemento <article> inclui conteúdo que pode ficar em sua própria e, potencialmente, ser distribuído de forma independente de outros conteúdos na página.
- O papel do elemento <section> é juntar um grupo temático de conteúdo, geralmente com um título.
- O elemento <hgroup> é útil quando você quiser um grupo de um conjunto de elementos para <h1> até <h6> que serão considerados como uma unidade dentro do esboço de documento global.
Neste primeiro artigo, eu criei o projeto no Visual Studio Express 2012 for Web e apresentei uma visão geral dos principais recursos da ferramenta que serão usados na criação do nosso web site. No próximo, iremos criar a camada de acesso a dados. *** Artigo de Macoratti
|
O MongoDB é um banco de dados
orientado a documentos de alta performance, open source e schema-free,
escrito em C++. Ele é uma mistura entre os repositórios escaláveis
baseados em chave/valor e a tradicional riqueza de funcionalidades dos
bancos relacionais.
Tem-se falado muito de bancos NoSQL e também do MongoDB, mas por que
você deveria usá-lo? Hoje vou te dar três razões para que você passe a
usar o MongoDB.
01. Consultas simples
MongoDB é um banco NoSQL baseado em documento sem transações e sem
joins. Quando um aplicativo utiliza esse tipo de banco de dados, o
resultado que se tem são consultas muito simples. Elas são mais fáceis
de escrever. Elas são mais fácil de ajustar. Deixam os desenvolvedores
fazerem seu trabalho mais facilmente. Em um exemplo onde 'usuarios'
possuem 'eventos', existe uma tabela para cada um, com um usuario_id na
tabela de eventos. Vamos dizer que eu quero todos os usuários
que publicaram um evento.
Em um banco de dados SQL, tenho duas tabelas: usuários e eventos. Eu poderia escrever esta consulta da seguinte forma:
SELECT * from `usuarios` INNER JOIN `eventos` ON `eventos`.`usuario_id` = `usuarios`
Analogamente, em um banco de dados MongoDB, digamos que eu tenha
apenas uma coleção: usuários. Cada documento de usuário tem um atributo
chamado "eventos", que é uma lista de documentos incorporados. Parece
algo como isto em JSON:
{
nome : Jean carlo Nascimento,
email: jnascimento@gmail.com,
eventos : [
{titulo : Primeiro!},
{titulo : Legal!},
{titulo : Festao, publicado : true}
]}
Para executar a mesma consulta em MongoDB, fica:
db.usuarios.find (('eventos.publicado': ($ ne: null)))
Mais simples. Mais simples de ler, de escrever. E você pode ver claramente como ele faz as coisas mais fáceis de entender.
02. Sharding
Sharding é um conceito simples: se você tem um monte de dados e está no
limite de disco e/ou a falta de espaço, a resposta é ter os seus dados
divididos entre várias máquinas. Você fica com mais rendimento e com
maior capacidade de armazenamento em disco. Em um mundo perfeito, como
seu armazenamento e desempenho precisa crescer, basta acrescentar mais
shards.
MongoDB é muito próximo a este mundo perfeito. Se você tem um processo mongod execução, e quer usar sharding, você:
- Abre uma nova máquina.
- Inicia um processo novo mongod para atuar como um membro do cluster shard.
- Inicia um processo novo mongod para atuar como um banco com
configuração separada, para manter informações sobre quais bancos
possuem shard.
- Inicia um processo mongo e informa como encontrar o db atual, o novo membro do shard, o banco de dados de configuração.
- Digita ~ 5 para permitir sharding em qualquer banco de dados e coleções que você quiser.
- Modifica seus aplicativos para se conectarem ao processo mongo ao invés do antigo processo mongod.
- Pronto.
Para saber mais como configurar o sharding, leia http://www.mongodb.org/display/DOCS/Configuring+Sharding
Toda a comunicação é feita sobre IP. Para configurar os processos
mongod e mongo, podem ser executados em suas próprias máquinas ou correr
na mesma máquina como um de seus shards. Isso pode ser feito com
qualquer tempo de inatividade. E você não precisa ter um olho para o
sharding quando começar, você pode tomar um antigo processo regular
mongod e vai "simplesmente funcionar".
Existem soluções para esse problema no MySQL, mas eles exigem
manipulação de dados em uma camada acima da base de dados. O próprio
banco não oferece suporte a esse recurso. Além disso, você não precisa
pensar sharding até que você precise dele, você não tem que
pré-otimizar.
Agora pense em vídeo HD, geolocalização, mensagens em tempo real,
realidade aumentada, imagens em tempo próximo ao real por satélite.
Pense em todos esses dados, e na velocidade que as pessoas vão querer
isso (e mashups e derivados disso). Então, pense sobre qual banco de
dados que você deseja começar a usar agora.
3. GridFS
Digamos que você tenha uma aplicação onde o usuário pode fazer upload de
uma foto de perfil. A prática corrente é a de armazenar o caminho para o
arquivo no banco de dados, armazenar o arquivo no filesystem (sistema
de arquivos compartilhado se você tiver vários servidores de aplicação)
ou S3. Se você usar um sistema de arquivos, algum tipo de apoio é
normalmente realizado também. Se você tem múltiplas aplicações, você tem
que usar um sistema de arquivos compartilhados.
Com GridFS, você armazena arquivos no banco de dados. MongoDB foi
construído para fazer isso. Por que isso é uma razão "para usar
MongoDB"? Porque o MongoDB tem replicação e sharding de coleções. E
adivinhem? Você pode aplicar esse material para coleções GridFS
perfeitamente bem. Quando você guarda os arquivos no MongoDB, recebe
toda a capacidade de replicação e sharding gratuitamente. Quer backup
dos arquivos do usuário? Basta replicar as coleções GridFS.
Guardar os arquivos em um banco de dados é o caminho que deveríamos fazer de agora em diante.
Para conhecer melhor o GridFS, leia esse texto.
Conclusão
Então, se você utilizar o MongoDB, será fantástico por causa de uma
sintaxe de consulta simples, a habilidade de shard dos dados entre
máquinas com a facilidade e a possibilidade de armazenar arquivos em
GridFS tirando partido de replicação e sharding. Isso porque não levei
em conta a facilidade de instalação dele, que ganha de longe do CouchDB! artigo publicado originalmente no iMasters, por Jean Nascimento
|
A dica Git desta semana é sobre puxar mudanças de um branch para outro, chamada de cherry picking.
Escolhendo mudanças
Cada commit em um repositório corresponde a uma tree cheia de
arquivos. Normalmente, esses arquivos foram criados ao longo de vários
commits. Mas, às vezes, é necessário levar o delta entre dois commits, e
aplicá-lo a um branch diferente.
Um caso comum em que isso ocorre é quando um problema foi
identificado e posteriormente corrigido, mas precisa portar para um
branch de versão anterior.
Nesse caso, você não quer pegar o estado atual da tree (que pode ter
alterações inacabadas ou não testadas); você só quer pegar o delta
associado a essa mudança.
Em outros sistemas de controle de versão, você teria apenas que criar
um diff com base na mudança mais recente, e depois corrigir a mudança
em seu branch de lançamento. Em vez disso, com o Git, podemos usar o
comando cherry-pick para fazer o trabalho para nós:
$ git checkout master
$ echo Working >> file.txt
$ git commit -m "Working" file.txt
$ echo BugFix >> bugfix.txt
$ git commit -m "BugFix" bugfix.txt
$ echo More Working >> file.txt
$ git commit -m "More working" file.txt
$ git checkout release10
$ git cherry-pick master~1
[release10 41037ab] BugFix
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bugfix.txt
Isso nos permitiu fazer uma única alteração - descrita aqui com master~1 - e copiar o delta no branch de lançamento.
Conjuntos de alterações
Podemos escolher conjuntos de commit (intervalos de revisões) para
escolher se quisermos. Se tivéssemos várias mudanças, poderíamos ter master~3..master~1. Ao contrário de apenas gerar um diff e patch da tree atual, isso vai copiar os commits (e suas relações) sobre o novo branch.
Na verdade, já vimos o pick em uso, quando abordamos rebasing
na semana passada. Quando você cria uma série de comandos para
rebasing, você está dando-lhe instruções para escolher ou editar as
alterações existentes:
@ edit 7bf9271 Typo
@ pick 756281e First
@ fixup 07e9061 First
@ pick 13aba60 Second
O “pick” aqui significa o mesmo que “git cherry-puck” para a mudança única. Na verdade, “edit” é realmente um atalho para “git cherry-pick -e”, e “fixup” e “squash” são atalhos para o git cherry-pick -n.
Origem da mudança
Finalmente, é interessante notar que, quando você copia uma mudança
usando esse mecanismo, o hash de commit vai mudar (notavelmente porque
terá uma hierarquia diferente).
Às vezes, isso não importa, mas se você deseja gravar onde a mudança original veio, você pode executar git cherry-pick-x. Isso insere uma mensagem de commit indicando de onde a mudança original veio:
$ git checkout release10
$ git cherry-pick -x master~1
$ git cherry-pick master~1
[release10 41037ab] BugFix (cherry picked from commit 938a4c0bbb3985524192aa8a926ea6757263e94b)
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bugfix.txt
No entanto, note que isso geralmente só faz sentido se a mudança que
está sendo pesquisada é de um branch público (para que a alteração de
referência seja visível). Outra forma de representar essa mudança é a
criação de um merge node entre o branch de liberação e o branch de
desenvolvimento em curso como uma forma de mostrar que a fusão ocorreu.
Criando um novo histórico
Sempre que você está usando o cherry-pick, principalmente se você
estiver reordenando commits, você está criando um novo histórico. No
entanto, você nunca realmente joga fora o antigo, tudo está disponível a
partir dos reflogs.
Você não está destruindo o histórico, você está criando outros
alternativos. Todo o cherry picking te dá a capacidade de aplicar os
patches de outros branches de uma maneira segura e com menos erros.
⁂
Texto original disponível em http://alblue.bandlem.com/2011/06/git-tip-of-week-cherry-picking.html
|
Hoje contamos com alguns servidores HTTP (web) tais como Apache, lighttpd, Nginx, TUX, Cherokee
e outros. O desenvolvimento deste artigo é para explicar melhor como
trabalhar com Python e desenvolver coisas novas para as necessidades do
dia a dia.
Vou explicar qual foi a necessidade do meu cliente para que eu escrevesse este software:
O Cliente tinha um sistema rodando com Ruby On Rails e o
desenvolvedor como não sabia configura o Ruby para processar juntamente
com o servidor web (Apache); ele rodou o servidor web do próprio Ruby On
Rails com a porta 4000.
Como teria que mexer no sistema e não sou programador Ruby, fiz uma
contra-proposta para desenvolver o sistema novamente (porque tinha
muitos erros) em Python (pois é a linguagem que eu sei programar). O
cliente aceitou e dei start no desenvolvimento.
Ao terminar o software, queria que ficasse transparente para o
usuário final (para ele acessar da mesma forma que acessava); testei
alguns servidores web como Nginx e lighttpd, só que ele estava comendo
recursos desnecessário no servidor, lembrando que eu só queria colocar
um HTML com uma meta tag para redirecionar para o sistema novo. Bom, resolvi desenvolver uma solução própria em Python, e achei a biblioteca BaseHTTPServer.
A estrutura que montei é a seguinte:
avelino@program-8:~/python/httpd$ ls htdocs httpd.py
O daemon que vamos usar é o httpd.py, vamos para a parte de código.
Vamos usar as seguintes bibliotecas:
import sys,os import string,cgi,time from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
Vamos escrever uma classe para tratar o POST e GET (Não usei o POST
na minha necessidade, mas para quem quer fazer um servidor HTTP simples
pode precisar):
class http(BaseHTTPRequestHandler):
def do_GET(self): try: if self.path.endswith(".html"): f = open(DocumentRoot + self.path) self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() self.wfile.write(f.read()) f.close() return
if self.path.endswith(".esp"): self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() self.wfile.write("hey, today is the" + str(time.localtime()[7])) self.wfile.write(" day in the year " + str(time.localtime()[0])) return
return
except IOError: self.send_error(404,'File Not Found: %s' % self.path)
def do_POST(self): global rootnode try: ctype, pdict = cgi.parse_header(self.headers.getheader('content-type')) if ctype == 'multipart/form-data': query=cgi.parse_multipart(self.rfile, pdict) self.send_response(301)
self.end_headers() upfilecontent = query.get('upfile') print "filecontent", upfilecontent[0] self.wfile.write("<html>Post OK. <br /><br />"); self.wfile.write(upfilecontent[0]); self.wfile.write("</html>")
except:
pass
Os nomes das def do_GET e do_POST são padrões do BaseHTTPRequestHandler. O do_GET usamos para renderização de qualquer arquivo. Por exemplo, temos uma index.html em nossa pasta htdocs, ele vai trabalhar pegando o arquivo index.html (/home/avelino/python/httpd/htdocs/index.html) e renderizando o html dele.
Vou criar uma função para chamar as declarações da classe:
def main(NameVirtualHost):
try: virtualhost = string.split(NameVirtualHost,":") if virtualhost[0] == "*": virtualhost[0] = "" server = HTTPServer((virtualhost[0], int(virtualhost[1])), http) print 'Start server HTTP IN %s' % NameVirtualHost server.serve_forever()
except KeyboardInterrupt: print 'Shutting down server HTTP' server.socket.close()
A var NameVirtualHost é onde vamos passar IP e PORTA para o servidor HTTP, exemplo.
Liberar só para acesso local: localhost:8000 Liberar para qualquer IP que estiver configurado na maquina: *:8000
Na biblioteca BaseHTTPServer temos uma função onde o
mesmo server, para rodar o servidor, recebe dois parâmetros: o primeiro
é IP/PORTA, e o segundo é a classe onde estão os métodos (GET, POST etc) que, no nosso caso, é a classe html.
Agora vamos chamar a def que fizemos:
if __name__ == '__main__': DocumentRoot = "%s/htdocs/" % os.path.realpath(os.path.dirname(__file__)) PORT = "8000" HOST = "localhost"
try : main(sys.argv[1]) except : main("%s:%s" % (HOST,PORT))
- DocumentRoot = Pega a pasta local que estamos e concatena com "/htdocs/"
- PORT = Porta padrão do servidor
- HOST = Host padrão do servidor
Temos uma TRY que vamos tratar o que vem por parâmetro (argv), caso
ele tenha valores errados chamará o HOST/PORT declarado do software.
Rodando o servidor:
avelino@program-8:~/python/httpd$ python httpd.py *:8000 Start server HTTP IN *:8000
Agora, para matar o processo, é como qualquer outro:
avelino@program-8:~/python/httpd$ python httpd.py localhost:8000 Start server HTTP IN localhost:8000 localhost - - [14/Sep/2010 09:42:05] "GET /index.html HTTP/1.1" 200 - localhost - - [14/Sep/2010 09:42:54] "GET /index.html HTTP/1.1" 200 - ^CShutting down server HTTP avelino@program-8:~/python/httpd$
Se olharmos o LOG acima, ele mostra tudo que foi processado com LOG de Apache ou qualquer outro servidor HTTP. artigo publicado originalmente no iMasters, por Thiago Avelino
|
Este é um tutorial sobre Python e GeeXLab. O objetivo é dar
uma olhada geral nas bibliotecas Python que podem ser úteis para demos GeeXLab E que funcionam no GeeXLab.
O GeeXLab
tem uma maneira muito simples de trabalhar. Superficialmente falando, um demo é
feito a partir de um script de inicialização (INIT, executado uma vez) e de um
script por frame (FRAME, executado a cada frame). Esses scripts podem ser
programados no Lua ou no Python. Em um script, você pode codificar o que quiser
com ambas as linguagens. Não existe restrição: o GeeXLab pode ser visto como
uma máquina virtual para o Lua ou o Python. É por isso que a maioria dos
pacotes Python disponíveis irá funcionar com o GeeXLab.
Para
interagir com os dados de cenário do GeeXLab (texturas, GLSL shaders, meshes
etc) existe o Host-API, que é simplesmente a API do GeeXLab para Lua e para Python. A
descrição das funções do Host-API para GeeXLab está disponível aqui.
A rápida
descrição do scripting do GeeXLab é importante, porque irei focar nas funcionalidades oferecidas por
essas bibliotecas, e tentarei limitar o uso das funções GeeXLab ao mínimo. Dessa maneira, você poderá
rapidamente reutilizar todos os fragmentos de códigos em seus próprios
projetos Python.
Dito
isso, vamos falar sobre a primeira biblioteca Python: PIL.
1 – PIL: biblioteca
de imagens do Python
PIL ou Biblioteca de Imagens do Python é um pacote que expõe muitas
funções para manipular imagens a partir de um script Python. A homepage oficial
do PIL está aqui. Quando escrevi este artigo, a versão atual do PIL era PIL
1.1.7 e estava disponível para Python 2.3 até Python 2.7. Irei usar o PIL 1.1.7 for Python
2.6 neste artigo.
No
Windows (XP, Vista ou 7), a instalação do PIL é bem simples: apenas inicie o PIL Windows installer e pronto. Claro que você precisa
de uma instalação válida do Python 2.6.6 antes.
A
documentação do PIL está disponível aqui:
2 – Carregando uma imagem
Aqui está
um pequeno script INIT que usa o PIL para carregar uma imagem e exibi-la. Se
você precisar, uma versão do PIL pode ser encontrada na variável Image.VERSION.
import HYP_Utils import sys
from PIL import Image
scriptDir = HYP_Utils.GetDemoDir()
PIL_Version = Image.VERSION
img_filename = "%s/flower.jpg" % scriptDir im = Image.open(img_filename) im.show()
No
Windows, a função Image.show() salva a imagem em um arquivo temporário e
chama o visualizador de imagem padrão. No meu sistema, o Irfanview é
chamado para visualizar a imagem:
Demo_Python_PIL_01.xml
3 – Salvando uma imagem
Apenas
chame e função Image.save(). Você quer
salvar no formato JPEG? Apenas adicione a extensão.jpg no nome do seu arquivo… Mesma
coisa para os outros formatos.
Formatos suportados
em leitura E escrita: *.bmp, *.gif, *.jpg, *.msp, *.pcx,
*.png, *.ppm, *.tiff e .xbm.
Aqui está um simples conversor de JPG para BMP:
import HYP_Utils from PIL import Image
scriptDir = HYP_Utils.GetDemoDir()
PIL_Version = Image.VERSION
img_filename = "%s/flower.jpg" % scriptDir im = Image.open(img_filename) im.save("%s/flower.bmp" % scriptDir)
4 – Lendo os pixels
Existem
duas funções que possibilitam a leitura do mapa de pixels (ou pixel data): Image.getpixel()
e Image.getdata().
Image.getpixel()
retorna o valor de um único pixel. Apenas faça a enupla com as coordenadas X e
Y e o getpixel() retornará um 3-tuple RGB para uma imagem RGB ou um único valor
para uma imagem de luminância. O Image.getdata() retorna o
mapa de pixels completo. Você precisa da função list() do Python para criar a lista do mapa de pixels das tuplenuplas RGB.
Aqui está um fragmento de código que carrega uma
imagem com PIL, cria um objeto de textura com o GeeXLab Python API e preenche a
textura com os pixels da imagem.
import HYP_Utils import HYP_Texture import HYP_Material import sys
from PIL import Image
scriptDir = HYP_Utils.GetDemoDir()
PIL_Version = Image.VERSION
img_filename = "%s/flower.jpg" % scriptDir im = Image.open(img_filename)
imageW = im.size[0] imageH = im.size[1]
TEXTURE_2D = 2 RGB_BYTE = 2 texId = HYP_Texture.Create(TEXTURE_2D, RGB_BYTE, imageW, imageH, 0)
matId = HYP_Material.GetId("plane1_mat") HYP_Material.AddTexture(matId, texId)
if (im.mode == "RGB"): for y in range(0, imageH): for x in range(0, imageW): offset = y*imageW + x xy = (x, y) rgb = im.getpixel(xy) HYP_Texture.SetValueTex2DByteRgb(texId, offset, rgb[0], rgb[1], rgb[2]) elif (imout.mode == "L"): for y in range(0, imageH): for x in range(0, imageW): offset = y*imageW + x xy = (x, y) rgb = im.getpixel(xy) HYP_Texture.SetValueTex2DByteRgb(texId, offset, rgb, rgb, rgb)
Com
o Image.getdata(), as últimas linhas do script anterior seriam:
pixels = list(im.getdata()) if (im.mode == "RGB"): for y in range(0, imageH): for x in range(0, imageW): offset = y*imageW + x rgb = pixels[offset] HYP_Texture.SetValueTex2DByteRgb(texId, offset, rgb[0], rgb[1], rgb[2]) elif (imout.mode == "L"): for y in range(0, imageH): for x in range(0, imageW): offset = y*imageW + x rgb = pixels[offset] HYP_Texture.SetValueTex2DByteRgb(texId, offset, rgb, rgb, rgb)
 Demo_Python_PIL_02.xml
5 – Processamento de imagem
Você pode facilmente aplicar filtros comuns de
imagem com o PIL: blur, emboss, sharpen etc. Apenas importe o módulo ImageFilter:
from PIL import Image from PIL import ImageFilter
...
i = Image.open(img_filename) im = i.filter(ImageFilter.EMBOSS)
...
Os
filtros pré-definidos são: BLUR, CONTOUR, DETAIL, EDGE_ENHANCE,
EDGE_ENHANCE_MORE, EMBOSS, FIND_EDGES, SMOOTH, SMOOTH_MORE, e SHARPEN.

Demo_Python_PIL_03.xml
– EMBOSS

Demo_Python_PIL_03.xml
– FIND_EDGES
Existe
também um módulo chamado ImageOps que expõe as funções de processamento
da imagem, como colorize(), flip(), grayscale(), invert(), mirror(),
solarize(), ou posterize().

Demo_Python_PIL_04.xml
– solarise()

Demo_Python_PIL_04.xml
– posterize()
6 – Adicionando uma marca d’água
ImageDraw e ImageFont garantem ao PIL a capacidade de escrever textos em uma imagem, bem como
desenhar linhas ou pontos. Aqui está o fragmento do código que mostra um
simples conversor de lotes com PIL: ele lê todos os arquivos jpg de uma pasta,
adiciona a marca d’água (uma cruz e a faixa “GEEXLAB”) e salva as imagens com o
prefixo gxl_.
import HYP_Utils import os, glob from PIL import Image from PIL import ImageDraw from PIL import ImageFont
scriptDir = HYP_Utils.GetDemoDir()
ft = ImageFont.load("timR24.pil")
os.chdir(scriptDir) file_list = glob.glob("*.jpg") for f in file_list: im = Image.open(scriptDir + str(f)) draw = ImageDraw.Draw(im) draw.line((0, 0) + im.size, fill=(255, 255, 255)) draw.line((0, im.size[1], im.size[0], 0), fill=(255, 255, 255)) wh = ft.getsize("G E E X L A B") draw.text((im.size[0]/2 - wh[0]/2, im.size[1]/2 + 20), "G E E X L A B", fill=(255, 255, 0), font=ft) draw.text((im.size[0]/2 - wh[0]/2, im.size[1]/2 - 60), "G E E X L A B", fill=(255, 255, 0), font=ft) del draw im.save(scriptDir + "gxl_" + str(f))
O
arquivo timR24.pil vem com um pacote de fontes PIL. Você pode fazer o download aqui.

Demo_Python_PIL_05.xml
Existe
também uma função legal ImageFont.truetype(), mas ela não funcionou no meu
sistema porque essa função se apóia na biblioteca _imagingft.pyd (na verdade um
DLL) que não pôde ser carregada devido a um problema de tempo de execução do Visual
C. Aqui está o erro em um console GeeXLab:
# ERROR:
Python – Script [initScene] has a runtime error. Error line: 29 – Error object:
– Error data: DLL load failed: The application has failed to start because its
side-by-side configuration is incorrect. Please see the application event log
or use the command-line sxstrace.exe tool for more detail.. Script disabled.
Este link tem alguns detalhes sobre esse
problema.
7 – Downloads
Se você
quiser brincar com os demos GeeXLab, você pode encontrá-los no pacote de
amostras demo disponíveis aqui. Os demos relacionados ao PIL estão na pasta
Python_PIL/.
Aqui está
um patch para o GeeXLab 0.2.5 + Python 2.6.6 que você deve usar para executar
os demos. Apenas unzip o arquivo e copie o DLL para dentro da pasta GeeXLab_Python_Lua/.
PATCH
DOWNLOAD: GeeXLabCore.dll
⁂
Texto original em
inglês de JeGX, disponível em http://www.geeks3d.com/20100930/tutorial-first-steps-with-pil-python-imaging-library/
|
Olá, pessoal! Neste artigo vou abordar uma dúvida que muitas
pessoas possuem ao começar na área de desenvolvimento de aplicações e
sistemas: existe uma maneira divertida de aprender a programar?

Bem, para começarmos é importante dizer que a programação é uma das
disciplinas que envolvem competências da área de ciências exatas e, por
causa disso, muita gente já torce o nariz e pensa que vai trabalhar com
números e coisas chatas. Mas não precisa ser assim! Como veremos, há
muitos recursos para tornar o aprendizado da programação de computadores
divertido, independente de qual linguagem, plataforma, ferramenta ou
recurso tecnológico for utilizado. Afinal de contas, uma certa babá
já dizia em 1900 e guaraná com rolha que na execução de qualquer
trabalho tem que haver um elemento de diversão. E isso vale para o
aprendizado de programação também!
Um ponto que deve ser deixado claro logo no início é que quando
falamos sobre diversão, provavelmente cada pessoa pensa na sua definição
pessoal do que é divertido. Ou seja, a diversão, assim como o humor, é
subjetiva e o que pode ser muito divertido e até hilário para uma
pessoa, pode ser completamente sem graça para outra. Quando falamos
sobre diversão ligada ao aprendizado de programação estamos nos
referindo a aquele tipo de diversão em que obtemos quando jogamos
xadrez, abrimos um brinquedo para ver como ele funciona, cozinhamos um
prato de uma receita nova ou passamos daquela fase difícil de um jogo
eletrônico. De qualquer maneira, o tipo de diversão que pode ser
associada com o aprendizado de programação é aquela em que nos
divertimos produzindo algo de maneira ativa e não passiva (tal como
assistir a um show de comédia em pé ou sentamos em um carrinho de uma
montanha russa). Ou seja, o foco deve ser em atitudes mais construtivas
do que contemplativas.

Outro detalhe importante é que geralmente encontramos material de
estudo (livros, cursos, vídeos, exemplos, projetos, exercícios) didático
e divertido para quem está começando a aprender a programar. Porém,
quem já possui um pouco de experiência e quer fugir dos exemplos
simples, procurando assuntos mais avançados, raramente vai encontrar
material divertido. Isso quer dizer que, quanto mais complexo o assunto
for, mais áspero, chato e entediante o material vai ser. Infelizmente,
isto ainda é verdade e parece que os produtores de conteúdos avançados
têm em mente que a partir de certo nível de complexidade o senso de
humor e os aspectos cômicos e divertidos devem que ficar de fora dos
estudos.
 
O primeiro recurso para aprender programação se divertindo tem a ver
com jogos. Inicialmente ligados à área de entretenimento, já faz algum
tempo que educadores e professores utilizam jogos para uma aprendizagem
lúdica. Gostaria de destacar dois jogos casuais que podem ser utilizados
para ensinar aspectos básicos de programação como sequência de passos,
modularização e recursão. Um deles é o LightBot,
um jogo em flash onde é preciso colocar ordens para que um robô vá de
um ponto a outro do tabuleiro e acenda uma lâmpada. O outro é o jogo
gratuito para a plataforma iOS chamado Cargo-bot,
onde é preciso indicar a sequências de ações necessárias para partir de
um estado inicial de blocos coloridos e chegar ao estado final. Estes
dois jogos são básicos e exercitam a maneira de pensar necessária para
quem quer programar.

Segundo a linha gradual de recursos para aprendizado divertido, o
próximo grupo de recursos se resume aos ambientes de programação visual.
Nesta abordagem geralmente utiliza-se algum tipo de linguagem de
programação simplificada que fornece suporte básico para variáveis,
desvios condicionais, loops, modularização, recursos para captar dados
de dispositivos de entrada e fundamentos de linguagens de programação
funcional. Um exemplo clássico é a linguagem de programação LOGO,
criada para ensinar crianças a fazer desenhos a partir de primitivas
gráficas simples. Existem vários interpretadores de LOGO, inclusive um disponível online.

Outro ambiente também voltado para crianças é o Kodu,
um jogo para Xbox que permite a criação de jogos simples a partir de
uma linguagem de programação visual que pode ser utilizada com o
controle do Xbox. Novamente, esta abordagem permite um contado inicial
com alguns dos recursos utilizados para a programação.

Recentemente, a plataforma de programação Scratch
vêm ganhando popularidade por permitir o uso fácil de elementos de
programação através da ação de clicar e arrastar. O principal foco dela é
facilitar o aprendizado a partir de blocos de programação pré-definidos
para a criação de pequenas animações e pode ser utilizado produzir
jogos com interatividade pelo teclado, animação de imagens e sons. Há,
inclusive, propostas de ensino utilizando este software junto com o Raspberry Pi para ensinar conceitos fundamentes de programação para crianças. Este link mostra outas abordagens voltadas o ensino divertido de programação para crianças.
Ainda focando em crianças, este estudo
mistura o uso de marionetes como recurso para aprendizado de
programação. O interessante neste caso é o emprego de aspectos culturais
de forma didática associada ao aprendizado em comunidades carentes que
não possuem recursos tecnológicos, mas mesmo assim podem aprender a
programar. Sem contar que tal atividade pode ajudar a identificar
prodígios e indivíduos que possivelmente podem se tornar muito
proficientes na área da programação e, em geral, em qualquer uma das
ciências exatas. Este é, na minha opinião, um uso mais nobre e adequado
de marionetes do que o simples entretenimento e emprego do conteúdo para fins publicitários.
 
Uma das frustrações de quem começa a aprender a programação é a falta
de resultado imediato e a consequência das linhas de programação no
mundo físico fora do computador. Bem, nestes casos pode ser interessante
tentar programar algum tipo de sistema robótico cuja saída do programa
seja representada por movimentos de um robô. A LEGO foi pioneira com um
kit para desenvolvimento de robótica chamado MindStorm
que é muito interessante, pois além dos componentes físicos que devem
ser montando existe uma plataforma de desenvolvimento visual que permite
programar o robô em uma sequência de passos sem se preocupar com
detalhes de nomes de comandos, parâmetros de funções, sintaxe, regras de
precedência, operadores e tantos outros elementos que tornam o
aprendizado de programação complexos, chatos e até maçantes. Mesmo quem
não possui meios de se obter este kit é possível trabalhar com o
simulador ou procurar outras abordagens semelhantes como este , este, este e este projeto.

Existem muitos recursos divertidos para quem está procurando material
de aprendizado focado em uma plataforma ou linguagem de programação
específica. Na parte de livros podemos notar que algumas editoras
resolveram investir em outras maneiras de explicar o conteúdo como, por
exemplo, a série de livros Use a Cabeça (Head First) e também Os Guias Manga.
Aqui uma recomendação pessoal: quem está estudando conceitos profundos
de computação e quer um livro muito bom que explora a relação de
algoritmos e matemática recomendo o ótimo Matemática Concreta.
Além de ser co-escrito por um dos mais importantes professores da área
da computação, Donald E. Knuth, o uso do recurso simples de anotações na
margem das páginas faz dele o livro de matemática voltado para
computação mais divertido que já li. Mas não se enganem: não é um livro
de leitura fácil, seu conteúdo é complexo e os tópicos são fortemente
baseados em equações, notações e elementos matemáticos que exigem muito
do leitor que não está acostumado a enxergar a computação desta maneira.
Contudo, isso não deixa o livro menos divertido do que qualquer comédia
estrelada pela celebridade cômica da vez.

Quem está procurando material didático no formato de curso online de programação se depara com diversas opções. O CodeAcademy segue uma linha interativa muito divertida. Já os vídeos do site FunProgramming
são recomendados para designers, web masters e profissionais da área
digital ou gráfica com tendência artística, pois todo o conteúdo é
apresentado através da linguagem Processing. Outra abordagem é
apresentado no site TheCodePlayer cujas animações simulam o cenário onde o aprendiz olha por cima do ombro de quem está programando.
Como
não poderia deixar de ser, o uso de sarcasmo, contra-exemplos,
anomalias e bizarrices também pode representar uma alternativa divertida
no aprendizado de programação. O blog Coding Horror é um exemplo deste tipo de recursos, assim como o concurso internacional de código em c ofuscado e outros. Há também uma boa dose das populares tirinhas e web comics,
cujo tema é programação e que se não ensina como programar, ao menos
faz os leitores rirem das situações no mínimo inusitadas pelas quais
profissionais ligados à programação se deparam.
Há quem diga que para aprender de forma divertida basta encontrar um
projeto que o aprendiz considera legal e sair codificando. Nesta
filosofia, vale a pena dar uma olhada em sites especializados para
desenvolvimento de jogos como o GameDev e o Open Source Arcade,
pois eles possuem diversos recursos incluindo repositórios no Git Hub
com o código fonte completo de jogos profissionais e semi-profissionais.
Há também diversas listas com projetos que podem ser divertidos de
programa (aqui, aqui e aqui).
O aprendizado de programação pode ser algo muito solitário. Às vezes
brinco com os meus alunos dizendo que quem está começando a aprender
precisa ter um índice HBC muito alto (HBC significa Horas de Bunda na
Cadeira). Mas hoje em dia não precisa ser mais assim: existem diversas
atividades em grupo que além de tornar o aprendizado de programação mais
divertido também proporcionam um aspecto social muito e, quem sabe, num
destes eventos o aprendiz encontre alguém para um projeto e deste
encontro apareça uma semente para uma nova empresa?


Um dos eventos que vêm ganhando muito destaque atualmente e que
considero divertidíssimo é o conding dojo. Neste tipo de encontro
geralmente um problema é proposto por um programador mais experiente e
quem está participando é livre para trocar ideias e desenvolver a sua
solução da maneira que achar melhor. O iMasters orgulhosamente fomenta, patrocina e conduz alguns dojos de programação
para quem estiver interessado neste tipo de evento. Outra boa
iniciativa é participar das maratonas de programação hacker, as já
conhecidas hackatons.
Neste contexto vale a pena participar com um grupo já formado e sair
projetando a solução. Nem sempre atrativa a novatos, esta atividade é
muito divertida e recomendada para quem está começando com a programação
e quer aprender não só aspectos técnicos para também observar como
programadores mais experientes trabalham e alcançam níveis de
produtividade impressionantes.
Para finalizar, outra sugestão divertida que ajuda quem está
começando a programa é ouvir podcasts que falam sobre este assunto. Sou
suspeito para falar, mas o DatabaseCast possui alguns episódios para iniciantes como este aqui. Também recomendo este, esta série de episódios (parte 1, parte 2, parte 3, parte 4, parte 5 e parte 6) e também este programa
que não necessariamente ensinam passo a passo a programar, mas que com
certeza ajudam a tirar um pouco a cara da frente do monitor e ainda se
divertir durante o aprendizado de programação.
*** Artigo de Mauro Pichiliani
|
Olá, pessoal! Se você está iniciando com o Hibernate, um dia vai ser apresentado ao Criteria. Realmente, quem usa o Criteria não quer voltar ao SQL para as funções mais básicas e só o faz nos casos extremos, nos quais o Criteria não atende. Então, neste artigo vou mostrar um pouco o que se pode fazer com o Criteria nas suas aplicações Java. Farei uma breve introdução neste primeiro artigo e no próximo vamos colocar mão na massa. Mas, por enquanto, quero que conheçam um pouco a sintaxe. CriteriaO Criteria Query API permite construir query expression em Java, possibilitando, assim, a checagem em tempo de compilação - ao contrário do HQL ou SQL. O Criteria API permite, de forma programática, construir objetos query a partir da interface org.hibernate.Criteria, que define os métodos disponíveis que precisamos para trabalhar com o Criteria. Para persistir um objeto da classe, usamos o método createCriteria(), que retorna um objeto Criteria, que permite ter acesso a instância de persistência da classe. O createCriteria() pertence à interface Session. Então, se for preciso retornar todas propriedades de uma classe com Criteria, seria assim: Criteria critera = session.createCriteria(Produto.class)
List lista = criteria.list();
Bem mais simples do que o HQL. Este é o mesmo resultado com o from Produtos, que executamos no HQL e que fazemos no SQL: SELECT * from mytable. Vamos dizer que precisamos obter os produtos que tenham no nome “smartphone”, então, precisamos conhecer o método add() da classe Criteria, que tem como objetivo adicionar uma restrição em seu argumento. Uma outra classe importante é Restrictions class, do pacote org.hibernate.Criterion, que possui métodos static para as condições de restrições que precisamos. Veja o trecho do código: Criteria crit = sesion.createCriteria(Produto.class)
crti.add(Resctrictions.eq(“nome”, “smart phone”);
List list = crit.list();
Explicando o código:Na primeira linha, nós criamos o objeto Criteria que fez a persistência em nossa entidade. Na linha 02, costumo ler da seguinte forma para facilitar a compreensão: “adicionando uma restrição a class persistida”. Na linha 03 é o resultado da restrição. Um ponto importante é que não podemos fazer uma restrição de resultado usando o método eq/ne para propriedades com o valor null. Para isso, há métodos static especificos: o isNull() e o isNotNull(). Para realizar busca, temos os métodos like() e ilike(). Eles servem para quando precisamos buscar algo fornecendo apenas algumas informações para o buscador. Exemplo: traga todos os produtos que tem a palavra “smart”. A diferença é que o ilike é case-insensitive. Outro detalhe importante que podemos informar é onde buscaremos a palavra: no inicio, no final - para ser exato -, ou em qualquer lugar. Exemplo: Criteria crit = session.createCriteria(Produto.class)
crit.add(Restrictions.like(“nome”, “smart%”));
List list = crit.list();
O símbolo % informa que a busca é por partes da string. No exemplo a seguir, eu seleciono para buscar no final dela. Crit.add(Restrictions.like(“nome”, “smart”, MatchMode.end)); O MatchMode é um tipo de enumeration que possui quatro tipos diferentes de match: anywhere, end, exact, start. E assim finalizo o primeiro artigo sobre Criteria. No próximo veremos mais algumas restrições interessantes. Espero que tenham gostado do artigo!
|
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
|
Se você trabalha com desenvolvimento de software, por experiência
própria, deve saber que a única constante no processo de
desenvolvimento é a mudança.
Mas por que isso ocorre? Com o desenvolvimento tecnológico obtidos
nos últimos tempos a área da tecnologia da informação foi impactada por
dois fatores importantes:
- O aumento do tamanho e da complexidade dos sistemas de software;
- A redução do tempo e custo de desenvolvimento e manutenção do software.
Assim, os sistemas ficaram mais complexos e maiores e o tempo e o
orçamento para desenvolver tais sistemas diminuiu. E o negócio não pode
parar…
Um software é um produto que foi criado para atender uma necessidade
de negócio, e os requisitos de negócio mudam a todo instante com base
nas prioridades do mesmo, logo o software tem que ser alterado para dar
suporte a tais mudanças. Dessa forma, um software que não foi bem
projetado para dar suporte às constantes mudanças irá se tornar obsoleto
e não vai mais cumprir o seu objetivo afetando os negócios.
Então ‘o negócio’ é projetar um software que seja fácil de ajustar e
barato de manter. Parece simples não é mesmo? Tudo começa com a
definição da arquitetura de software a ser adotada. Uma das tarefas
fundamentais no processo de criação de um software é a definição da
arquitetura do projeto de software pois uma arquitetura consistente e
bem definida se torna fundamental para que o projeto seja implementado
com eficiência.
A arquitetura de software desempenha um papel fundamental para
gerenciar a complexidade inerente ao software a ser criado. Uma boa
arquitetura possibilita que um sistema satisfaça às exigências
principais de um projeto, tais como: desempenho, confiabilidade,
portabilidade, manutenibilidade, interoperabilidade e etc.
Uma má arquitetura simplesmente fará com que o software seja um fracasso.
O que é arquitetura de software ?
Existem muitas definições de arquitetura de software:
“Uma arquitetura de software envolve a descrição de
elementos arquiteturais dos quais os sistemas serão construídos,
interações entre esses elementos, padrões que guiam suas composições e
restrições sobre estes padrões”. GARLAN, 2000
“A arquitetura de software define o que é o sistema em termos de
componentes computacionais e os relacionamentos entre estes
componentes”. VAROTO, 2002
“A arquitetura de software de um sistema consiste na definição dos
componentes de software, suas propriedades externas, e seus
relacionamentos com outros softwares. O termo também se refere à
documentação da arquitetura de software do sistema. A documentação da
arquitetura do software facilita: a comunicação entre os stakeholders,
registra as decisões iniciais acerca do projeto de alto-nível, e permite
o reuso do projeto dos componentes e padrões entre projetos”. http://pt.wikipedia.org/wiki/Arquitetura_de_software, acessado em 2012
Obs: Stakeholder é qualquer pessoa ou organização
que tenha interesse, ou seja afetado pelo projeto. (Stake: interesse,
participação, risco / Holder: aquele que possui)
Assim, a arquitetura de um sistema deve definir os elementos que irão
compor o software. Tais elementos definem como o software é
particionado em pedaços menores e, assim, definem como o software é
entendido.
Como definir uma boa arquitetura?
Segundo o RUP – Rational Unified Process, a arquitetura de um
software envolve o conjunto de decisões que definem a organização do
sistema e devem cumprir os seguintes objetivos:
- Definir os elementos estruturais e suas interfaces de modo a estabelecer a composição do sistema;
- Estabelecer o comportamento pela colaboração entre estes elementos;
- Compor estes elementos estruturais e comportamentais em subsistemas (agregação).
Diversos fatores influenciam a definição da arquitetura como por exemplo:
- Arquitetura do hardware;
- Sistema operacional utilizado;
- Sistema Gerenciador de Banco de dados adotado;
- Protocolos de rede;
- A linguagem de programação;
- O ambiente de interface gráfica;
- As bibliotecas de funções disponíveis;
- Os sistemas legados envolvidos;
- As necessidades de desempenho, portabilidade, usabilidade, disponibilidade, etc;
- Documentação.
Levando em conta esses fatores e sendo bem objetivo e prático, como
podemos definir uma arquitetura básica que possa ser implementada em
sistemas de pequeno é médio porte?
Por onde começar?
Comece pelo começo…
1. Defina os requisitos do sistema
Definir de forma sistemática os requisitos do sistema envolvendo
todos os stackholders (interessados) no projeto de forma a ter o maior
número possível de requisitos definidos de forma clara e objetiva;
Os requisitos expressam as características e restrições do produto de
software do ponto de vista de satisfação das necessidades do usuário,
e, em geral independem da tecnologia empregada na construção da solução
sendo a parte mais crítica e propensa a erros no desenvolvimento de
software.
Requisitos são objetivos ou restrições estabelecidas por clientes e
usuários do sistema que definem as diversas propriedades do sistema. Os
requisitos de software são, obviamente, aqueles dentre os requisitos de
sistema que dizem respeito a propriedades do software.
A necessidade de se estabelecer os requisitos de maneira de forma
precisa é crítica na medida que o tamanho e a complexidade do software
aumentam. Os requisitos exercem influência uns sobre os outros. Por
exemplo, o requisito de que o software de ter grande portabilidade (por
exemplo, ser implementado em Java) pode implicar em que o requisito
desempenho não seja satisfeito (programas em Java são, em geral, mais
lentos).
Uma boa especificação de requisitos deve ser:
- Clara e não ambígua;
- Completa;
- Correta;
- Compreensível;
- Consistente;
- Concisa;
- Confiável;.De acordo com Farley, um documento de especificação de requisitos deve possui as seguintes seções:
- Visão geral do produto e sumário;
- Ambientes de desenvolvimento, operação e manutenção;
- Interfaces externas e fluxo de dados;
- Requisitos funcionais;
- Requisitos de desempenho;
- Tratamento de exceções;
- Prioridades de implementação;
- Antecipação de mudanças e extensões;
- Dicas e diretrizes de design;
- Critérios de aceitação;
- Índice remissivo;
- Glossário.
2. Definir uma ferramenta ORM
De forma geral, você pode escolher uma ferramenta ORM para ajudá-lo a
criar os objetos com base no seu domínio e a partir deles gerar o banco
de dados usado pela aplicação.
Existem dezenas de ferramentas ORMs disponíveis no mercado. Abaixo uma relação das mais importantes para a plataforma .NET:
(fonte: http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software)
- ADO.NET Entity Framework, included in .NET Framework 3.5 SP1 and above
- AgileFx, open source
- Base One Foundation Component Library, free or commercial
- Devart LinqConnect, commercial, an ORM solution for Oracle, MySQL, PostgreSQL, and SQLite
- Castle ActiveRecord, ActiveRecord for .NET, open source
- DatabaseObjects .NET, open source
- DataObjects.NET, commercial
- ECO, commercial but free use for up to 12 classes
- EntitySpaces, commercial
- Habanero, free open source enterprise application framework with a free code generating tool
- MyBatis, free open source, formerly named iBATIS
- iBATIS, free open source, maintained by ASF but now inactive.
- LINQ to SQL, included in .NET Framework 3.5
- LLBLGen Pro, commercial
- Neo, open source but now inactive.
- NHibernate, open source
- nHydrate, open source
- OpenAccess ORM, by Telerik free or commercial
- Persistor.NET, free or commercial
- Quick Objects, free or commercial
- Signum Framework, open source
- SubSonic, open source
- Symbiotic, by Frozen Elephant Inc.
- XPO, commercial, by DevExpress
3. Aplique a separação das responsabilidades ao seu projeto de software
A definição da separação em camadas estimula a organização da
arquitetura do sistema em um conjunto de camadas coesas com fraco
acoplamento entre elas onde cada camada possui um propósito bem
definido.
Principais camadas:
- UI(camada de apresentação): agrega as classes do sistema com as quais os usuários interagem;
- Negócio: mantém as classes do sistema responsáveis pelos serviços e regras do negócio;
- Dados: camada responsável pelo armazenamento e recuperação dos dados persistentes do sistema;
- Comunicação: responsável pela distribuição do sistema em várias máquinas.

Considerações:
- Seja explícito sobre como as camadas se comunicam entre si –
Permitir que todas as camadas em um aplicativo se comuniquem ou tenham
dependências sobre todas as outras camadas resultará em uma solução que é
mais difícil de entender e gerenciar;
- Use a abstração para implementar o acoplamento fraco entre as
camadas – Isto pode ser conseguido através da definição de componentes
de interface, tais como uma Facade com entradas e saídas bem conhecidos
que traduzem os pedidos para um formato compreendido por componentes no
interior da camada;
- Não misture tipos diferentes de componentes na mesma camada lógica –
Comece por identificar diferentes áreas de interesse e, em seguida
agrupe os componentes associados a cada área de interesse em camadas
lógicas. Por exemplo, a camada de interface do usuário não deve conter
componentes de processamento de negócios, mas deve conter componentes
usados para manipular a entrada do usuário e solicitações dos usuários
do processo;
- Mantenha o formato de dados consistente dentro de uma camada ou
componente – Misturar formatos de dados irá tornar a aplicação mais
difícil de implementar, ampliar e manter. Toda vez que você precisar
converter dados de um formato para outro, você é obrigado a implementar o
código de tradução para executar a operação e incorrendo em uma
sobrecarga de processamento.
4. Utilize padrões de projeto de forma a obter um código robusto e obter a reutilização de código
- Mantenha os padrões de projeto consistentes dentro de cada camada –
Dentro de uma camada lógica, sempre que possível, o design de
componentes deve ser consistente para uma determinada operação;
- Não duplique a funcionalidade de um aplicativo – Deve haver apenas
um componente proporcionando uma funcionalidade e esta funcionalidade
específica não deve ser repetida em qualquer outro componente. Isso faz
com que seus componentes coesos e torna mais fácil otimizar os
componentes se uma determinada função ou funcionalidade sofrer
alterações;
- Estabeleça uma convenção de estilo de codificação e nomeação para o
desenvolvimento – Verifique se a organização estabeleceu o estilo de
codificação e padrões de nomenclatura.
5. Adote princípios básicos de projeto de software
- Separação de Responsabilidades – Divida sua aplicação em recursos
distintos com a menor sobreposição de funcionalidade possível. O fator
importante é a minimização dos pontos de interação para alcançar alta
coesão e baixo acoplamento;
- Princípio da responsabilidade individual- Cada componente ou módulo
deve ser responsável por apenas uma característica específica ou
funcionalidade, ou agregação de funcionalidade coesa;
- Princípio da menor conhecimento – (também conhecida como Lei de
Deméter ou LoD). Um componente ou objeto não deve saber sobre detalhes
internos de outros componentes ou objetos;
- Não repita você mesmo (DRY) – Você só precisa especificar a intenção
em um só lugar. Por exemplo, em termos de projeto da aplicação, a
funcionalidade específica deve ser implementada em apenas um componente;
a funcionalidade não deve ser repetida em qualquer outro componente;
- Minimizar projeto inicial – Projete apenas o necessário. Em alguns
casos, você pode requerer um projeto inicial abrangente com realização
de testes para verificar se o custo de desenvolvimento ou uma falha no
projeto será muito alto. Em outros casos, especialmente para
desenvolvimento ágil, você pode evitar antecipadamente um projeto
grande. Se os requisitos da aplicação não são claros, ou se existe a
possibilidade do projeto evoluir ao longo do tempo, evite fazer um
esforço grande prematuramente. Este princípio é conhecido como YAGNI
(“Você não vai precisar dele” – You ain’t gonna need it);
- Considere a operação de sua aplicação – Determine quais métricas e
dados operacionais são exigidos pela infraestrutura de TI para garantir a
implantação e operação eficiente de sua aplicação.
6. Determinar o tipo de aplicação
Escolher o tipo de aplicação adequada é a peça chave do processo de
concepção de uma aplicação. Sua escolha é governado por suas
necessidades e limitações específicas de infraestrutura. Muitas
aplicações devem suportar vários tipos de cliente, e podem fazer uso de
mais do que um dos arquétipos básicos:
- As aplicações concebidas para dispositivos móveis;
- Aplicações rich client projetadas para funcionar primeiramente em um PC cliente;
- Aplicações ricas da Internet projetadas para serem implantadas a
partir da Internet, que suportam interface rica e cenários de mídia;
- Aplicações de serviços projetados para suportar a comunicação entre os componentes fracamente acoplados;
- Aplicativos da Web concebidos para serem executados principalmente no servidor em cenários totalmente conectados.
7. Determinar a estratégia de distribuição
O aplicativo pode ser implantado em uma variedade de ambientes, cada
um com seu próprio conjunto específico de restrições, como a separação
física dos componentes em diferentes servidores, uma limitação em
protocolos de rede, configurações de firewall e roteador e muito mais.
Existem vários padrões comuns de implantação, que descrevem os
benefícios e as considerações para uma série de cenários distribuídos e
não distribuídos. Você deve equilibrar as necessidades da aplicação com
os padrões apropriados que hardware pode suportar, e as restrições que o
ambiente exerce sobre as opções de implantação. Estes fatores irão
influenciar o seu projeto de arquitetura.
8. Determinar os atributos de qualidade desejados
Os atributos de qualidade, tais como segurança, desempenho e
usabilidade podem ser usados para focar o seu pensamento sobre os
problemas críticos que seu projeto deve resolver. Dependendo de suas
necessidades, você pode ter que considerar todos os atributos de
qualidade, ou talvez você só precise considerar um subconjunto. Por
exemplo, cada projeto de software deve considerar sempre a segurança e o
desempenho, mas o projeto talvez não precise considerar os atributos
interoperabilidade e escalabilidade.
9. Determine um processo bem definido de desenvolvimento de software
Um exemplo muito usado a ser considerado é o Processo Unificado da
Rational (RUP) que foi construído envolvendo as seis melhores práticas
para fornecer um processo bem definido e foi baseado nas boas práticas
de desenvolvimento de software.
O RUP é um processo de desenvolvimento de software que assegura a
produção de software de qualidade de forma repetida e previsível, com
isso, se ganha tempo e facilita no desenvolvimento do projeto, visto que
as tarefas são divididas de formas iterativas.

O modelo do RUP é interativo e incremental onde temos que em cada iteração:
- São identificados e especificados os casos de uso mais relevantes;
- E feita a análise e projeto dos casos de uso, usando-se a arquitetura como guia;
- São implementados componentes que realizam o que foi projetado;
- Verifica-se se os componentes satisfazem os casos de uso escolhidos.
Os casos de uso são usados no planejamento e acompanhamento das iterações:

A arquitetura serve para organizar o desenvolvimento, estruturar a
solução e identificar oportunidades de reuso enquanto que os casos de
uso dizem o que deve ser feito.
Dessa forma, podemos resumir o processo de desenvolvimento de software em cinco etapas:

*** Artigo de Macoratti
|
Neste artigo, veremos como inserir e obter imagens de um banco de
dados SQL Server e como exibir as imagens em um controle GridView.
Acompanhe a versão para desktop deste artigo no link: Trabalhando com imagens no SQL Server – Macoratti.net
Vamos iniciar abrindo o Visual Web Developer 2010 Express Edition e criando um novo projeto via opção File -> New Project.
Selecione a linguagem Visual C# e a opção Web.
A seguir, selecione o template ASP .NET Web Application e informe o nome Tratando_Imagens_SQLServer.

Criando o banco de dados no SQL Server
Eu poderia criar o banco de dados usando o SQL Server Management Studio (SSMS), mas vou usar o próprio ambiente do Visual Web Developer Express Edition.
Abra a janela DataBase Explorer e clique com o botão direito em Data Connections, clicando a seguir em Add Connection.

Na janela Add Connection, clique no botão Change e altere o Data Source para: Microsoft SQL Server Database File.
Obs: Esta janela poderá exibir outras opções de Data Source, mas eu
escolhi trabalhar com um banco de dados anexado ao meu SQL Server Local.

Informe o nome do banco de dados; no exemplo, o nome usado foi Cadastro.mdf, e clique no botão OK.

Uma caixa de diálogo irá surgir informando que o banco de dados não
existe e se você deseja criá-lo. Confirme e clique no botão Sim para
criar o banco de dados.
Você verá na janela DataBase Explorer o banco de dados Cadastro.
Clique com o botão direito no item Tables e a seguir clique em Add New Table;

Crie a tabela Imagens definindo os campos:
- id – int – chave primária e do tipo identity;
- descrição – nvarchar(150)
- imagem – image

Assim, temos o banco de dados Cadastro.mdf e a tabela Imagens criadas e prontas para serem usadas.
Definindo as páginas do projeto
Vamos definir a página Default.aspx como a página principal do
projeto clicando com o botão direito do mouse sobre essa página e
selecionando a opção Set As Start Page.
Agora vamos alterar o código da página Site.Master para exibir uma
opção para acessar a página onde vamos tratar as imagens conforme o
código a seguir:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="Tratando_Imagens_SQLServer.SiteMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
<title></title>
<link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form runat="server">
<div>
<div>
<div>
<h1>
Macoratti .net
</h1>
</div>
<div>
</div>
<div>
<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal">
<Items>
<asp:MenuItem NavigateUrl="~/Default.aspx" Text="Home"/>
<asp:MenuItem NavigateUrl="~/About.aspx" Text="About"/>
<asp:MenuItem NavigateUrl="~/Imagens.aspx" Text="Imagens"/>
</Items>
</asp:Menu>
</div>
</div>
<div>
<asp:ContentPlaceHolder ID="MainContent" runat="server"/>
</div>
<div>
</div>
</div>
<div>
</div>
</form>
</body>
</html>
A seguir, vamos incluir um novo Web Form chamado Imagens.aspx em nosso projeto.
No menu Project, clique em Add New Item.
Selecione o template Web Form using Master Page, informe o nome Imagens.aspx e clique no botão Add.

Na próxima janela, selecione a master page Site.Master e clique em Ok.

Vamos incluir na página Imagens.aspx a partir da toolbox os seguintes controles:
- TextBox – ID=txtDescricao TextMode=Multiline
- FileUpload – ID=arquivoUploadImagem
- GridView – ID=gdvImagens
- Button – ID=btnUpload – Text=Enviar Arquivo
Conforme o leiaute da figura abaixo:

No controle GridView, vamos definir dois campos: Descrição e Imagem.

A seguir, vamos converter o campo Imagem em um TemplateField e definir nesse template um controle Image.
Defina a seguir as propriedades DataBindings conforme a figura abaixo para esse controle:

O código do arquivo Imagens.aspx deverá ficar da seguinte forma:
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="Imagens.aspx.cs" Inherits="Tratando_Imagens_SQLServer.Imagens" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
Inserindo e Recuperando imagens no SQL Server com ASP .NET
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<head>
<style type="text/css">
.Gridview
{
font-family:Verdana;
font-size:10pt;
font-weight:normal;
color:black;
}
</style>
</head>
<table>
<tr><td> Descricao:</td>
<td> <asp:TextBox ID="txtDescricao" runat="server" BackColor="#FFFFCC" Height="97px"
TextMode="MultiLine" Width="260px"></asp:TextBox>
</td>
</tr><tr><td>Imagem:</td>
<td> <asp:FileUpload ID="arquivoUploadImagem" runat="server" Width="350px" /> </td>
</tr><tr><td>
</td>
<td><asp:Button ID="btnUpload" runat="server" Text="Enviar Arquivo"
onclick="btnUpload_Click" />
</td>
</tr>
</table>
</div>
<asp:GridView ID="gdvImagens" CssClass="Gridview" runat="server" AutoGenerateColumns="False"
HeaderStyle-BackColor="#7779AF" HeaderStyle-ForeColor="white" Height="766px"
Width="521px">
<Columns>
<asp:BoundField HeaderText = "Descrição" DataField="imagename" />
<asp:TemplateField HeaderText="Imagem">
<ItemTemplate>
<asp:Image ID="Image1" runat="server"
ImageUrl='<%# "ImageHandler.ashx?ImgID="+ Eval("id") %>' Height="150px"
Width="150px"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle BackColor="#7779AF" ForeColor="White"></HeaderStyle>
</asp:GridView>
</asp:Content>
Observe que no botão Enviar Arquivo estamos tratando o evento Click.
Definindo a string de conexão no arquivo Web.Config
Abra o arquivo Web.Config e inclua o código abaixo na seção
<configuration> para definir a string de conexão com o banco de
dados Cadastro.mdf:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="ConexaoSQLServer"
connectionString="Data Source =.\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>
.........
........
Definindo o código para tratamento das imagens
Vamos abrir o arquivo code-behind Imagens.aspx.cs e definir o seguinte código:
No início do arquivo, defina a utilização dos seguintes namespaces:
using System; using System.Web; using System.Web.UI; using System.Data; using System.Data.SqlClient; using System.Configuration;
Após a declaração do formulário, obtenha a string de conexão do arquivo web.config:
string strcon = ConfigurationManager.ConnectionStrings["ConexaoSQLServer"].ConnectionString;
No evento Load da página, inclua o código abaixo:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
VincularDados();
}
}
No evento Click do botão Enviar inclua o código a seguir:
protected void btnUpload_Click(object sender, EventArgs e)
{
//Verifica se enviou imagem ou não
if (arquivoUploadImagem.HasFile)
{
//obtem o tamanho da imagem enviada
int tamanho = arquivoUploadImagem.PostedFile.ContentLength;
//cria um array de bytes para armazenar os dados binários da imagem
byte[] imgbyte = new byte[tamanho];
//armazena a imagem selecinada na memória
HttpPostedFile img = arquivoUploadImagem.PostedFile;
//define os dados binários
img.InputStream.Read(imgbyte, 0, tamanho);
string descricaoImagem = txtDescricao.Text;
//abre uma conexão
SqlConnection connection = new SqlConnection(strcon);
connection.Open();
SqlCommand cmd = new SqlCommand("INSERT INTO Imagens (descricao,imagem) VALUES (@descricao,@imagem)", connection);
cmd.Parameters.Add("@descricao", SqlDbType.VarChar, 50).Value = descricaoImagem;
cmd.Parameters.Add("@imagem", SqlDbType.Image).Value = imgbyte;
int contador = cmd.ExecuteNonQuery();
connection.Close();
if (contador == 1)
{
VincularDados();
txtDescricao.Text = string.Empty;
ScriptManager.RegisterStartupScript(this, this.GetType(), "alertmessage", "javascript:alert('" + descricaoImagem + " imagem incluida com sucesso')", true);
}
}
}
O código acima inclui uma imagem na tabela Imagens e exibe uma
mensagem via JavaScript de alerta ao usuário avisando que a imagem foi
incluída.
O código da rotina VincularDados() é o seguinte:
private void VincularDados()
{
SqlConnection connection = new SqlConnection(strcon);
SqlCommand command = new SqlCommand("SELECT descricao,id from Imagens", connection);
SqlDataAdapter daimages = new SqlDataAdapter(command);
DataTable dt = new DataTable();
daimages.Fill(dt);
gdvImagens.DataSource = dt;
gdvImagens.DataBind();
gdvImagens.Attributes.Add("bordercolor", "black");
}
Nesse código, estamos recuperando as imagens da tabela Imagens e vinculando no controle GridView.
Após a conclusão do código acima, precisamos adicionar um arquivo
HttpHandler ao nosso projeto para recuperar imagens do banco de dados,
pois nós salvamos as imagens em formato binário, e obter as imagens no
formato binário é fácil, mas a exibição não é tão simples assim, e por
isso vamos usar um HttpHandler para resolver esse problema.
Aqui o HttpHandler é uma classe simples que lhe permite processar um
pedido e retornar uma resposta para o navegador. De forma simples, o
manipulador é responsável por atender solicitações do navegador. Ela só
pode lidar com uma solicitação por vez o que lhe dá um bom desempenho.
No menu Project, clique em Add new Item e a seguir selecione o
template Visual C# -> Web e Generic Handler, informando o nome
ImagemHandler.ashx e clique no botão Add.

A seguir inclua o código abaixo no arquivo ImagemHandler.ashx:
Neste código, incluímos a linha para obter a string de conexão do
arquivo web.config e definimos o código do evento ProcessRequest() para
obter e exibir a imagem:
using System;
using System.Web;
using System.Data.SqlClient;
using System.Configuration;
namespace Tratando_Imagens_SQLServer
{
public class ImagemHandler : IHttpHandler
{
string strcon = ConfigurationManager.ConnectionStrings["ConexaoSQLServer"].ConnectionString;
public void ProcessRequest(HttpContext context)
{
string imagemID = context.Request.QueryString["ImgID"];
SqlConnection connection = new SqlConnection(strcon);
connection.Open();
SqlCommand command = new SqlCommand("select imagem from Imagens where id=" + imagemID, connection);
SqlDataReader dr = command.ExecuteReader();
dr.Read();
context.Response.BinaryWrite((Byte[])dr[0]);
connection.Close();
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
Agora podemos executar o projeto e, ao acionar o link Imagens do menu
da página, poderemos incluir e exibir as imagens no controle Gridview,
conforme mostra a figura abaixo:


Após selecionar uma imagem e clicar no botão Enviar Arquivo, veremos uma mensagem indicando que imagem foi incluída com sucesso.
Pegue o projeto completo aqui: Tratando_Imagens_SQLServer.zip *** Artigo de José Carlos Marcoratti
|
Hoje vou mostrar como recuperar um valor de uma função definida
pelo usuário no SQL Server que retorna um valor escalar usando ADO .NET.
Para fazer isso, vamos criar a Function (Função) no SQL Server e
tratá-la como se fosse um procedimento armazenado. A partir do SQL
Server 2000 temos o recurso chamado Functions, que permite criar funções
para auxiliar na consulta e obtenção de informação.
Uma função definida pelo usuário é uma rotina Transact-SQL ou CLR
(Common Language Runtime) que aceita parâmetros, executa uma ação (como
um cálculo complexo) e retorna o resultado dessa ação como um valor. O
valor de retorno pode ser um valor escalar (único) ou uma tabela.
A criação de uma user function é similar à criação de uma stored
procedure ou uma view. Atualmente, temos a possibilidade de criar
funções dos seguintes tipos:
- Inline Function – São usadas para parametrizar views;
- Table-valued Function – Usada para lógicas complexas; retorna uma tabela;
- Scalar-valued Function – Retorna apenas um parâmetro; são semelhantes as funções pré-existentes no SQL Server(Ex: getDate())
Vamos, então, criar uma Scalar-valued Function e mostrar como podemos
tratar o seu retorno usando ADO .NET. Os recursos necessários usados
neste artigo foram:
- Visual Basic 2010 Express Edition;
- SQL Server 2008 Express;
- Banco de dados Northwind.mdf.
Abra o Visual Basic 2010 Express Edition e crie um novo projeto
(File-> New Project) do tipo Windows Forms Application com o nome de
SQLServer_FuncaoEscalar:

Agora vamos abrir a janela DataBase Explorer e exibir os objetos do
banco de dados Northwind.mdf. Depois clique com o botão direito sobre o
item Functions e selecione Add New -> Scalar-valued Function.

Será aberta uma janela com uma estrutura pronta para criarmos a nossa função:

Defina a função com o nome ValorEstoque, conforme mostra a figura a seguir:

Esta função calcula o valor do estoque para um produto multiplicando o
seu preço unitário pelo sua quantidade em estoque. Agora vamos usar a
instrução com um DataAdapter para preencher um DataTable com os cinco
primeiros registros da tabela Products do banco de dados Northwind.mdf.
Assim vamos obter o valor do estoque para cada registro usando a função
criada com o valor escalar.
Na janela Solution Explorer selecione o formulário form1 e a partir
da ToolBox vamos incluir os seguintes controles no formulário:
- DataGridView – name = gdvDados
- Button – btnExecutar
Conforme o leiaute abaixo:

No evento Click do botão Executar, vamos incluir o código abaixo:
Private Sub btnExecutar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExecutar.Click
Try
Dim sqlConnectString As String = "Data Source=.\SQLEXPRESS;Integrated security=SSPI;Initial Catalog=Northwind;"
'Dim sql1 As String = "SELECT TOP 5 *, " + "dbo.ValorProdutoEstoque(UnitPrice, UnitsinStock) as " + "ValorEstoque FROM Products"
Dim sql2 As String = "SELECT ProductID, ProductName, ValorEstoque=dbo.ValorEstoque(UnitPrice, UnitsInStock) FROM Products"
Dim da As New SqlDataAdapter(sql2, sqlConnectString)
Dim dt As New DataTable()
da.Fill(dt)
gdvDados.DataSource = dt
formatagrid()
Catch ex As Exception
MessageBox.Show("Erro : " + ex.Message)
End Try
End Sub
Estamos chamando a função na instrução SQL:
Dim sql2 As String = "SELECT ProductID, ProductName, ValorEstoque=dbo.ValorEstoque(UnitPrice, UnitsInStock) FROM Products"
Note que temos que informar o ower da function ao chamá-la, por isso
usamos dbo.ValorEstoque(UnitPrice, UnitsInStock). Se você chamar
ValorEstoque(UnitPrice, UnitsInStock) não vai funcionar.
A rotina formatagrid() tem o seguinte código e é usada para formatar o controle datagridview:
Private Sub formatagrid()
With gdvDados
'.AutoGenerateColumns = True
.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders
.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single
'altera a cor das linhas alternadas no grid
.RowsDefaultCellStyle.BackColor = Color.White
.AlternatingRowsDefaultCellStyle.BackColor = Color.Aquamarine
'altera o nome das colunas
.Columns(0).HeaderText = "Código"
.Columns(1).HeaderText = "Produto"
.Columns(2).HeaderText = "Valor do Estoque"
.Columns(0).Width = 50
.Columns(1).Width = 300
.Columns(2).Width = 200
'esconde a coluna
.Columns("ProductID").Visible = False
'formata as colunas valor, vencimento e pagamento
.Columns(2).DefaultCellStyle.Format = "c"
'seleciona a linha inteira
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
'não permite seleção de multiplas linhas
.MultiSelect = False
' exibe nulos formatados
.DefaultCellStyle.NullValue = " - "
'permite que o texto maior que célula não seja truncado
.DefaultCellStyle.WrapMode = DataGridViewTriState.True
'define o alinhamamento
.Columns("ValorEstoque").DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
End With
End Sub
Executando o projeto iremos obter:

Percebeu como é fácil criar e utilizar uma função definida pelo
usuário (FUNCTION) no SQL Server? Você pode criar Functions para obter
informações e realizar operações.
Mas qual a vantagem das Functions sobre os Procedimentos armazenados?
Uma das vantagens de funções definidas pelo usuário sobre os
procedimentos armazenados, é o fato de que uma UDF pode ser usada em
instruções Select, Where ou em uma declaração Case.
Elas também podem ser usadas para criar associações (Joins). Além
disso, funções definidas pelo usuário são mais simples para invocar do
que procedimentos armazenados de dentro de outra instrução SQL.
Pegue o projeto completo aqui: SQLServer_FuncaoEscalar.zip
|
Tudo o que fazemos em nossas vidas envolve
processos; desde levantar de manhã a fazer um churrasco com os amigos,
fazer uma viagem, abastecer o carro a caminho do trabalho... Se preciso
começar a estudar às 19h, mas sempre chego às 19h30, então preciso
entender e analisar os processos que sigo (incluindo métricas, como
tempo perdido, tempo de locomoção, trabalho além do horário etc.) antes
que eu possa fazer melhorias que garantam que eu vá chegar aonde preciso
na hora prevista.
Definições de processo
Um processo trata de uma série de ações, passos ou procedimentos que
conduzem a um resultado. Em alto nível, é uma sequência ou fluxo de
tarefas realizadas durante uma produção, ou a entrega de um serviço.
Processo pode significar uma atividade de alto, ou de baixo nível em uma organização.
É uma técnica que normalmente utiliza diagramas (fluxogramas) para
documentar o entendimento dos processos atuais de uma área de negócio.
Um modelo de processo identifica as atividades essenciais do negócio
que existem dentro de uma organização. Um modelo inclui descrição,
diagrama textual, métricas e outras informações de apoio.
- Modelagem de processos de gestão:
É um método para a criação de melhores processos que possibilitem melhorar o desempenho organizacional.
Existem muitas técnicas de modelagem que ajudam a compreender os
processos de negócio. A maioria delas tem sido usada há muitos anos e,
surpreendentemente, ainda funciona excepcionalmente bem.
Para que se tenha um pouco de referência da história recente
relacionada à modelagem de processos de negócio, é preciso ter em mente
que existem vários símbolos e formas que podem ser usados para criar
diagramas. Por exemplo, a abordagem inicial de diagramas de fluxo de
trabalho foi recomendada pelo American National Standards Institute
(ANSI) em 1970; e ela ainda é amplamente aceita e utilizada. Mais
recentemente, uma nova abordagem para a criação de diagramas de fluxo de
trabalho foi denominada de Notação de Modelagem de Processos de Negócio
(BPMN – Business Process Management Notation). Essa atualização foi
definida pela BPMI – Business Process Management Iniciative.
O BPMI é um consórcio de empresas
fornecedoras e usuárias de BPM que trabalham em conjunto para
desenvolver uma linguagem comum (BPML), uma notação padronizada para
essa linguagem (BPMN) e uma linguagem de consulta (BPQL). Tem-se a ideia
de que as empresas devem modelar seus processos de forma mais
automatizada e também que elas sejam capazes de monitorar e alterar
esses processos de acordo com suas necessidades e especificidades.
Anos atrás, ainda em crescente evolução e aplicação dos conceitos, o
BPMI fundiu-se com OMG – Object Management Group, com o objetivo de
manter padrões da UML - Unified Modeling Language - que são um pouco mais específicos, mas ainda sim muito utilizados.
Abaixo destacaremos importantes lições baseadas em técnicas de
mercado que certamente contribuirão com a modelagem de processos em sua
organização.
- Diagramas de fluxo de trabalho
Os diagramas de fluxo de trabalho são muito utilizados para entender a
situação atual (AS-IS) e a situação futura desejada (TO-BE) das
organizações. Servem como uma análise de eventuais lacunas entre como a
organização trabalha atualmente e como deve trabalhar no futuro,
sinalizando os pontos que precisam ser melhorados para que possamos
alcançar efetividade na melhoria de processos de negócio.
Trata-se de técnicas de modelagem um tanto antigas, mas também são
muito populares e fáceis de usar. Esses diagramas são úteis para mostrar
como o trabalho flui entre as camadas e os departamentos da organização
e entre os diferentes papéis e responsabilidades das pessoas envolvidas
nos processos de negócio.
Esses diagramas mostram como o trabalho é realizado, incluindo a
sequência em que as tarefas são realizadas e por quem elas devem ser
realizadas - incluindo pessoas, agentes externos ou sistemas. A
simplicidade do diagrama de fluxo de trabalho pode ser um perigo se ele
não for uma representação verdadeira da realidade de uma empresa, e isso
significa que a responsabilidade de quem está realizando a análise de
negócios é grande.
Figura 1: Diagrama de Fluxo de Trabalho para o processo “Aprovação de Pagamentos”.
Um diagrama de decomposição mostra as funções essenciais do negócio
de uma organização sem mostrar qualquer sequência ou relações entre
elas. A decomposição é uma abordagem comprovada para quebrar uma
organização ou sistema complexo em partes gerenciáveis e discretas, que
são mais fáceis de entender para muitas pessoas. É normalmente utilizado
para apresentar muitos pontos de vista diferentes do mesmo negócio ou
sistema.
No planejamento estratégico, um diagrama de decomposição é usado para
decompor metas de alto nível das empresas em níveis inferiores e/ou
metas por departamentos. Um diagrama de decomposição pode ser usado,
também, como um quadro para definir funcionalidades necessárias para um
novo sistema.
Existem algumas regras para a construção de um diagrama de
decomposição que garantem a sua consistência e precisão. Um bom analista
de negócios deve ter a capacidade de estruturar corretamente as
informações da organização. Quando construído corretamente, o diagrama
de decomposição é um modelo duradouro de negócio que pode ser refinado e
reutilizado especialmente quando se reflete com precisão os processos
de negócios reais.
 Figura 2: Diagrama de decomposição para sistema de informação.
Embora o diagrama de caso de uso tenha sido criado como uma
ferramenta de design de software, ele foi também aceito por analistas de
negócios como uma importante ferramenta para mostrar informações não
técnicas pertinentes ao negócio. Nessas situações, eles são geralmente
denominados "casos de uso de negócios".
Esses diagramas são uma técnica criada nos anos 1980 para mostrar os
requisitos funcionais de um sistema a partir da perspectiva de seus
usuários, que são chamados de atores, e o diagrama demonstra como esses
usuários interagem com o sistema. É uma técnica útil especialmente para
desenvolvimento de sistemas, pois auxilia na definição do ambiente e dos
requisitos necessários para gerarmos a solução.
Figura 3: Exemplo de diagrama de caso de uso.
Um diagrama de caso de uso é utilizado para identificar atores e
casos de uso necessários para uma solução, mas não descreve a informação
necessária para entender o que está acontecendo dentro do caso de uso.
Portanto, um diagrama de caso de uso deve ser apoiado por uma descrição
que contenha todos os componentes e as etapas sequenciais que mostram
como o sistema e os atores interagem para atingir o objetivo de negócio.
A descrição de caso de uso inclui pré-condições, pós-condições,
caminhos de processamento primário, caminhos alternativos que mostram o
processamento de exceção e as condições de erro, a ação do ator e a
forma como o sistema deve responder. Incluem também protótipos de tela,
requisitos de dados, juntamente com as regras de negócio, resultados de
produção, a comunicação com os clientes e mensagens de erro.
Como a maioria das técnicas de análise, os casos de uso parecem muito
mais simples do que de fato são. Contudo, essa é uma ótima técnica para
usar com os executivos e tomadores de decisão, porque requer decisões
sobre como as pessoas irão trabalhar com o sistema.
- Diagramas de entidade relacionamento (DER)
É considerado pelos profissionais de análise de negócios uma das
ferramentas mais importantes quando é necessário compreender a
complexidade dos processos de negócio de uma organização ou sistema,
pois através deste diagrama é possível compreender visualmente as
informações exigidas pela empresa para gerenciar suas operações de
negócio e tomar decisões.
Ele auxilia na modelagem de informações de negócio em um nível
conceitual e lógico, criando uma visualização de requisitos de
informação de negócio.
Especialistas afirmam que, se usarmos diagramas de entidade
relacionamento conjuntamente com diagrama de fluxo de trabalho,
obteremos uma excelente noção geral do negócio como um todo, o que
compreende a complexidade do negócio.
 Figura 4: Exemplo básico de um diagrama de entidade relacionamento.
A partir dessas noções integradas dos processos, é possível
visualizar pontos onde há desafios e oportunidades de melhoria, tais
como:
- Problemas com a integração das suas informações das áreas;
- Oportunidade de unificar dados redundantes em um banco de dados;
- Oportunidade de unificar informações duplicadas de diferentes sistemas;
- Definição de padrões que não estejam claros em toda a organização.
É dentro desse contexto que a modelagem de dados promove mudanças
culturais e aumenta a experiência e a maturidade dos processos. Essas
mudanças vão requerer que as pessoas articulem e compreendam todos os
aspectos do seu negócio. Elas auxiliam, também, no entendimento entre os
domínios de negócios e eliminam a duplicidade de informações.
Os diagramas de entidade relacionamento são uma técnica excelente,
pois ajudam o analista a entender o negócio a partir de perspectivas
diferentes e são muito úteis quando se investigam soluções complexas.
Compreender as necessidades de dados de negócios é crucial para qualquer
mudança que seja necessária aplicar, pois certamente determinará os
impactos de uma mudança nas várias áreas que são atendidas por esse
processo.
 Figura 5: Exemplo de diagrama de entidade relacionamento.
Esta é uma técnica antiga de diagramação usada pelos analistas quando
se trabalha com as partes interessadas (stakeholders). São essas as
partes que devem responder a diversas questões e articular claramente
que parte do negócio deve ser examinada.
Um diagrama de contexto é frequentemente usado por analistas no
início do projeto e é uma ótima técnica para começar a usar o consenso
das partes interessadas sobre a área de negócio a ser investigada.
Também ajuda o analista a fazer perguntas significativas e por isso pode
descobrir complexidades ocultas que não estavam claras até aquele
momento e determinar o impacto que poderia ser causado sobre o projeto,
podendo até mesmo colocá-lo em risco.
O diagrama de contexto é simples de usar e, devido à sua
simplicidade, é uma técnica bem sucedida. O verdadeiro valor da técnica
está no desenvolvimento do diagrama, fazendo boas perguntas sobre quem é
afetado pelo projeto e quais informações devem ser fornecidas ou
recebidas pela área de negócio. O escopo do projeto definido pelo
patrocinador pode nunca ter considerado algumas especificidades que
serão expostas através da técnica de diagrama de contexto.
 Figura 6: Exemplo de diagrama de contexto.
Ao analisar uma área de negócio, é importante compreender os eventos
que desencadeiam o início do trabalho para poder criar um diagrama da
área de negócio em questão. Um evento é geralmente algo que acontece
fora da área de negócio e que demanda respostas, que podem ser dadas de
diversas maneiras. Há três tipos comuns de eventos. São eles:
- Eventos externos acionados por clientes, fornecedores, legislação etc.;
- Eventos temporais desencadeados de tempos em tempos, tais como
relatórios de final de mês, análises anuais, como definição de
orçamento etc.;
- Eventos internos acionados por regras de negócios,
conformidades legais etc., tais como quando um cliente exige um padrão
de qualidade.
 Figura 7: Exemplo de diagrama de evento.
Histórias de usuários são uma técnica usada para apoiar os casos de
uso. Elas são criadas por usuários e descrevem o que o sistema precisa
fazer para a execução de um caso de uso. Analistas coletam as histórias
de usuários escritas em cartões onde sintetizam as expectativas dos
usuários e apóiam a comunicação de casos de uso para a equipe de
desenvolvimento de TI. É uma ótima técnica para usar quando os usuários
estão geograficamente distantes.
Simples, claras e com breves descrições de funcionalidades que são
valiosas para os usuários – assim devem ser as histórias de usuários.
Criar e manter um conjunto de histórias de usuários escritas em cartões
de 150 x 100 mm ajuda a descrever como a equipe de desenvolvimento deve
trabalhar com as histórias de usuários.
Figura 8: Exemplo de história de usuário escrita em cartão.
Conclusão
Definir as técnicas de análise e os padrões é uma tarefa árdua, e a
maioria das organizações não compreende a análise de negócios como
suficiente para apreciar com flexibilidade as habilidades que um
profissional de análise de negócios precisa ter.
Os projetos variam muito e as análises diferem em perspectiva,
quantidade e nível de detalhe. Exigir um padrão de notação particular ou
uma modelagem pode parecer uma boa maneira de introduzir consistência
na organização.
Em vez de organizações que empregam centenas de pessoas para realizar
análises de negócios, as organizações devem empregar dezenas de
excelentes profissionais de análise de negócios que tenham domínio de
notações de modelagem diferentes, que tenham domínio da arte de
trabalhar com as partes interessadas, que tenham domínio da arte da
comunicação em todos os níveis da organização, que tenham a capacidade e
a habilidade de usar diferentes estruturas e que usem ferramentas para
organizar e representar os componentes da organização com precisão.
Com base nessas ações, as organizações tendem a receber muito bem as
ações de modelagem de processos de negócio, e seus impactos na
organização passam a ser os mais benéficos possíveis, pois dá a
visibilidade necessária para as etapas seguintes à modelagem, onde serão
almejadas as mudanças consistentes de curto e longo prazo que farão a
organização emergir no mercado com mais força, com processos
corporativos padronizados, com ganho expressivo de produtividade e
eficiência, além de garantir medições, análises e aperfeiçoamento da
gestão estratégica.
|
Nem sempre você vai precisar de um banco de dados para guardar
informações. Os bancos de dados relacionais são a melhor opção quando o
objetivo é armazenar e recuperar informações, mas apresentam diversos
problemas. Se o seu caso não requer a utilização de um banco de dados,
considere armazenar informações em arquivos XML. As perspectivas de XML para armazenamento de dados são surpreendentes e até mesmo os Data WareHouses
já estão armazenando informações no formato XML. Como o objetivo
principal de armazéns de dados é armazenar dados não-operacionais a
longo prazo, ou seja, para trocá-los ao longo do tempo, as razões
fundamentais para o sucesso esmagador do XML como um formato de troca
também esperam por data warehouses.
Um data warehouse
(ou armazém de dados, ou depósito de dados no Brasil) é um sistema de
computação utilizado para armazenar informações relativas às atividades
de uma organização em bancos de dados, de forma consolidada. O desenho
da base de dados favorece os relatórios, a análise de grandes volumes de
dados e a obtenção de informações estratégicas que podem facilitar a
tomada de decisão.
Se pensarmos que a plataforma .NET oferece diversos recursos para que
possamos tratar informações no formato XML, de forma rápida e
descomplicada, temos aí um motivo a mais para pensarmos na utilização do
formato XML quando realmente indicado.
Neste artigo, eu vou mostrar como criar uma aplicação usando a
linguagem C# que realiza o gerenciamento de informações sobre alunos,
incluindo a foto, persistindo e recuperando as informações de um arquivo
XML. É uma aplicação simples, mas meu objetivo é mostrar o potencial
que tem esse recurso na plataforma .NET.
No exemplo deste artigo, eu vou armazenar as seguintes informações sobre os alunos:
- Código
- Nome
- Curso
- Mensalidade
- Foto
Irei utilizar o arquivo Alunos.xml para armazenar as informações dos alunos. Esse arquivo possui a seguinte estrutura:
<?xml version="1.0" standalone="yes"?> <alunos> <aluno> <codigo>10</codigo> <nome>Jimmi Hendrix</nome> <curso>Musica</curso> <mensalidade>3500</mensalidade> <foto>10)hendrix.jpg</foto> </aluno> </alunos>
As fotos dos alunos serão armazenadas em uma pasta do projeto chamada Dados
juntamente com o arquivo xml. Para evitar que existam nomes de fotos
duplicadas (esse é um dos problemas de usar essa solução), eu vou sempre
concatenar o código do aluno mais o caractere cerquilha (#) com o nome
da foto. Dessa forma, sempre teremos um nome único para a foto.
Para criar o projeto deste artigo, eu vou usar o Visual C# 2008 Express Edition e, antes de iniciar o projeto, vou mostrar a aparência que terá a nossa aplicação na figura abaixo:

Agora vamos ao que
interessa...
Criando a aplicação Windows Forms no Vsual C# 2008 Express Edition
Abra o Visual C# 2008 Express e crie um novo projeto do tipo Windows Forms Application no menu File->New Project -> Windows Forms Application com o nome CadastroAlunos.
No formulário form1.cs, vamos incluir os controles a partir da ToolBox conforme o layout da figura abaixo:

- 1 DataGridView
- gdvAlunos
- 4 TextBox :
txtCodigo, txtNome, txtCurso, txtMensalidade,
picFoto
- 11 Buttons
assim designados:
01. Buttons para
movimentação dos registros:
- btnPrimeiro
- btnAnterior
- btnProximo
- btnUltimo
02. Botões para
operações de manutenção de dados:
- btnInlcuir
- btnProcurar
- btnAtualizar
- btnDeletar
- btnLimpar
- btnCarregaXML
- btnSair
- btnLocalizarFoto
- 1 Contrrole
PictureBox - picFoto
Além disso, vamos usar dois
controles OpenFileDialog: ofd1 e ofd2. Após incluir os controles
acima e definir o nome de cada um conforme indicado, defina os
controles conforme o layout acima. A seguir, vamos definir os
namespaces usados no projeto no início do formulário form1.cs:
using System; using System.Data; using System.Drawing; using System.Windows.Forms; using Microsoft.VisualBasic; using System.IO;
Feito isso, vamos definir as
variáveis que serão usadas no projeto:
//define variáveis usadas no projeto DataSet ds; string fcaminho; string fdiretorio; string pcaminho; string pnome; string pdestino; int reg = 0; DataRow linharegistro;
Vou começar definindo o
código do botão de comando Carregar Arquivo XML.
Ao clicar no botão, será
aberta uma janela de diálogo OpenFileDialog
para que seja possível selecionar o arquivo XML que desejamos
carregar e exibir no controle DataGridView - gdvAlunos. O código
é visto abaixo:
private void btnCarregaXML_Click(object sender, EventArgs e) { try { ofd1.Filter = "xml|*.xml|all files|*.*"; DialogResult res = ofd1.ShowDialog(); if (res == DialogResult.OK) { gdvAlunos.DataSource = null; btnLimpar.PerformClick(); fcaminho = ofd1.FileName; ds = new DataSet(); ds.ReadXml(fcaminho); //definindo a chave primaria a fim de procurar o registro usando o método find ds.Tables[0].Constraints.Add("pk_codigo", ds.Tables[0].Columns[0], true); gdvAlunos.DataSource = ds.Tables[0]; fdiretorio = fcaminho.Substring(0, fcaminho.LastIndexOf("\\") + 1); mostrarDados(); } } catch(Exception ex) { MessageBox.Show("Informação inválida : " + ex.Message, "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); } }
Se um arquivo for
selecionado, então faremos o seguinte:
- Limpamos os controles do
formulário: btnLimpar.PerformClick();
- Obtemos o caminho e o nome do
arquivo selecionado: fcaminho = ofd1.FileName;
- Criamos um dataset e, usando o
método ReadXml(fcaminho),
lemos o conteúdo do arquivo XML
para o dataset;
- Definimos uma chave
primária na tabela a fim de procurar o registro usando o
método Find;
O
método Find da coleção Rows retorna um objeto DataRow,
e, nesse caso, uma única linha e não um array de
linhas. Esse método precisa que você defina a propriedade chave
primária (Primary Key) antes de usá-lo. Se você não
fizer isso, vai obter uma exceção.
- Chamamos a rotina mostrarDados()
para exibir os dados no DataGridView.
Vejamos a seguir o
código da rotina mostrarDados():
void mostrarDados() { if (ds.Tables[0].Rows.Count > 0) { picFoto.Image = null; txtCodigo.Text = ds.Tables[0].Rows[reg][0].ToString(); txtNome.Text = ds.Tables[0].Rows[reg][1].ToString(); txtCurso.Text = ds.Tables[0].Rows[reg][2].ToString(); txtMensalidade.Text = ds.Tables[0].Rows[reg][3].ToString(); picFoto.ImageLocation = fdiretorio + ds.Tables[0].Rows[reg][4].ToString(); } else MessageBox.Show("Não existem registros.","Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); }
Este código verifica se
existem linhas na tabela:
if(ds.Tables[0].Rows.Count > 0)
Em caso positivo, exibe os dados nos
controles do formulário. Estamos usando um dataset não tipado, no qual temos que definir a posição do registro na tabela do
dataset da seguinte forma:
ds.Tables[0].Rows[reg][0].ToString()
- ds - o
dataset
- ds.Tables[0]
- a primeira tabela do dataset (só existe uma
mesmo)
- ds.Tables[0].Rows[reg][n]
- campo de índice igual a n existente na linha
(Rows)
A rotina mostrarDados()
não retorna nada, por isso o modificador void.
Ela será usada sempre que desejamos exibir informações nos
controles do formulário.
Vejamos agora o código do
botão Incluir que deverá incluir um novo aluno no arquivo XML:
private void btnIncluir_Click(object sender, EventArgs e) { linharegistro = null; linharegistro = ds.Tables[0].Rows.Find(txtCodigo.Text); if (linharegistro == null) { //atribui os valores dos controles ao datarow linharegistro = ds.Tables[0].NewRow(); linharegistro[0] = txtCodigo.Text; linharegistro[1] = txtNome.Text; linharegistro[2] = txtCurso.Text; linharegistro[3] = txtMensalidade.Text;
salvaFoto(); linharegistro[4] = pnome; //inclui uma linha na tabela ds.Tables[0].Rows.Add(linharegistro); reg = ds.Tables[0].Rows.IndexOf(linharegistro); //salva dados no arquivo xml ds.WriteXml(fcaminho); MessageBox.Show("Registro incluído com sucesso.", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); } else MessageBox.Show("Registro já existe.O código deve ser único.","Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); }
Verificamos se o registro
já existe usando o método Find: linharegistro =
ds.Tables[0].Rows.Find(txtCodigo.Text).
Em caso positivo, criamos uma nova
linha(NewRow) e atribuímos os valores informados
no TextBox à nova linha. Chamamos a rotina SalvaFoto()
e incluímos a nova linha na tabela e, em seguida, gravamos os dados
no arquivo XML usando o método ds.WriteXml().
A rotina SalvaFoto()
tem seu código exibido a seguir:
void salvaFoto() { //Procurando o nome da foto //salvando na pasta do arquivo xml com nome unico (codigo+nome_foto) pcaminho = picFoto.ImageLocation; pnome = txtCodigo.Text + "#" + (pcaminho.Substring(pcaminho.LastIndexOf('\\') + 1));//(codigo + nome da foto) pdestino = fdiretorio + pnome; picFoto.Image.Save(pdestino);//salva imagem no disco }
Neste código, atribuímos o
caminho da foto à variável pcaminho e montamos o nome da foto
com o código do aluno mais o caractere # e o nome da foto. Montamos o diretório de
destino e salvamos a foto no disco. No botão Procurar,
temos o código que localiza um registro e exibe as informações
no formulário:
private void btnProcurar_Click(object sender, EventArgs e) {
int n = Convert.ToInt32(Interaction.InputBox("Informe o código do aluno :", "Procurar", "10", 200, 200)); //procurando registros usando o método find linharegistro = null; linharegistro = ds.Tables[0].Rows.Find(n); if (linharegistro != null) { //preenche os controles do formulário reg = ds.Tables[0].Rows.IndexOf(linharegistro); txtCodigo.Text = linharegistro[0].ToString(); txtNome.Text = linharegistro[1].ToString(); txtCurso.Text = linharegistro[2].ToString(); txtMensalidade.Text = linharegistro[3].ToString(); picFoto.ImageLocation = fdiretorio + linharegistro[4]; } else MessageBox.Show("registro não localizado.", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
}
Solicitamos o código do
aluno usando o InputBox e novamente usamos o
método Find para localizar o registro. O código do botão Atualizar
que altera os dados do arquivo XML:
private void btnAtualizar_Click(object sender, EventArgs e) { //procurando registros usando o método find DataRow linharegistro = ds.Tables[0].Rows.Find(txtCodigo.Text); if (linharegistro!= null) { reg = ds.Tables[0].Rows.IndexOf(linharegistro); //atribui os valores dos controles aos campos da tabela ds.Tables[0].Rows[reg][0] = txtCodigo.Text; ds.Tables[0].Rows[reg][1] = txtNome.Text; ds.Tables[0].Rows[reg][2] = txtCurso.Text; ds.Tables[0].Rows[reg][3] = txtMensalidade.Text;
File.Delete(fdiretorio + linharegistro[4]); salvaFoto();
ds.Tables[0].Rows[reg][4] = pnome; //grava no arquivo xml ds.WriteXml(fcaminho); MessageBox.Show("registro atualizado", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); } else MessageBox.Show("Não existe registro de aluno com este código.", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); }
Localizamos o item usando o método Find e
atribuímos os valores informados nas caixas de texto às linhas da tabela,
salvamos a foto e gravamos as alterações no arquivo XML. A rotina para excluir uma linha do arquivo é vista
no código a seguir:
private void btnDeletar_Click(object sender, EventArgs e) { //procurando registros usando o método find DataRow linharegistro = ds.Tables[0].Rows.Find(txtCodigo.Text); if (linharegistro!= null) { File.Delete(fdiretorio + linharegistro[4]); ds.Tables[0].Rows.Remove(linharegistro); ds.WriteXml(ofd1.FileName); MessageBox.Show("Registro deletado.", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); reg = 0; mostrarDados(); } else MessageBox.Show("Não existe registro de aluno com este código.", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); }
Localizamos o item usando o método Find e
usando método Remove excluímos a linha da tabela. O código de cada um dos botões de navegação é
mostrado a seguir:
private void btnPrimeiro_Click(object sender, EventArgs e) { reg = 0; mostrarDados(); }
private void btnAnterior_Click(object sender, EventArgs e) { if (reg > 0) { reg--; mostrarDados(); } else { MessageBox.Show("Primeiro Registro."); } }
private void btnProximo_Click(object sender, EventArgs e) { if (reg < ds.Tables[0].Rows.Count - 1) { reg++; mostrarDados(); } else { MessageBox.Show("Último Registro."); } }
private void btnUltimo_Click(object sender, EventArgs e) { reg = ds.Tables[0].Rows.Count - 1; mostrarDados(); }
Verificamos a posição do registro e usamos a rotina
mostraDados para exibir os dados atuais. O código do botão Limpar é dado a seguir:
private void btnLimpar_Click(object sender, EventArgs e) { //limpa controles TextBox do formulário e o picturebox txtCodigo.Text = txtNome.Text = txtCurso.Text = txtMensalidade.Text = ""; picFoto.Image = null; }
Também incluímos o código abaixo no evento
CellClick do DataGridView.
private void gdvAlunos_CellClick(object sender, DataGridViewCellEventArgs e) { try { //obtem o valor da primeira célula do grid que é o código do aluno int codigo = Convert.ToInt32(gdvAlunos.CurrentRow.Cells[0].Value); linharegistro = ds.Tables[0].Rows.Find(codigo); if (linharegistro != null) { //preenche os controles do formulário reg = ds.Tables[0].Rows.IndexOf(linharegistro); txtCodigo.Text = linharegistro[0].ToString(); txtNome.Text = linharegistro[1].ToString(); txtCurso.Text = linharegistro[2].ToString(); txtMensalidade.Text = linharegistro[3].ToString(); picFoto.ImageLocation = fdiretorio + linharegistro[4]; } else MessageBox.Show("registro não localizado.", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); } catch { } }
Dessa forma, quando uma linha do grid for clicada,
obtemos os valores da linha e exibimos no formulário. Para encerrar, temos o código do botão que encerra a
aplicação:
private void btnSair_Click(object sender, EventArgs e) { DialogResult resultado = MessageBox.Show("Deseja Encerrar a aplicação?", "Sair", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (resultado == DialogResult.Yes) Application.Exit(); }
Com isso, mostramos que podemos ter informações armazenadas em arquivos XML e
que podemos tratá-las de forma dinâmica e funcional com os recursos da linguagem
C#.
Simples, simples assim. Pegue o projeto completo aqui: CadastroXML.zip.
Eu sei, é apenas XML, mas
eu gosto...
artigo publicado originalmente no iMasters, por José Carlos Macoratti
|
Sites como o Facebook e o Orkut usam um efeito muito interessante de
carregamento de conteúdo de acordo com a posição da barra de rolagem. O
site carrega apenas uma parte dos dados e, à medida que o usuário vai descendo a
barra de rolagem, o site se encarrega de pegar mais dados no servidor
para exibir.
O efeito é não é complicado de fazer, além de ser muito
útil, pois o servidor não precisará carregar todos os dados de uma só
vez. Para fazer isso, utilizaremos o JQuery.
Vamos utilizar o código HTML abaixo, os estilos foram colocados direto no código apenas para fins didáticos, não façam isso.
<html> <head> <title>yLog Scroll Tutorial</title> </head> <body> <div id="content" style="width:120; height:100px; overflow-y:scroll;"> <ul style="position: relative;"> <li>item 1</li> <li>item 2</li> <li>item 3</li> <li>item 4</li> <li>item 5</li> <li>item 6</li> <li>item 7</li> <li>item 8</li> <li>item 9</li> <li>item 10</li> </ul> </div> </body> </html>
Ao abrir esse HTML no navegador,
aparecerá uma lista de itens com uma barra de rolagem. O que queremos é
que, ao rolar a barra até o fim, novos itens apareçam. Para carregar
conteúdo dessa forma, usa-se AJAX, nada muito complicado, mas a maior
dúvida é como saber se a barra chegou ao final.
Primeiro importe o JQuery, adicione a
linha abaixo entre as tags <head></head>. É uma boa prática
importá-lo direto do Google.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
Existe um evento chamado "scroll",
nome mais óbvio impossível. Vamos usá-lo para fazer algo quando a
barra for rolada. Adicione esse código logo abaixo da linha que importa o
JQuery.
<script> $(document).ready(function() { $("#content").scroll(function() { //fazer algo aqui }); }); </script>
Com os métodos scrollTop() e
height(), é possível saber o quanto foi rolado e a altura da div, mas
essa não é a altura total, ela é a altura apenas do que está sendo
exibido. Para saber o tamanho total da div, é necessário usar a
propriedade .scrollHeight. Com esses três valores, é possível fazer o
cálculo para saber se a rolagem chegou ao fim.
O quanto foi rolado,
somado à altura de exibição da div, será igual ao tamanho total da div
quando a barra de rolagem chegar ao final.
No código, isso seria:
$(this).scrollTop() + $(this).height() == $(this).get(0).scrollHeight.
Atualizando nosso script:
<script> $(document).ready(function() { $("#content").scroll(function() { if ($(this).scrollTop() + $(this).height() == $(this).get(0).scrollHeight) { // a rolagem chegou ao fim, fazer algo aqui. } }); }); </script>
Dentro do if você só precisa usar AJAX para pegar os dados do servidor. Ficaria algo mais ou menos assim:
<script> $(document).ready(function() { $("#content").scroll(function() { if ($(this).scrollTop() + $(this).height() == $(this).get(0).scrollHeight) { $.ajax({ type: "post", url: "/maisitems/", success: function(data) { //manipula os dados $("#content ul").append("<li>" + item + "</li>"); }, error: function() { } }); } }); }); </script>
O código completo do HTML + Javascript fica assim:
<html> <head> <title>yLog Scroll Tutorial</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script> <script> $(document).ready(function() { $("#content").scroll(function() { if ($(this).scrollTop() + $(this).height() == $(this).get(0).scrollHeight) { console.log("fim"); $("#content ul").append("<li>item x</li>");
$.ajax({ type: "post", url: "/maisitems/", success: function(data) { //manipula os dados $("#content ul").append("<li>" + item + "</li>"); }, error: function() { } }); } }); }); </script> </head> <body> <div id="content" style="width:120; height:100px; overflow-y:scroll;"> <ul style="position: relative;"> <li>item 1</li> <li>item 2</li> <li>item 3</li> <li>item 4</li> <li>item 5</li> <li>item 6</li> <li>item 7</li> <li>item 8</li> <li>item 9</li> <li>item 10</li> </ul> </div> </body> </html>
Espero que tenham gostado dessa dica. Se necessário, gravem esse código final, ele pode ser útil.
artigo publicado originalmente no iMasters, por Yuri Malheiros
|
Confira uma forma bem resumida de como criar uma
aplicação ASP .NET em 3 camadas usando a linguagem C#. Acompanhe cada
etapa e deixe suas impressões ao final do artigo.
O significa criar uma aplicação em camadas?
Quando acessa a página do seu banco na internet, você está usando uma
aplicação que possui uma tela de apresentação, na qual o usuário recebe
e entra com as informações.
- Quando você faz o login na sua conta acessando a página do seu
banco na internet, existe uma interface na qual você informa seu login e
senha.
- Quando você submete essa informação, a aplicação aplica as regras de negócios para verificar se seu login e senha são válidos.
- Para isso, a aplicação consulta um cadastro de informações, que está
em um banco de dados, e verifica se o que o usuário digitou corresponde
ao que está no cadastro.
Com esse exemplo bem simples, podemos perceber que temos três partes distintas atuando:
- A interface representada pela tela de login solicitando login e senha.
- As regras de validação que serão aplicadas representando as regras de negócio.
- As informações armazenadas no cadastro representando o banco de dados.
A figura abaixo procura mostrar de forma resumida esses três componentes, identificando e nomeando cada um deles.

Podemos identificar as seguintes camadas:
- Camada de Apresentação (Presentation Tier)
- Camada de Negócios (Business Logic Tier)
- Camada de Acesso a dados (Data Tier)
Embora para o cliente tudo seja apenas uma única aplicação, para o
desenvolvedor criar uma aplicação em camadas significa desenvolver
separadamente cada um dos componentes identificados no exemplo acima de
forma a facilitar a manutenção e a ganhar produtividade.
Chama-se a isso uma aplicação com arquitetura em três camadas. Lembrando que podemos ter aplicações em n-camadas. Resumindo:
A arquitetura em três camadas é uma arquitetura cliente
servidor na qual a interface do usuário, os processos de negócios e o
armazenamento de dados são desenvolvidos e mantidos em módulos
independentes, ou em plataforma separadas.
Basicamente existem três camadas:
- Camada de apresentação: User Interface (UI)
- Camada de Negócios: Business Logic Layer (BLL)
- Camada de Acesso a dados: Data Access Layer (DAL)
Cada camada pode ser desenvolvida e testada separadamente. Para a
nossa aplicação ASP .NET, podemos resumir a arquitetura em três camadas
da seguinte forma:

- A camada de apresentação contém os elementos da interface do
usuário do site e acrescenta toda a lógica que inclui a interação entre o
visitante e as regras de negócio. (ASP .NET Web Forms, Users Controls e
Master Pages)
- A camada de negócio (BLL) recebe a requisição da camada de
apresentação e retorna o resultado dependendo da lógica de negócio.
(Classes C#)
- A camada de acesso a dados contém as classes que acessam o banco de
dados e retornam o resultado a camada de negócio. (Classes C#)
Criando a aplicação ASP .NET em três camadas
Definindo o banco de dados, a tabela e a stored procedure
Em nosso exemplo, iremos criar uma aplicação ASP .NET para gerenciar as informações de clientes existentes na tabela Clientes do banco de dados Macoratti.mdf do SQL Server. O script para gerar o banco de dados Macoratti.mdf e a tabela Clientes é apresentado abaixo:
CREATE DATABASE [Macoratti] ON PRIMARY ( NAME = N'Macoratti', FILENAME = N'c:Program FilesMicrosoft SQL ServerMSSQL10.SQLEXPRESSMSSQLDATAMacoratti.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ) LOG ON ( NAME = N'Macoratti_log', FILENAME = N'c:Program FilesMicrosoft SQL ServerMSSQL10.SQLEXPRESSMSSQLDATAMacoratti_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%) GO
USE [Macoratti] GO
CREATE TABLE [dbo].[Clientes]( [id] [int] IDENTITY(1,1) NOT NULL, [nome] [nvarchar](50) NULL, [email] [nvarchar](150) NULL, [nascimento] [date] NULL, CONSTRAINT [PK_Clientes] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
GO
Se você desejar incluir dados na tabela Clientes usando o SQL Server Management Studio, pode usar o seguinte script:
INSERT INTO [Macoratti].[dbo].[Clientes] ([nome] ,[email] ,[nascimento]) VALUES (<nome, nvarchar(50),> ,<email, nvarchar(150),> ,<nascimento, date,>) GO
Em VALUES, inclua os dados que deseja incluir. O banco de dados Macoratti.mdf foi criado no SQL Server Management Studio e nele também foi criado uma stored procedure chamada GetClientes, conforme mostra a figura abaixo:

Essa stored procedure GetClientes oferece acesso à tabela Clientes e retorna todos os registros da tabela.
Vamos usar o Visual Web Developer 2010 Express Edition para criar o nosso site. No menu File, clique em New Web Site e a seguir selecione a linguagem Visual C#, o template ASP .NET Empty Web Site, informe o nome ASPNET_3Camadas e clique no botão OK.

Criando o projeto no Visual Web Developer Express
Na janela Solution Explorer, você poderá ver a estrutura do projeto contendo apenas o arquivo web.config. Vamos incluir uma Master Page no projeto. No menu WebSite, selecione Add New Item e a seguir selecione o template Master Page, informe o nome Site.master e clique no botão Add.

Após incluir a Master Page, vamos incluir nela uma tabela com 3 linhas e 1 coluna a partir do menu Table->Insert Table, definindo na página o seguinte layout:

Definindo as Classes do projeto
Vamos agora definir três classes em nosso projeto:
- Configuração: classe responsável por obter a string de conexão e o nome do provedor usado.
- AcessoDados: classe que contém os métodos para acesso aos dados.
- Cliente: classe que irá chamar os métodos da classe AcessoDados.
Vamos criar uma nova pasta no projeto chamada App_Code para conter essas três classes.
A pasta App_Code é uma pasta especial na qual você
pode armazenar seu código-fonte e ele será compilado automaticamente em
tempo de execução.O assembly resultante está acessível a todos os outros
códigos no aplicativo da Web. Dessa forma, a pasta App_Code funciona como a pasta Bin, exceto pela possibilidade de armazenar código-fonte nela em vez de código compilado.
A pasta App_Code e seu status especial em um
aplicativo ASP.NET tornam possível criar classes personalizadas e outros
arquivos que contém somente código-fonte e usá-los em seu aplicativo da
Web sem ter que compilá-los independentemente.
A pasta App_Code pode conter quantos arquivos e
sub-pastas quanto você precisar. Você pode organizar seu código-fonte de
qualquer forma que você achar conveniente.
No menu WebSite, clique em Add ASP .NET Folder e selecione App_Code:

Criando a classe Configuracao.cs
Vamos agora criar a classe Configuracao.cs na pasta App_Code. Clique com o botão direito do mouse sobre a pasta App_Code e selecione Add New Item. Selecione o template Class, informe o nome Configuracao.cs e clique no botão Add. Em seguida, digite o código abaixo na classe Configuracao.cs:
using System.Configuration;
public static class Configuracao { private static string dbConnectionString; private static string dbProviderName;
static Configuracao() { dbConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; dbProviderName = ConfigurationManager.ConnectionStrings["ConnectionString"].ProviderName; }
public static string DbConnectionString { get { return dbConnectionString; } }
public static string DbProviderName { get { return dbProviderName; } } }
Nesse código, estamos usando o namespace System.Configuration, pois vamos obter a string de conexão e o nome do provedor a partir do arquivo de configuração Web.Config.
Vamos então abrir o arquivo Web.Config e incluir na seção connectionStrings a string de conexão para acesso ao banco de dados Macoratti, além do nome do provedor conforme abaixo:
<connectionStrings> <add name="ConnectionString" connectionString="Data Source=.SQLEXPRESS;Initial Catalog=Macoratti;Integrated Security=True" providerName="System.Data.SqlClient"/> </connectionStrings>
Criando a classe AcessoDados.cs
Clique com o botão direito do mouse sobre a pasta App_Code e selecione Add New Item. Selecione o template Class, informe o nome AcessoDadaos.cs e clique no botão Add. Em seguida, digite o código abaixo na classe AcessoDados.cs:
using System; using System.Data; using System.Data.Common;
namespace Macoratti { public static class AcessoDados { static AcessoDados() { }
public static DbCommand CreateCommand() { string dbProviderName = Configuracao.DbProviderName; string dbConnectionString = Configuracao.DbConnectionString; DbProviderFactory factory = DbProviderFactories.GetFactory(dbProviderName); DbConnection connection = factory.CreateConnection(); connection.ConnectionString = dbConnectionString; DbCommand command = connection.CreateCommand(); command.CommandType = CommandType.StoredProcedure; return command; }
public static DataTable ExecuteReader(DbCommand command) { DataTable table; try { command.Connection.Open(); DbDataReader reader = command.ExecuteReader(); table = new DataTable(); table.Load(reader); } catch (Exception ex) { throw ex; } finally { command.Connection.Close(); } return table; }
public static int ExecuteNoneQuery(DbCommand command) { int linhasAfetadas = -1; try { command.Connection.Open(); linhasAfetadas = command.ExecuteNonQuery(); } catch (Exception ex) { throw ex; } finally { command.Connection.Close(); } return linhasAfetadas; }
public static string ExecuteScalar(DbCommand command) { string valor = ""; try { command.Connection.Open(); valor = command.ExecuteScalar().ToString(); } catch (Exception ex) { throw ex; } finally { command.Connection.Close(); } return valor; } } }
Nessa classe, definimos 4 métodos para acessar os dados:
- CreateCommand: cria um novo comando a partir do nome do provedor
O método CreateCommand() é do tipo DbCommand e cria
um novo comando usando uma fábrica de provedores, além de utilizar o
nome do provedor e a string de conexão para criar um comando para o
provedor definido no arquivo Web.Config.
O novo modelo de provedor disponível a partir da ADO.NET 2.0 está baseado em um série de classes base no namespace System.Data.Comom. A classe DBProviderFactories permite a realização de dois tipos de tarefas:
- Obter uma lista de todos os provedores existentes via método estático GetFactoryClasses
- Criar uma instância de um determinado Factory conforme o seu tipo via método GetFactoryClass
Uma classe base de provedor é um objeto factory, que é usado para criar um conjunto de objetos relacionados como SqlConnection e SqlCommand. Eles retornam um tipo de classe abstrata do tipo DBConnection.
As classes de provider factory são derivadas de uma classe base abstrata: System.Data.Common.DbProviderFactory. Para cada tipo de base de dados a ser acessado, temos uma nova classe derivada dessa classe base abstrata. A classe DbDataProvider define o número de funções que essa subclasse precisa implementar:
CreateComand() |
Cria um objeto
Command derivado de DBCommand. |
CreateCommandBuilder() |
Cria um objeto derivado de DbCommandBuilder |
CreateConnection() |
Cria um objeto
derivado de DbConnection. |
CreateConnectionStringBuilder() |
Cria um objeto
derivado de DbConnectionStringBuilder |
CreateDataAdapter() |
Cria um objeto
derivado de DbDataAdapter. |
CreateDataSourceEnumerator() |
Cria um objeto
derivado de DbDataSourceEnumerator. |
CreateParameter() |
Cria um objeto
derivado de DbParameter. |
CreatePermission() |
Cria um objeto
derivado de CodeAccessPermission, |
Funções
DbDataProvider |
Desde que o DbProviderFactory apropriado foi criado, a função na tabela acima pode ser usada para criar o objeto apropriado em vez de usar o operador New como anteriormente. Para determinar todas as classes DbProviderFactory disponíveis e criar suas classes adicionais, é fornecida a classe System.Data.Common.DbProviderFactories.
Cada provedor de dados faz o registro de uma classe ProviderFactory no arquivo machine.config da plataforma .NET. A classe base DbProviderFactory e a classe ProviderFactories podem retornar um DataTable de informações sobre os diferentes provedores registrados no arquivo machine.config. Eles podem recuperar a ProviderFactory conforme a sequência do provedor fornecida ou um DataRow de um DataTable.
- ExecuteReader: retorna um DataTable usando para
instruções SELECT com objetivo de obter os dados retornado por consultas
SQL usando SELECT
O método ExecuteReader possui um parâmetro DbCommand. Esse comando irá obter um DataTable resultado da consulta SELECT. O DbDataReader irá ler todos os dados a partir das tabelas e finalmente o comando irá retornar o resultado como um DataTable.
- ExecuteNonQuery: usado para instruções INSERT, UPDATE,
DELETE. Neste caso, não teremos dados retornados apenas as
linhas(registros) que foram afetadas
- ExecuteScalar: usado para obter somente o primeiro dado retornado pela consulta SELECT
Criando a classe Cliente.cs
Clique com o botão direito do mouse sobre a pasta App_Code e selecione Add New Item. Selecione o template Class, informe o nome Cliente.cs e clique no botão Add. Em seguida, digite o código abaixo na classe Cliente.cs:
using System.Data; using System.Data.Common;
namespace Macoratti { public class Cliente { public static DataTable GetClients() { DbCommand command = AcessoDados.CreateCommand(); command.CommandText = "GetClientes"; return AcessoDados.ExecuteReader(command); } } }
Nesse código, criamos um comando para usar a stored procedure GetClientes, criada no banco de dados Macoratti.mdf. A seguir, executamos o método ExecuteReader da classe AcessoDados que retornar um DataTable com os dados dos clientes.
Definindo a camada de apresentação
Vamos incluir no projeto um novo Web Forms para exibir as informações da tabela Clientes usando as classes que criamos nos tópicos anteriores. No menu WebSite, clique em Add New Item e a seguir selecione o template Web Form. Informe o nome ListaClientes.aspx, marque a opção Select master page e clique no botão Add.

A seguir, selecione a master page Site.master e clique em OK.

Em seguida, na página ListaClientes.aspx, inclua um controle GridView alterando seu ID para gdvClientes. A seguir, abra o arquivo ListaClientes.aspx.cs e defina o código abaixo no evento Load da página:
namespace Macoratti {
public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { gdvClientes.DataSource = Cliente.GetClientes(); gdvClientes.DataBind(); } } }
Pegue o projeto completo Versão C# e compartilhe seus experimentos em três camadas.
Até a próxima!
artigo publicado originalmente no iMasters, por José Carlos Macoratti
|
Neste artigo, pretendo apresentar uma maneira de usar um método post
de formulário com o uso de Jquery. Com auxílio da função Ajax disponível
na base do Jquery, será apresentada uma forma que envia os dados sem a
necessidade do recarregamento da página dando ao usuário uma experiência
melhor com o sistema.
Para apresentar o recurso, escolhi um modelo de cadastro de
Newsletter com banco de dados MySQL, mas é possível utilizá-lo de
diversas maneiras seja para cadastros, consultas ou exclusões.
Como havia dito, utilizaremos a biblioteca Jquery que pode ser encontrada no endereço http://jquery.com/.
Para este artigo, utilizaremos a versão 1.4.2 min, porém qualquer
versão a partir da 1.2 pode ser usada, já que todas contêm em seu núcleo
a função Ajax. Salve o arquivo com o nome "jquery-1.4.2.min.js" na
mesma pasta que irá salvar as outras páginas.
Agora iremos criar o banco de dados Msql. Abaixo segue a estrutura definida.
DROP DATABASE IF EXISTS `newsletter`; CREATE DATABASE `newsletter`; USE `newsletter`;
CREATE TABLE `newsletter` ( `Id` int(11) NOT NULL auto_increment, `Nome` varchar(255) default NULL, `Email` varchar(255) default NULL, PRIMARY KEY (`Id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Com a base de dados pronta, iremos criar a página do formulário e
posteriormente criaremos a página que recebe os dados e realiza o
cadastro.
Página do formulário. Salve com o nome "Form_Newsletter.asp"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Formulário de Cadastro</title>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script> $(document).ready(function() { $("#button").click(function () { //Declarando as variaveis var Nome =""; var Email =""; //Recuperando os dados e atribuindo as variaveis Nome = $("#Nome").val(); Email = $("#Email").val(); //Inicio da funcao $.ajax({ //Metodo utilizado type: "POST", //Pagina que recebe os daods url: "Recebe_dados.asp", //String de dados enviada data: "Nome="+Nome+"&Email="+Email+"", //Inicio da funcao que requisita a resposta da pagina onde recebeu os dados success: function(msg){ alert( "Sucesso! " + msg ); //Limpando os valores dos campos $("#Nome").val(''); $("#Email").val('');
} });
}); }); </script>
</head>
<body> <p>Newsletter</p>
<table width="280" border="0"> <tr> <td>Nome:</td> <td><input type="text" name="Nome" id="Nome" /></td> </tr> <tr> <td>E-Mail:</td> <td><input type="text" name="Email" id="Email" /></td> </tr> <tr> <td> </td> <td><label> <input type="submit" name="button" id="button" value="Cadastrar" /> </label></td> </tr> </table>
</body> </html>
Na página acima, notamos a função "$.ajax" nessa área. É onde aplica o
recurso que faz a chamada, transferindo os registros para a página de
cadastro.
$.ajax({ //Metodo utilizado type: "POST", //Pagina que recebe os daods url: "Recebe_dados.asp", //String de dados enviada data: "Nome="+Nome+"&Email="+Email+"", //Inicio da funcao que requisita a resposta da pagina onde recebeu os dados success: function(msg){ alert( "Sucesso! " + msg ); //Limpando os valores dos campos $("#Nome").val(''); $("#Email").val('');
} });
Página que realiza a inclusão dos dados enviados pela função acima.
Salve com o nome "Recebe_dados.asp".
<% 'Declarando a variavel de conexao Dim Conexao 'Atribuindo o objeto a variavel de conexao Set Conexao = Server.CreateObject("ADODB.Connection") 'String de conxao para base de dados Mysql Conexao.ConnectionString = "driver={MySQL ODBC 5.1 Driver};server=localhost;uid=usuario;pwd=senha;database=newsletter" 'Abrindo a conexao Conexao.Open
'Funcao para tratar as variaveis Function Trata_Request(txt)
entrada = replace(txt,"'","")
Trata_Request=entrada end Function
'Recuperando as variaveis enviadas pelo metodo post Nome = Trata_Request(request.Form("Nome")) Email = Trata_Request(request.Form("Email"))
'Instrucao SQL para inserir as variaveis set cadastra = Conexao.execute("INSERT INTO newsletter(nome,email) VALUES('"&Nome&"','"&Email&"')") %>
Dados recebido com sucesso!
Ao receber os dados a página, mande uma resposta de ok e, com isso, é
apresentada a informação que os dados foram cadastrados com sucesso.
Vimos neste artigo uma maneira de melhorar a usabilidade de um
sistema de Newsletter que pode ser aplicado a outros sistemas, focando
em uma melhor experiência dos usuários. Com os recursos atuais e com
boas práticas, podemos economizar recursos de processamento ao
transferir informações entre páginas. artigo publicado originalmente no iMasters, por Thiago Violim
|
Olá, pessoal! Continuando nosso artigo sobre o reporting services (veja a primeira parte aqui), começaremos a analisar o que chamamos de relatórios local mode.
Local mode
Também conhecidos como client-side, os relatórios ditos
locais seguem o modelo de desenvolvimento e deploy dos relatórios
desenvolvidos como o Microsoft Access e Crystal Reports, onde os
relatórios são parte integrante da aplicação.
Arquitetura
Nesse modelo de relatório, todo processamento é realizado no cliente.
A aplicação é responsável por obter os dados provenientes de qualquer
fonte de dados, e o controle ReportViewer apresenta os relatórios. A
figura abaixo apresenta a arquitetura dos relatórios Local Mode:
 Figura 2.1 – arquitetura local mode
Caracteristicas
Os relatórios “local mode” caracterizam-se especialmente por:
- A segurança é herdada da aplicação que o hospeda;
- Filtros, ordenação, agrupamento e funções de agregação estão disponíveis;
- Possui formatação rica e inteligente, com imagens, fontes e cores;
- Interatividade com bookmarks e DocumentMap;
- Liberdade para interatividade com o usuário final;
- Integração com o controle ReportViewer;
- DataSet como estrutura de dados;
- Arquivos .RDLC (nenhuma instrução de acesso e/ou conexão à base de dados).
E seus elementos fundamentais correlacionam-se conforme a figura abaixo:
 Figura 2.2 – correlação dos elementos
Processo de criação
A partir dessa sessão, começaremos a implementar alguns relatórios
exemplo. Para isso utilizaremos um banco de dados que controla pedidos
de uma loja de departamentos. O diagrama abaixo apresenta as tabelas e
seus respectivos relacionamentos.
 Figura 2.3 – modelo de dados utilizado em nossos exemplos
Retornando ao processo de criação, para qualquer relatório implementado temos que seguir basicamente os seguintes passos:
- Modelagem do repositório de dados local
DataSet – estrutura de dados com integridade relacional:
- Elaboração do layout e “inteligência” do relatório
Header, Body, Footer:
- Uso de patterns – dados agrupados, tabular, matriz, colunas múltiplas, gráficos.
Criação de parâmetros, formatação condicional:
- Recuperação dos dados, preenchimento do dataset e bind com o relatório
- APIs do ADO .NET, Stored Procedures, T-SQL
- Controle ReportViewer
Template de aplicação
Para nossos exemplos, tomaremos uma aplicação Windows Forms, como
apresentado na figura abaixo. Atente para as pastas DataSources e
Reports, onde respectivamente armazenaremos os DataSets e os relatórios
criados.
 Figura 2.4 – template de aplicação
Repositório de dados local – dataset
Relatórios são representações formatadas de um conjunto de registros
provenientes de uma consulta em um repositório de dados. Para os
relatórios criados na plataforma do Reporting Services é necessário um
DataSet tipado com uma ou mais tabelas, que serão a estrutura de dados
volátil contendo as informações dos relatórios. Esse dataSet será
preenchido no aplicativo que hospeda o relatório e será utilizado na sua
formatação.
Nota: Um DataSet é uma representação na memória de um banco de dados relacional. Maiores informações, consultar a página do MSDN especifica sobre essa estrutura de dados.
 Figura 2.5 – criação de datasets
Podemos criar objetos DataSets de diversas formas.
Utilizaremos aqui o wizard do Visual Studio para a criação dos nossos,
bem como das tabelas necessárias para criação dos relatórios. Nesse
primeiro exemplo teremos um relatório tabular com os produtos, suas
respectivas categorias, quantidade em estoque e valor unitário. Então,
modelaremos um dataset com uma única tabela contendo esses campos como
mostrado na figura 2.6. A figura 2.5 ilustra a criação de um novo
dataset através da inclusão de um novo item (DataSet) ao projeto.
 Figura 2.6 – datatable do dataset exemplo
Formatando os relatórios
Tipos e estrutura do relatório
Uma vez modelado o DataSet, é hora de utilizá-lo para formatar o
relatório. O primeiro passo é decidir que tipo de relatório será
utilizado. Por exemplo, se os dados estiverem relacionados a agrupamento
de itens, a melhor escolha é utilizar um relatório tabular (como no
caso desse nosso primeiro exemplo). No entanto, relatórios com gráficos
são mais indicados para representar dados sumarizados. A estrutura dos
relatórios do RS inclui três sessões como mostrado na figura 2.7:
- Header: indicado para incluir informações estáticas referentes ao
relatório, tais como título, data, logo da empresa e, se for o caso,
alguns dos parâmetros informados pelo usuário;
- Body: é a região dos detalhes do relatório, onde os dados
provenientes das consultas (armazenados no DataSet), filtros e ordenação
serão exibidos;
- Footer: ideal para outras informações do relatório, tais como número de página e informações de direitos autorais.
 Figura 2.7 – sessões do relatório e dataSet
Report itens
Parte fundamental da formatação dos relatórios, os report items,
disponíveis na Toolbox do Visual Studio, funcionam como um canal entre o
DataSource e a estrutura do relatório. Os Report Itens são simples
objetos, parecidos com os controles das aplicações Window e Web Forms, e
como tal, o grande segredo do bom uso desses itens é conhecer suas
propriedades. A figura 2.8 apresenta nossa caixa de ferramentas, onde já
utilizamos alguns textbox e um table para formatar as sessões header e
body.
 Figura 2.8 – Toolbox
A tabela a seguir descreve resumidamente os itens da nossa caixa de ferramentas:
Item |
Descrição |
Poiter |
Seleciona os itens do relatório. |
Textbox |
Item mais utilizado da toolbox – exibe informações provenientes do datasource ou mesmo textos estáticos. |
Line |
Desenha uma linha como separador de informações. |
Table |
Exibe detalhadamente as informações do relatório em formato tabular, além de disponibilizar sessões de cabeçalho e rodapé. |
Matrix |
Exibe detalhadamente as informações do relatório correlacionando linhas e colunas. |
Rectangle |
Agrupa informações relacionadas. |
List |
Exibe detalhadamente as informações do
relatório. Parecido com o table, no entanto sem tantos recursos, tais
como as sessões de cabeçalho e rodapé. |
Image |
Permite inserir imagens no relatório. |
Subreport |
Inclui outro(s) relatório(s) dentro de um relatório principal. |
Chart |
Exibe as informações do relatório em formato gráfico, com diversas opções de formatação. |
Mais informações sobre os itens mais importantes:
- Textbox
Pode-se dizer que não é possível construir um relatório sem o Textbox,
que é sem dúvida o componente mais versátil que temos à disposição. Ele
pode ser utilizado para diversas finalidades, como o título do relatório
no header e a exibição de totalizadores. Esse controle é usado para
exibir textos estáticos, fazer bind com data source, campos calculados e
expressões. - Table
É o melhor item para relatórios detalhados. Cada tabela possui uma
estrutura com sessões Header, Detail e Footer – não confundir com as
sessões homônimas do próprio relatório. O Header é indicado para os
nomes das colunas; no Details, temos um conjunto de linhas provenientes
do datasource e, finalmente, no Footer, temos informações sumarizadas
dos dados do relatório. É possível ter mais de uma tabela em um
relatório. É muito importante dominar quais são as propriedades do
componente Table (figura 2.9 abaixo) – especialmente as tabs Groups,
onde é possível configurar diversos agrupamentos das informações e
Filter, onde podemos estabelecer restrições aos dados visíveis aos
usuários.
 Figura 2.9 – Table Properties
Subreport
Um relatório é considerado um subreport quando inserido em outro
relatório. O sub-relatório funciona como um filho do relatório que o
hospeda (parent), tornando os sub-relatórios uma poderosa ferramenta
para, por exemplo, implementar o tão requisitado conceito master/detail.
No entanto é preciso ter muita cautela na sua utilização, uma vez que
temos perdas consideráveis na performance do relatório.
Chart
O item Chart é responsável pela apresentação de informações numéricas
em formato de gráficos. As ferramentas de gráficos foram inseridas nos
relatórios do RS pela empresa Dunda Software, estando à disposição os
tipos mais comuns de gráficos: pizza, barra e colunas.
Formatação
Não se faz um relatório capaz de atrair a atenção dos leitores se
suas informações não forem bem formatadas. Dados numéricos, por exemplo,
são muito melhor compreendidos se devidamente formatados conforme seu
tipo – numérico inteiro, decimal, moeda ou científica, por exemplo.
Outra informação digna de atenção na sua formatação são os campos
referentes à data e hora. No processo de criação dos relatórios, a
formatação é feita através de uma caixa de dialogo na tab Format das
propriedades de uma caixa de texto, vide abaixo – figura 2.10.
 Figura 2.10 – Formatação texto
Dicas importantes:
- Certifique-se que o tipo do campo esteja devidamente bem definido no DataTable, do contrário a formatação simplesmente não funciona. E o tipo default dos campos é System.String;
- Garanta que o idioma do relatório esteja devidamente configurado;
- Considere o uso de Expressions do tipo, Common Functions à Text (Format, FormatCurrency, FormatDateTime, FormatNumber e FormatPercent).
Ainda com o intuito de tornar nossos relatórios atrativos aos
usuários, outros atributos das caixas de texto podem ser customizados,
tais como Fontes, Cor, Alinhamento e Decoração. Todos esses, além de
outros atributos, podem ser configurados na janela de propriedades do
Textbox, como mostrado na figura 2.11.
 Figura 2.11 – Formatação texto
Dentro da formatação, eis um recurso muito poderoso dos relatórios do
RS, que é a formatação condicional, onde através do editor de Expressions, que utiliza um dialeto da linguagem Visual Basic, é possível criar instruções condicionais como a descrita abaixo.
=IIf(Fields!QT_ESTOQUE.Value<230,”Red”,”Blue”)
Parametrização
Os relatórios possuem um mecanismo de parametrização onde é possível
passar informações a partir do cliente para o relatório em tempo de
execução. A figura 2.12 ilustra a janela Report Parameters para criação dos parâmetros de um relatório, onde para acessar, basta clicar com o botão direito fora das sessões do relatório.
 Figura 2.12 – parâmetros
Os parâmetros aqui criados podem ser utilizados para formatação condicional ou em expressões. Ao contrário dos relatórios remote mode,
esse modelo de relatórios não tem uma área para que o usuário selecione
ou digite o valor dos parâmetros, sendo responsabilidade do cliente
providenciar uma interface para coleta dessas informações. Dessa forma,
gerar o conjunto de dados devidamente filtrado e carregá-lo no dataSet,
os parâmetros são pouco utilizados para seleção dos registros, uma vez
que é mais indicado fazer essa restrição diretamente na pesquisa, ainda
que tenhamos como aplicar filtros (propriedade das tabelas, tab
Filters). Essa funcionalidade é mais indicada para criação de relatórios
do tipo master/detail com subreports.
Consumindo o relatório
Controle reportviewer
Para interação dos relatórios com os clientes, temos o controle
ReportViewer, disponível no visual Studio em duas versões – uma para web
e outra para Windows forms. Com ele é possível disponibilizar para as
aplicações um conjunto de funcionalidades, tais como:
- Exportação dos dados nos formatos Excel e PDF;
- Suporte a impressão e visualização de impressão do relatório
- Rica interatividade com navegação, document map, bookmarks e ordenação;
- Pesquisa de texto no corpo do relatório;
- Zoom.
O controle é capaz de processar e renderizar os relatórios
independente do seu modelo, local ou remote. A figura abaixo exibe o
controle ReportViewer em ação renderizando um relatório.
 Figura 2.13 – reportviewer
Parte dos recursos do ReportViewer, tais como Zoom, botão Stop, os
botões de pesquisa, de exportação, impressão, dentre outros, podem ser
desativados na sua janela de propriedade, como mostrado na figura
abaixo. Outra propriedade importantíssima do ReportViewer é seu
ProcessingMode.
 Figura 2.14 – propriedades do reportviewer
Código cliente
Uma vez modelados, o relatório e seu respectivo DataSet, chegou a
hora de relacionar tudo. E como já dissemos, todo processamento é feito
no cliente – da obtenção dos dados no repositório para carga do dataset,
à renderização do relatório via controle ReportViewer. A figura 2.15
apresenta o fluxo padrão de um código cliente para utilização de
relatórios RS em client-mode.
 Figura 2.15 – fluxo padrão do código cliente
Eis um pseudocódigo utilizado em um cliente de um relatório local mode.
string cnString = "Database=[banco];Server=[servidor];User Id=sa;PassWord=sa";
SqlConnection conReport = new SqlConnection(cnString);
SqlCommand cmdReport = new SqlCommand();
DataSet dsReport = new WFormReport.DataSources.ProdutosporCategoria();
conReport.Open();
SqlParameter[] parms = {new SqlParameter("@idCategorias", SqlDbType.VarChar,20)};
parms[0].Value = “1,2,3”;
cmdReport.CommandType = CommandType.StoredProcedure;
cmdReport.Connection = conReport;
foreach (SqlParameter parm in parms)
cmdReport.Parameters.Add(parm);
cmdReport.CommandText = "getProdutosinCategorias";
SqlDataReader drReport = cmdReport.ExecuteReader();
dsReport.Tables[0].Load(drReport);
drReport.Close();
conReport.Close();reportViewer1.LocalReport.ReportPath = “ProdutosporCategoria.rdlc";ReportDataSource rds = new ReportDataSource();rds.Name = "ProdutosporCategoria_ProdutosEstoque";
rds.Value = dsReport.Tables[0];reportViewer1.LocalReport.DataSources.Clear();
reportViewer1.LocalReport.DataSources.Add(rds);
reportViewer1.RefreshReport();
Por hoje é isso pessoal. Na próxima edição imperdível, trarei só códigos! Diversos exemplos para boas horas de diversão.
Grande abraço e até lá. *** Artigo de Caio Azevedo
|
Olá a todos!
No meu último artigo,
escrevi sobre virtualização de servidores, e neste artigo vou
apresentar uma solução que vem se consolidando no mercado, apesar de ser
estudada já há algum tempo. É uma solução relativamente nova: o SDN (Software Defined Networking).
As atuais tecnologias de rede não dão conta de todas as exigências
dos usuários e das empresas devido à sua complexidade e à quantidade de
protocolos utilizados; geralmente são desenvolvidas e definidas de forma
isolada e, para dificultar ainda mais, alguns fabricantes desenvolvem
“protocolos proprietários”.
Dessa forma, quando é preciso escalar a rede e adicionar mais
dispositivos, essa tarefa se torna cada vez mais complexa, pois
praticamente não existe interoperabilidade entre alguns fabricantes e,
quando isso se faz necessário, novos aplicativos e protocolos são
desenvolvidos, o que às vezes pode ser um processo lento, o que
inviabiliza a implantação de novas tecnologias em uma planta de redes já
existente.
Além desse detalhe, os pesquisadores na área de redes de computadores
têm problemas em testar novas ideias, uma vez que os switches/routers
encontrados hoje no mercado são criados com protocolos fechados e com
software pertencente às empresas. Em consequência disso, novas ideias
surgem para melhorar o desempenho das redes existentes, porém essas
pesquisas permanecem em ambientes de laboratório, não sendo possível
testar essas ideias em diferentes escalas para avaliar se a solução tem
ou não o funcionamento esperado. E, como sabemos, hoje é praticamente
impossível testar soluções em redes de produção, ainda mais em grandes
empresas.
Com esse problema em mente, a arquitetura Software Defined Networking
(SDN) surgiu para superar os problemas de switches e routers fechados e
de softwares proprietários, a fim de não comprometer os serviços de
redes em produção, e para facilitar a inovação. O SDN permite uma
separação útil entre os planos de controle e de dados: essa separação
torna possível haver switches e routers encaminhando dados de acordo com
novas regras que se encontram num servidor. O resultado é que o plano
de controle da rede fica à disposição dos pesquisadores, que agora podem
aplicar as suas novas ideias sem violar as regras existentes de
roteamento e sem causar problemas de funcionamento das redes em
produção.

A grande sacada da arquitetura SND é possibilitar a rápida
configuração da rede conforme a demanda de serviços e os negócios das
empresas, além de permitir a criação de features e protocolos, independentemente dos fabricantes.
Os principais fabricantes de equipamento de redes estão correndo para
a oferta de produtos compatíveis com o modelo, como a compra da Nicira
pela VMware, o lançamento de switches com software aberto, como os da
Arista Networks, entre outros.
Outra dificuldade encontrada hoje é que um grande parque de
equipamentos de diferentes fabricantes sempre exige mão de obra
altamente especializada, o que nem sempre é possível. No caso de uma
rede definida por software, um administrador de rede pode moldar o
tráfego a partir de um controle centralizado sem precisar mexer em
equipamentos de diversos fabricantes. O administrador pode alterar as
regras de qualquer switch de rede, quando necessário, priorizando ou
mesmo bloqueando determinados tipos de pacotes com um nível muito alto
de controle. Isso é especialmente útil em redes grandes e cloud computing, pois permite que o administrador gerencie as cargas de tráfego de uma forma flexível e mais eficiente.
SDN é por vezes referido como o “assassino Cisco”, porque permite que
os engenheiros de rede suportem redes de múltiplos fabricantes.
Atualmente, a especificação mais popular para a criação de uma rede
definida por padrão é chamada de OpenFlow .
Hoje, os clientes já estão “vendidos” para Infraestruturas de
Serviços (IaaS),(PaaS) e (SaaS), que possuem diversos sistemas e
softwares proprietários vindos de vários fabricantes, mas o que dizer de
se utilizar a rede como um serviço? Apesar do fato de a nuvem estar
ligada através da rede, ouve-se pouco ou nada sobre um novo paradigma
para a nuvem. Rede como um serviço não só é real, mas é provável que se
torne universal. No entanto, pode ser necessário utilizar um software de
rede definida (SDN) sob a forma de OpenFlow para que isso aconteça.
Cloud computing implanta uma infinidade de recursos que
podem ser provisionados sob demanda. A nuvem também envolve conexões aos
seus usuários, acesso a armazenamento, comunicações unificadas e
alocação de recursos ou de gestão. As tecnologias de rede Ethernet têm
deficiências quando se trata de serviços em nuvem por causa de
segurança, QoS, escalabilidade e custos operacionais.
Como praticamente todos os devices de rede e servidores
funcionam sob IP, a presunção de conectividade universal torna mais
difícil de gerenciar e ter segurança no tráfego. Uma solução proposta é
centralizar uma política de conexão usando SDN. Em SDNs, os terminais
não têm como se conectar, então nada na rede está ligado em primeiro
lugar. Em vez disso, um controle de software decide que conexões serão
permitidas, quais as premissas de segurança, engenharia de tráfego e
somente então será acessada por quem tem permissão de se conectar.
Essa gestão de recursos de rede centralizada é virtualmente idêntica
ao recurso de gestão por trás das IaaS, PaaS e SaaS em nuvem. Portanto,
não será uma surpresa a arquitetura SDN servir de base para a rede como
um serviço. Muitos dos principais fabricantes de switches e roteadores
manifestaram apoio ao OpenFlow, que é a arquitetura por trás da implementação da SDN.
OpenFlow é uma combinação de software de especificação e de código aberto que funciona nos devices de rede, com controle unificado. Em uma rede OpenFlow, quando um switch ou roteador recebe um pacote, em vez de tomar a decisão sozinho, o device
envia o pacote para o controlador, que, em seguida, utiliza critérios
para tomar a decisão. Essas políticas, então, criam uma regra de
encaminhamento, que o controlador passa de volta para o dispositivo
solicitante.
Um dos maiores desafios é que uma rede OpenFlow não pode
funcionar se cada pacote precisar ser enviado para um controlador
central a fim de ser analisado. Para fazer um trabalho de rede com
escalabilidade, o OpenFlow deve ser melhorado ou o seu uso deve ser contido dentro de rede em nuvem. Ambas as opções já estão sendo propostas. OpenFlow
vai funcionar melhor quando o tráfego for composto de um número modesto
de fluxos previsíveis. Dessa forma, uma vez que os switches e
roteadores tiverem aprendido as regras de trânsito a partir do
controlador, a interação adicional com o controlador será reduzida.
Quando usado em um datacenter para o controle de servidor para servidor ou servidor para storage, o OpenFlow serve de contribuição muito importante. Mesmo dentro de datacenters em uma nuvem (pública, privada ou híbrida) distribuída, o OpenFlow poderia ser utilizado para gerenciar o tráfego.
Felizmente, várias pesquisas estão sendo feitas para interagir OpenFlow
com MPLS e gerar um novo tipo de rede IP que oferecerá uma combinação
de conectividade aberta e políticas de gestão de conectividade. Existem
também as formas potenciais de fazer o controle OpenFlow de forma mais hierárquica e escalável. Além disso, há iniciativas em cloud computing,
em que o conceito de rede como um serviço surgiu, para gerir a forma de
lidar com aplicações em nuvem. Essas iniciativas convertem aplicativos
em “serviços virtuais” na nuvem. É muito cedo para dizer se eles irão
criar um OpenFlow escalável, mas, se o fizerem, haverá um
avanço em modelos de rede como um serviço, melhorando a forma de como os
recursos são acessados.
Essas novidades podem não ser disponíveis para todos agora, porém
todos os indícios apontam que essa inovação ocorrerá em um futuro breve.
Até a próxima!
|
O Quartz é um serviço de agendamento de tarefas que pode ser integrado, ou utilizado virtualmente, em qualquer aplicação Java SE ou Java EE. A ferramenta pode ser utilizada para criar agendas que executam milhares de tarefas, que são definidas utilizando componentes padrão da plataforma Java, que são codificados para suprir as necessidades da aplicação. O Quartz Scheduler fornece diversos recursos corporativos, como suporte a transações JTA ou clusterização. O Scheduler é o componente principal do Quartz e é o responsável por gerenciar a execução de jobs. A partir dele, o desenvolvedor pode agendar, iniciar e parar as execuções. Para construir um Scheduler, deve-se utilizar uma classe que implementa o padrão de projeto Factory no Quartz, representado pela interface SchedulerFactory. Existem duas classes que implementam esta interface: StdSchedulerFactory eDirectSchedulerFactory. A primeira permite a utilização de um arquivo properties para configuração e a segunda implementa um segundo padrão de projeto: o Singleton. Após obter um Scheduler, pode-se iniciar a execução do agendamento a partir do métodostart(), agendar novos jobs com o scheduleJob() e parar o agendador com o shutdown(). Ao se agendar um job com o método scheduleJob(), é necessário definir dois parâmetros: - O primeiro define o job que será executado, representado pela interface Job;
- O segundo define o trigger, representado pela interface Trigger, que corresponde às condições de agendamento para execução do job em questão.
O que é um job?Um job é uma tarefa a ser executada, que no Quartz nada mais é do que uma classe que implementa a interface Job e que agrega todo o código necessário para fazer a funcionalidade específica do job em questão. Ele pode, também, receber parâmetros para seu funcionamento correto e isso é feito a partir da classe JobDetail. Ao implementar a interface Job, deve-se implementar também o método execute(), que recebe como parâmetro um JobExecutionContext e lança uma exceção do tipoJobExecutionException. Dentro do método execute() estará todo o código referente ao job em questão. Um exemplo de job é uma varredura automática de spams em um e-mail, ou, uma busca por tags duplicadas de um produto para limpeza em um banco de dados de algum comércio eletrônico. Para a criação de um job, utiliza-se a classe JobBuilder, que define a classe do job implementado a partir do método newJob(), a identidade no método withIdentity() e a instanciação do mesmo no build(). O que é o trigger?Um objeto trigger é utilizado para disparar a execução de jobs. Quando um job é agendado, a instância de um trigger é feita e suas propriedades são configuradas para satisfazer o agendamento necessário para a aplicação. Existem alguns triggers pré-definidos na biblioteca Quartz, como, por exemplo, o SimpleTrigger e o CronTrigger. Para a construção de um trigger, é utilizada a classe TriggerBuild, que implementa métodos utilizando o Domain Specific Language (DSL) e permite a configuração dos dados do trigger, como, por exemplo, sua identidade, a partir do método withIdentity(); seus dados de agendamento, a partir do método withSchedule(), e a instanciação do trigger, a partir do método build(). Esse último retorna uma classe que implementa a interface Trigger. O CronTrigger é um tipo de trigger que é útil para agendamentos baseados em calendários, como, por exemplo, “uma execução deve ocorrer às quartas e quintas às 12:00h” ou “uma execução deve ocorrer todos os dias às 08:00h”, e assim por diante. Ele é construído quando se define um agendamento do tipo CronSchedule no métodoTriggerBuild.withSchedule. Este tipo de agendamento é construído a partir do método estático cronSchedule da classe CronScheduleBuilder, que recebe como parâmetro uma expressão cron. Para formar uma expressão cron, alguns requisitos devem ser satisfeitos. Primeiramente, deve-se conhecer a ordem dos parâmetros: - Segundos;
- Minutos;
- Horas;
- Dia do mês;
- Mês;
- Dia da semana;
- Ano (opcional).
Por exemplo, uma expressão cron que será executada todas às quartas-feiras às 12:00pm é escrita da seguinte forma: “0 0 12 ? * WED”. Outro exemplo de expressão demonstra uma tarefa executada todos os dias, às 08:00am e 12:00pm: “0 0 8,12 * * *”. ExemploPara ilustrar todos os conceitos apresentados anteriormente, foi desenvolvido um exemplo simples, que simula a utilização de um CronTrigger e define um job customizado que implementa a interface Job. Ele será responsável por exibir uma mensagem de texto simples indicando que foi executado a cada dez segundos todos os dias. O código do job foi definido conforme a listagem abaixo: public class MyJob implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
System.err.println("Servico executado conforme agendamento");
}
} A classe principal que faz a execução deste job foi definida conforme a listagem a baixo: public class Main {
public static void main(String[] args) {
try {
SchedulerFactory schedFact = new StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
JobDetail job = JobBuilder.newJob(MyJob.class)
.withIdentity("myJob", "group1")
.build();
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
.build();
sched.scheduleJob(job, trigger);
} catch (Exception e) {
System.out.println("erro");
e.printStackTrace();
}
}
} Neste exemplo de código, obtem-se uma instância de Scheduler a partir da FactoryStdSchedulerFactory. O agendamento é iniciado, depois cria-se um novo job, do tipoMyJob, um novo CronTrigger que possui a expressão cron “0/10 * * * * ?”, que significa “a cada dez segundos”, e o job é agendado conforme o trigger criado. ConclusãoApesar de ser um exemplo simples, com ele é possível verificar o funcionamento de cada componente necessário para a execução de um job agendado, e a partir dele é possível ver sua aplicabilidade no cenário de alguma aplicação que tenha estas necessidades. Referências
|
Olá, pessoal! Na primeira parte deste artigo sobre Criteria, eu fiz uma introdução a respeito. Agora, vamos ver mais algumas restrições importantes que temos nesta API. Vamos lá?! Criteria APIUma outra restrição bem interessante é o uso do >=, >, <=,< que fazemos no SQL, no HQL e etc. No Criteria temos métodos que nos ajudam na implementação desses operadores: gt(),ge(),lt(),le(). Veja cada um: - gt() = maior que
- ge() = maior ou igual que
- lt() = menor que
- le() = menor ou igual que
Saber de onde os métodos vêm é tão importante quando saber usá-los. Os que estão citados acima vêm da classe Resctrictions. Exemplo: crit.add(Restrictions.ge(“preco”, new Double(100.00)); A leitura é bem simples: retorna todos os produtos com o preço maior ou igual a R$100,00. Um dos pontos importante no uso de Criteria é quando precisamos usar AND e OR nas restrições.
crit.add(Restrictions.gt(“preco” new Double(100.0));
crit.add(Restrictions.like(“nome”, “smart%”));
List lista = crit.list(); A leitura é a seguinte: retorne produtos com o preço maior que R$100,00 e (AND) que tenham o nome “smart” como parte da string. Agora se precisarmos do OR, veja como fica: Criterion preco = Restrictions.gt(“preco”, new Double(100.0));
Criterion nome = Resctrictions.like(“nome”, “smart%”);
LogicalExpression orExp = Resctrictions.or(preco,nome);
crit.add(orExp);
List list = crit.list(); A lógica é a seguinte: retorne produtos com preço maior do que R$100,00 ou que tenha “smart” na palavra. Na linha 04 adicionamos o resultado. Então, a linha 02 somente é executada caso a primeira seja falsa. Quando queremos mais do que duas sequências diferentes de OR, podemos usar a classe Disjunction, que fica em org.hibernate.Disjunction para representar uma disjunction. Sem sombras de dúvidas usar a disjunction é mais conveniente do que vários OR no código, veja como fica: Criterion preco = Resctrictions.gt(“preco”, new Double(100.0));
Criterion nome = Resctrictions.like(“nome”, “smart%”);
Criterion fornecedor = Restrictions.like(“fornecedor”, “nokia%”);
Disjunction dis = Resctrictions.disjuntion();
dis.add(preco);
dis.add(nome);
dis.add(fornecedor);
cri.add(dis)
List lista = crit.list(); A leitura do código acima seria: retorne os produtos que tenha o preço maior do que R$100,00 ou (or) que tenha na parte da string a palavra “smart”, ou que tenha na propriedade fornecedor a palavra “Nokia”. Para fazer com o AND usamos o método conjunction() da classe Resctrictions. code Conjuction Apenas a linha acima será alterada para atender a cláusula AND. Vou ficando por aqui e espero que tenham gostado do artigo!
|
O Ruby tem um modo muito fácil para manipular
arquivos. Neste artigo, vamos ver os principais métodos para manipular
arquivos de texto plano.
arq = File.new("arquivo.txt", "modo_de_abertura")
- r - Abre o arquivo para leitura;
- w - Abre o arquivo para escrita;
- a - Anexa ao final do arquivo, caso você queira escrever no final do arquivo;
- r+ - Abre o arquivo para leitura e escrita;
- w+ - Cria um arquivo vazio para leitura e escrita;
- a+ - Abre o arquivo para leitura e anexação, ou seja, você
pode ler qualquer parte do arquivo, mas só pode escrever no final do
arquivo.
a = File.readlines("arquivo.txt")
Como pode ver, esse código devolve um vetor possuindo em cada elemento uma linha do arquivo.
- Lendo os caracteres do arquivo:
arq = File.open("arquivo.txt")
arq.getc.chr
arq.getc.chr
arq.getc.chr
arq.getc.chr
arq.getc.chr
arq = File.new("arquivo.txt", "w")
arq.write "Rails Open"
arq.puts " - Ruby on Rails"
arq.close unless file.closed?
O "unless file.closed?" foi colocado apenas para demonstrar o método
"close?". O "arq.close" já bastava para que ele funcionasse normalmente.
File.rename("arquivo.txt", "arquivo_novo.txt")
- Descobrindo a extensão do arquivo:
extensao = File.extname("arquivo_novo.txt") # => ".txt"
- Informações sobre o arquivo
O arquivo realmente existe?
File.exists?("arquivo_novo.txt")
Ele pertence a determinado diretório?
File.directory?("/home/samuelvinicius")
Qual o tamanho do arquivo em bytes?
File.size("arquivo_novo.txt")
O arquivo está vazio?
File.zero?("arquivo_novo.txt")
Qual a data de criação, de última modificação e de último acesso ao arquivo?
File.ctime("arquivo_novo.txt")
File.mtime("arquivo_novo.txt")
File.atime("arquivo_novo.txt")
- Posiciona em um ponto do arquivo:
arq = File.open('local_filename', 'r')
arq.seek(2, IO::SEEK_SET)
puts f.readline
***
Fonte: http://www.techotopia.com/index.php/Working_with_Files_in_Ruby
|
Olá, pessoal! Hoje eu vou explicar pra vocês como é que a equipe
define quais histórias estarão no Sprint Backlog do Sprint. Já vimos que
o PO é alguém importante no planejamento do Sprint. Então chegou a hora de discutir de como tirar as coisas que estão no Product Backlog e trazer para nossa “mesa”.
Como a equipe define as histórias que vão para um Sprint?
Essa é uma pergunta clássica. Eu já ouvi alguns comentários que
talvez o PO, ou SM, deveria fazer isso. Eu acho que se Scrum fosse um
framework que funcionasse com base do "quem tem o nível mais alto (para
não dizer cargo) é quem define as coisas", talvez faria sentido. Mas
como não é assim, o conceito de time, equipe, pessoas, etc, é de fato
mais importante que os papéis apenas.
Enfim, apesar do PO ter escrito toda história e em alguns casos ser o
responsável pelo investimento no projeto, no Scrum isso não dá o
direito de dizer: “a história já está escrita, priorizada e o escopo é
aquele. Se não entendeu algum ponto, por favor, deixe-me saber, mas não
vou mudar o escopo, porque eu quero assim”. Não é bem por ai... A
prioridade aqui é o time, ou seja, todos estão envolvidos e não apenas o
PO. Não é só porque ele é dono do produto que tudo vai acontecer como
ele deseja sem questionamentos.
Mas nós sabemos que esse cenário seria o ideal, mas que na realidade
não é assim. Se temos um problema como esse, é sinal de que seu cliente
não entendeu como o Scrum funciona e ai é um outro problema que precisa
ser tratado antes de tudo. Eu diria que até antes do cliente apresentar o
produto, ele já deveria saber o porquê vai rodar o Scrum e saber que as
coisas funcionam em um trabalho de equipe e que cada um tem suas
responsabilidade e limitações. Se isso não está claro para o seu
cliente, não inicie nada. Do contrário, terá problemas e discussões que
talvez não compensem. Agora vamos ignorar o cenário anterior.
Então, Camilo, como escolher a história que vai para o Sprint Backlog?
Por sentimento ou instinto. É isso mesmo! Não há mágica, ou
ferramenta, que vai te dizer: “pegue a história X, e a equipe que vai
contribuir para isso”. Normalmente, o ScrumMaster pergunta para equipe
se a história que está no topo da lista (aquela que tem mais importância
para o PO) dá para entregar naquela Sprint. Aquelas nas quais ainda
restarem dúvidas e incertezas a respeito da entrega ficam de fora (com o
aval e negociação do PO) do Sprint.
A seguir, temos um exemplo pratico (peguei a imagem do livro Scrum from the trenches):

Note: Claro que vamos seguir sempre a ordem de importância para o PO e não pegar as histórias aleatórias.
Vamos supor que o PO não gostou porque a história D está de fora -
afinal, a velocidade da equipe só permite entregar até a C. O que fazer?
Em primeiro lugar, o PO não pode obrigar a equipe a pegar a história D
(de novo, para você não esquecer). Então ele tem duas opções:
- É alterar o escopo, para que o time possa fazer uma nova estimativa;
- Mudar a ordem de prioridade, levando a história para cima do C, daí a
equipe é obrigada a pegá-la. Porém, a história C ficaria de fora.
Mas, o framework Scrum não diz que temos que pegar a história com
maior prioridade? Sim. Pegamos a história que está no topo da pilha do
product backlog, mas ao olhá-la, identificamos que é grande demais e não
cabe dentro do Sprint de duas semanas, ou seja, é pouco tempo para
muita coisa (escopo grande). Lembre-se, as histórias deve ser do tipo
INVEST.
- Independente: a história não pode ficar bloqueada durante a implementação; ela precisa ter vida por si só;
- Negociável: uma história precisa ter um escopo que pode ser alterado
sem perder toda a essência do que se pretende. E que algumas coisas
possam ser postergadas para um dos próximos Sprint tranquilamente;
- Valioso: deve agregar valor ao produto e ter um valor de importância dentro do próprio produto;
- Estimável: se não conseguimos estimar com base no que está escrito
para história, é porque temos algum problema no que ela se propõe. Então
precisamos ver com o PO o que ele está querendo dizer;
- Small: não é preciso ter todas as funcionalidade em única história,
sendo assim, ela pode ser pequena para que fique dentro do Sprint;
- Testável: toda história precisa ter uma forma de validar se ela foi
implementada corretamente. Então os critérios de aceitação devem
existir, para que possamos nos certificar que fizemos algo de acordo com
o esperado.
Bom, pessoal, era isso que eu tinha para apresentar para vocês. Não
se esqueçam que a responsabilidade de analisar e estimar é da equipe. O
que foi escrito pelo PO é o que ele desejaria de ver pronto, mas nem
sempre é possível, pois há vários fatores que contribuem para isso, tais
como: velocidade da equipe, nível técnico, interrupções, etc. Não é uma
tarefa fácil, mas com uma boa comunicação entre a equipe e o PO, sempre
terminamos no contexto ideal.
Espero que tenham gostado. Até o próximo artigo!
|
Olá, pessoal!
Neste artigo, veremos como montar "menu" com os dados vindo
diretamente do banco de dados. Sabemos que muitos aplicativos montam o
seu "menu" cadastrado no banco de dados, cada um com seu perfil e sua
permissão. Para isso, é necessário ter primeiro uma boa estrutura de
banco de dados e campos para montá-lo.
Em momentos anteriores, escrevi outros artigos que montam "menu"
diretamente de um XML, e com o componente diferente, ou seja, que
precisa ser referenciado no projeto. Este artigo será um pouco
diferente, pois os dados são de um banco de dados, e o componente para
montar o menu é o nativo da ferramenta.
Referências:
-
Banco de dados SQL Server
Vou mostrar o banco de dados montado para que entenda desde o começo o
passo a passo, pegando os dados do menu vindo do banco de dados.
O primeiro passo é criar uma tabela no banco de dados. Dei o nome de
dbo.Objeto. Essa tabela terá o menu, links, ordenação e informações
necessárias para montar o menu.

O campo ObjetoId é autoincremento e o objetoPaiId é um
auto-relacionamento indicando o menu principal. Por exemplo: se o "menu"
for o principal, esse campo ObjetoPaiId será NULL. Para o submenu, o
objetoPaiId terá um número indicando o ObjetoId. Segue a imagem
preenchida para que tenha uma outra boa referência:

Produção
Note que, na imagem, na primeira linha, o ObjetoPaiId está NULL (o
último campo da primeira linha). E que na segunda linha e no último
campo existe um número referenciado, é o mesmo da primeira linha; ou
seja; um auto-relacionamento.
Foram inseridos também alguns campos que, no momento, não serão
utilizados, mas podem ser futuro. Os campos são ExibeImagem e URLImagem.
Isso é para caso o seu menu tenha alguma imagem que precise ser
mostrada.
No campo endereço, o nome da página está com a extensão. Veja que não
coloquei o endereço completo, só o nome da página propriamente dito.
Todas as minhas páginas estão no diretório raiz. Dessa forma, coloquei
só o nome da página. Se tivesse dentro de uma pasta, colocaria o nome da
pasta barra o nome da página. (Isso é só para que entenda como
funciona).
O objeto que vou usar para mostrar o "menu" é o do próprio Visual Studio
.NET 2008. A versão da ferramenta não importa, pois o <ASP:MENU> é
o mesmo das versões anteriores.
E esse objeto funciona em todos os browsers sem qualquer problema. Pelo menos em meus testes todos abriram.
Além do objeto <ASP:MENU>, vou usar CSS e Imagens para ficar bonito o menu montado na tela.
Tabelas de vínculo
Agora, vamos ver a criação das tabelas de vínculo e um pouco de codificação em C#.NET.
Lembrando que não vamos mostrar aqui a forma de conectar ao banco de dados, nem
mesmo fazer o select para validar o usuário logado, isso porque estou partindo
do pressuposto que você sabe fazer isso. O objetivo é mostrar como carregar o
menu vindo do banco de dados de acordo com o usuário logado no sistema.
O menu precisa ser carregado de acordo com o perfil do
usuário, depois que ele entra com o usuário e senha. Dessa forma, o sistema
busca no banco de dados o perfil e com ele busca os dados no menu, que, no nosso
caso, é a tabela Objeto.
Se
o seu caso for apenas carregar o menu sem distinção de usuário, o caminho está
fácil. Mas se você precisa carregar o menu de acordo com o grupo
do usuário, é necessário criar mais algumas tabelas específicas.
Criando
tabelas para vincular o perfil do usuário
A
primeira tabela para gerar o perfil do usuário foi a Grupo.
Tabela Grupo
Campos:
- GrupoId (int) auto incremento
- Nome (varchar(60) notnull
A descrição do grupo pode ser colocada como você preferir. Na minha aplicação eu
tenho: Administrador, Usuário, Leitor.
Depois
de criar a tabela grupo, é necessário criar uma tabela chamada GrupoObjeto para
vincular a tabela Objeto com a tabela Grupo.
Tabela GrupoObjeto
Campos:
- ObjetoId
(int) notnull
- GrupoId
(int) notnull
O número do menu cadastrado fica no
campo ObjetoId, e o número do grupo cadastro fica no campo GrupoId.
A
próxima tabela para criar vínculo é a usuário grupo, ou seja, vincular o
usuário cadastro ao grupo. Para isso criei a tabela chamada UsuarioGrupo.
Tabela: UsuarioGrupo
Campos:
- UsuarioId (int) notnull
- GrupoId (int) notnull
Depois
de criar estas tabelas ficou simples fazer o select. Para facilitar, vou
colocar o select abaixou para carregar o menu do usuário que acabou de logar no
sistema.
Select
que retorna o menu para o usuário
Select distinct Obj.*
From Objeto Obj
Inner join GrupoObjeto gob on obj.objetoId = gob.objetoId
Inner Join Grupo gru on gob.grupoId = gru.grupoId
Inner Join UsuarioGrupo ugp on ugp.grupoId = gru.grupoId
Where ugp.usuarioId=(NUMERO_DO_USUARIO_ID)
Order by obj.Ordem
Select 1.1
Este select retorna o menu de acordo com o
usuário logado e com ele basta construir o código para mostrar em tela.
Codificando
Agora vamos codificar o menu para ser mostrado em tela. Para facilitar,
eu vou criar uma classe chamada Sessão, que carrega todas as sessões do meu
sistema, inclusive a sessão de menu.
Esta
classe sessão só tem get e set.
public static DataTable Menu { get { try { return (DataTable)HttpContext.Current.Session["Session:MENU"]; } catch { return null; } } set { HttpContext.Current.Session["Session:MENU"] = value; } }
public static decimal UsuarioId { get { try { return Conversion.ToDecimal(HttpContext.Current.Session["Session:USUARIOCOD"]); } catch { return 0; } } set { HttpContext.Current.Session["Session:USUARIOCOD"] = value; } }
Depois que o
usuário entrar no sistema com usuário e senha, eu preciso buscar o menu e
chamar o select 1.1. O retorno dela eu atribuo para a classe sessão atribuindo
o menu.
Sessao.Menu = new ObjetoBRL().BuscaObjetosDoUsuario(Sessao.UsuarioId);
Assim,
eu fico com a sessão menu preenchida para montar na tela.
Na próxima parte do artigo veremos o restante da codificação. Espero que tenha entendido e
gostado, qualquer dúvida pode entrar em contato.
artigo publicado originalmente no iMasters, por Maurício Junior
|
Uma das tarefas mais importantes para os
engenheiros/analistas/programadores de software é a escolha da
linguagem que irão utilizar para realizar o trabalho da "melhor forma
possível". Acho importante enfatizar a "melhor forma possível" com
aspas, pois ela varia de acordo com uma série de parâmetros que
geralmente estão ligados à época (arquitetura dominante, teoria e até
modismo ...), filosofia da empresa e/ou do sistema, quesitos como performance, estabilidade, funcionalidade, segurança, user friendliness etc. Portanto, a "melhor forma possível" varia dependendo do referencial.
Dito isso, vou escrever um pouco sobre Programação Orientada a Objetos (OOP),
que é provavelmente a principal razão pela qual estamos interessados em
diferenciar linguagens baseadas em objetos e orientadas a objetos.
A OOP
é um paradigma (padrão a ser seguido) que utiliza objetos para
construir programas de computador. Apesar de haver muita controvérsia
sobre o assunto, muitas vezes a OOP está relacionada à
"melhor forma possível" de se programar, principalmente quando ela
resulta de uma simples e coerente compreensão da realidade sob o ponto
de vista da Análise Orientada a Objetos (OOA), tornando o Design Orientado a Objetos (OOD) consistente, o que, por fim, facilita a OOP,
resultando em programas claros e fáceis de manter.
Entretanto, nem
sempre uma modelagem da realidade pode ser expressa através de objetos,
ou simplesmente talvez não seja a melhor forma de fazê-lo. Existem
vários dilemas e casos onde, dependendo do que se busca, não vale a
pena utilizar OO. Nesse ponto, não posso deixar de citar os artigos "Why OO Sucks" de Joe Armstrong, criador da linguagem Erlang; "Bad Engineering Properties of Object-Oriented Languages" de Luca Cardelli, principal pesquisador e líder dos grupos "Programming Principles and Tools" e "Security" na Microsoft Research em Cambridge; e o desabafo de Richard Stallman, criador do projeto GNU e fundador da Free Software Foundation, no Google Group comp.emacs.xemacs,
que diz que "adicionar OOP no Emacs não é claramente uma melhoria; usei OOP quando
trabalhava no sistema de janela da Lisp Machine e não concordo com a
visão usual de que ela seja uma forma superior de se programar." (ver thread original "Mode inheritance, cloning, hooks & OOP").
Dado ests breve overview sobre OOP, seguirei o artigo escrevendo mais um pouco sobre objetos, OOA, OOD
e depois entrarei no tema principal que é "Linguagens: Baseada em
Objetos e Orientada a Objetos", mas antes disso segue abaixo o lembrete
que alguns já conhecem, mas outros não.
Para os que ainda não sabem, este é o quarto artigo de uma série que
me comprometi a escrever para o iMasters. Segue abaixo a relação dos
artigos:
- ASP, uma tecnologia mal interpretada.
- Programação orientada a eventos e lambda function em ASP/VBScript.
- TDD (Test Driven Development) em ASP/VBScript.
- Linguagens: Baseada em Objetos e Orientada a Objetos.
- Orientação a Objetos em VBScript "Hackers way".
- Scripting Components, os "Às" na manga.
- Caching, conceito de DRY(Don't Repeat Yourself) aplicado ao ASP.
Se você estiver lendo um artigo meu pela primeira vez, recomendo
enfaticamente que leia os anteriores primeiro, pois estou tentando
levá-los à compreensão de uma grande abstração, contando uma pequena
parte da ideia por vez. Colocarei links para os temas anteriores para
facilitar o acesso, mas utilizem CTRL+Click, pois não há links de um artigo para seus sucessores.
O que é um objeto?
Sinto um certo desconforto por ter utilizado demasiadamente o termo
objeto sem antes assegurar uma noção do conceito ao leitor. Portanto,
esta seção remedia a situação.
Existem várias definições para objeto, tais como a de Booch (1991), um dos criadores do UML:
"Um objeto tem um estado, comportamento e identidade; a estrutura e o
comportamento de objetos semelhantes são definidos em sua classe comum;
os termos instância e objetos são intercambiáveis".
Essa é uma
definição muito restritiva que se aplica apenas a "linguagens
orientadas a objetos clássicas" como Java, C#, C++ e outras em acordo
com a definição de Coplien (1992) onde "classes desempenham um papel
central na modelagem de objetos", uma vez que em linguagens de prototyping ou delegates
elas não têm este papel. Há também definições mais abrangentes como a
de Cox (1991), "quaquer coisa com uma fronteira razoavelmente (crisply)
definida" que servem a um domínio mais amplo (extrapolam o mundo
computacional), mas que, embora descreva objetos, também descreve
ideas, distribuições etc.
Entretanto, essa é um boa definição quanto
aumentada para um domínio específico. É o caso de Rumbaugh (1991):
"Nós
definimos um objeto como um conceito, abstração ou coisa com uma
fronteira razoavelmente (crisp) definida com significado para o problema em questão".
Quando isso ocorre, o desenvolvedor precisa parar, pensar, rever
seus conceitos e decidir exatamente onde quer chegar antes de seguir
adiante. No meu caso, gosto de buscar minhas inspirações na filosofia
oriental. Veja abaixo uma citação de Confúcio:
"É por respeitar a natureza virtuosa que o homem verdadeiro
dedica-se a aprender o Tao. Examinando em conjunto e por miúdo; do
máximo da claridade encontra o caminho do meio. É por retomar os
antigos que se descobre o novo e, com isto, honra os Ritos."
Na busca pelo caminho do meio em programação, não querendo ser
genérico nem especializado demais, nem almejando uma guerra de chamas
contra os antigos pela busca da definição ideal, utilizarei
simplesmente uma versão atenuada de objetos derivada da definição de
Booch mesclada à de Rumbaugh: "Um objeto é uma estrutura que possui
estados, comportamentos, identidade e possui algum significado para o
problema em questão", que é a de Booch (1991) sem as restrições e
consequências relacionadas ao uso de classes, unida à de Rumbaugh (1991),
trocando-se a parte de fronteira por estados e comportamentos. Essa
definição é melhor nos dias atuais, pois engloba outros conceitos que
surgiram para trabalhar com objetos que não o de classe.
OOA, OOD?
Apesar das raízes de objetos em computação datarem do final da
década de cinquenta em trabalhos do grupo de inteligência artificial no
MIT e, posteriormente, conceituados formalmente para programação com a introdução do Simula 67 na década de sessenta. Os temas OOA e OOD só se tornaram assuntos relevantes de pesquisa na década de noventa, quando a OOP
se tornou a metodologia de programação dominante, possivelmente
impulsionada pelo C++, Visual FoxPro 3.0 e pelo sucesso das interfaces
de usuário gráficas, que são fortemente baseadas em técnicas de
programação orientada a objetos.
Portanto, não é surpreendente que uma das maiores autoridades neste
assunto seja Peter Coad, autor dos livros "Object Oriented Analysis"
(1990) e "Object Oriented Design" (1991) entre outros. Para ele, "OOA
é o desafio de entender o domínio do problema e depois as
responsabilidades do sistema sob esta luz." ou, em outra palavras, "...
análise é o estudo do domínio de um problema, levando à especificação
de um comportamento externamente observável; uma completa, consistente
e viável declaração do que é necessário; uma cobertura funcional e
quantificada das características operacionas (por exemplo
confiabilidade, disponibilidade, performance)" e OOD (...)
" é a prática de tomar uma especificação de um comportamento
externamente disponível e adicionar detalhes necessários para sua
implementação em sistemas de computador, incluindo detalhes sobre
interação humana, gerenciamento de tarefas e gerenciamento de dados".
Enfim, por que toda essa história é importante? A progressão usual de OOA para OOD para OOP corresponde aproximadamente ao modelo de desenvolvimento conhecido como Waterfall de Royce (1970), e as metodologias OO modernas praticamente buscam reduzir os problemas principais desse modelo, tais como os listados por Humphrey (1989):
- Ele não responde adequadamente a mudanças.
- Ele assume um sequência relativamente uniforme e ordenada das etapas de desenvolvimento.
- Ele não prevê métodos como prototipagem rápida ou linguagens avançadas.
Essas e outras dificuldades levaram pessoas como Barry Boehm e Tom Gilb a criarem alternativas como o "Spiral Model" e o "Incremental Model"
de sua autoria, na respectiva ordem. A aparição desses novos modelos
certamente influenciou Coad (1991) a apresentar o seguinte resumo do
ciclo de desenvolvimento:
Waterfall
Spiral [Boehm, B. Spiral Model, 1988]
- Análise, prototipagem, gerenciamento de risco
- Design, prototipagem, gerenciamento de risco
- Programação, prototipagem, gerenciamento de risco
Incremental [Gilb, T. Principles of Software Engineering Management, 1988]
- Um pouco de Análise
- Um pouco de Design
- Um pouco de Programação
- Repita
Esses modelos alternativos são a origem das metodologias de OO
modernas, cujos enfoques variam de acordo com a vontade dos seus
"criadores". Atualmente a moda é enfatizar o desenvolvimento
incremental, iterativo, evolucionário, concorrente e a "natureza
situacional do software". Um bom exemplo é o Manifesto Ágil".
Portanto, para desenvolver software é importante, além de conhecer as várias metodologias, ter uma compreensão profunda sobre OOA e OOD, uma vez que muitos dos problemas podem ser modelados através de OO. Mais que isso, para ser um bom gerente e teórico da ciência do desenvolvimento de software, o importante de facto
é jamais esquecer que somos todos humanos e queremos viver bem em
sociedade.
Todas as pessoas querem ter onde morar, o que comer, como se
divertir e ainda manter isso ao longo da vida. Por isso, não colocar
nenhum indivíduo em má posição perante seus superiores; permitir que
ele participe da resolução do problema; saber que às vezes as
necessidades mudam com o tempo e entregar sistemas que cumprem sua
tarefa é o que importa no final das contas; porque, de forma geral, é o
que aproxima as pessoas envolvidas no projeto e assegura que as
vitórias ou derrotas sejam compartilhadas de forma coletiva.
Isso pode
parecer bobagem e algo que todas as pessoas já sabem, mas o tema é tão
crítico que é colocado como diferencial em novas metodologias. Quem não
leu "Individuals and interactions over processes and tools" ou "Customer collaboration over contract negotiation"?
Bastaria que as pessoas no mundo sentissem mais empatia para que não
precisássemos "descobrir" algo que deveria ser natural para uma espécie
dita social.
Linguagens Baseada em Objetos e Orientada a Objetos
Atualmente é bem aceito que: "object-oriented = data abstractions + object types + type inheritance" (OO). Tanto Cardelli (1985), Wegner (1985), como Booch (1991) chegaram a este consenso.
Mais tarde, Booch (1994) separou object types em encapsulation e modularity e chamou type inheritance de hierarchy.
Imagino que Booch fez isso possivelmente para enfatizar que os objetos
muitas vezes, para modelar melhor a realidade, possuem um estado
interior ao qual o mundo externo não possui acesso (encapsulation).
Imagine a tarefa de modelar uma pessoa sem levar em consideração o
"encapsulamento": a pessoa simplesmente seria incapaz de mentir sobre
seu estado atual, todos saberiam se a pessoa está realmente feliz ou
infeliz. Não haveria os mistérios do tipo "A vida dela era tão
perfeita, por que será que ela se matou?". Parece-me, portanto, que é
válido permitir que a modelagem de objetos em programação também
selecione quais estados o mundo exterior terá acesso e também que este
acesso seja filtrado antes da informação ser emitida. Quantas vezes já
perguntamos para uma pessoa querida: "Tudo bem com você?" e ouvimos:
"Tudo bem...", mesmo quando a situação era difícil...
Além desses requisitos, existem outras três características (pure)
que geralmente são verificadas para classificar uma linguagem puramente
orientada a objetos (mas se não é pura, ela não é, ok?):
- Todos os tipos pré-definidos são objetos.
- Todas as operações são realizadas através do envio de mensagens a objetos.
- Todos os tipos definidos pelo usuário são objetos.
Esse conjunto de requisitos, somado à hipótese de que uma linguagem
só é orientada a objetos se todas essas características estão presentes
na linguagem de forma explícita; isto é, sem ter que escrever uma
plataforma ou utilizar convenções de codificação para suprir todos os
requisitos; é o que nos permite diferenciar linguagens baseadas em
objetos e orientadas a objetos.
Antes de começar a citar algumas linguagens famosas e o porquê de elas
serem orientadas a objetos ou não, gostaria de enfatizar que a OOP
existe independentemente do fato de a linguagem ser orientada a objetos,
pois para isso basta que a linguagem e a forma de se programar utilizem
como base "data abstractions + object types + type inheritance".
Outro fato que acho interessante é o grande número de pessoas que
discutem e brigam, tentando defender que a sua linguagem é orientada a
objetos. Gente, ser uma linguagem orientada a objetos não é uma característica que faz a linguagem ser melhor do que as outras. Nem
a programação orientada a objetos, nem a linguagem ser orientada a
objetos são garantias de qualidade. Muito pelo contrário, se apegar
tanto a uma forma de pensar e escrever traz algumas vantagens para os
iniciantes, mas existem também desvantagens que só aparecem sob a luz
da experiência no desenvolvimento de muitos sistemas conceitualmente
diferentes e experimentação de muitas linguagens.
Acho que uma
analogia pertinente é a questão: "Linguagens (humanas) só de
ideogramas, como o chinês, são melhores do que linguagens sem nenhum
ideograma, como o português?" e a resposta, embora eu não saiba, é que
vejo tanto chineses como portugueses se expressando muito bem, não
importando qual conjunto de regras impostas pela linguagem.
Aliás,
vivemos atualmente um forte retorno à iconografia. Basta você escrever
:) no messenger que automaticamente a pessoa com quem você
está conversando sabe seu estado emocional (feliz), não é verdade? Não
seria a utilização dos emoticons uma evidência de que os ideogramas tem seu espaço na comunicação? Ou a escrita japonesa que possui tanto Kanjis (ideogramas) quanto Hiraganas e Katakanas (esses dois últimos como se fossem sílabas) um exemplo da vantagem do "multi-paradigmatismo"?
Dito isso, acendam a fogueira para queimar o herege, vamos utilizar
a plataforma de diferenciação de linguagens baseadas em objetos e
orientadas a objetos definida acima.
Linguagens como Smalltalk, Ruby, C#, Scala e Fantom são orientadas a objetos, pois satisfazem aos seis critérios. Algumas linguagens como C++ e Javascript são multi-paradigma e possuem mecanismos nativos para implementar OO,
mas não se preocupam em satisfazer todas as características.
C++, por
exemplo, utiliza tipos nativos e Javascript que apenas não se preocupa
com encapsulation de forma explícita por não precisar, pois o mesmo efeito é obtido através da utilização correta de closures. Java e Python geralmente esperneiam dizendo que são orientadas a objetos, mas elas não satisfazem as características (pure).
Java, por exemplo, faz uso de tipos nativos e Python possui algumas
operações interessantemente implementadas como globais.
Visual Basic,
VBScript, PHP, Perl também não são por vários motivos, apesar de
oferecerem um suporte básico para programadores buscando OOP. Outras linguagens como C, Lisp e Erlang nem sequer se importam em ser ou parecer orientadas a objetos.
That's all folks. Espero que vocês tenham gostado do artigo e até a próxima, onde mostrarei algumas formas de como programar OOP em VBScript.
Links interessantes na web
Referências Bibliográficas
- Booch, G. Object-Oriented Analysis and Design, with Applications (2nd Ed.), 1994
- Booch, G. Object Oriented Design, 1991
- Coad, P. Object Oriented Design, 1991
- Coplien, James O. Advanced C++ Programming Styles and Idioms, 1992
- Cox, Brad J. Object Oriented Programming: An Evolutionary Approach, 1991
- Humphrey, W. Managing the Software Process, 1989
- Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F., & Lorensen, W. Object-Oriented Modeling and Design, 1991
artigo publicado originalmente no iMasters, por Fabio Nagao
|
Na primeira parte deste artigo, apresentei os conceitos básicos sobre o código EAN 13 e EAN 8 (fonte wikipédia). Agora vou mostrar dois projetos completos que permitem gerar os códigos de barras EAN:
1. Projeto C# para gerar e imprimir código de barras EAN-13

2. Projeto VB .NET para gerar código EAN8 e EAN13

Cabe a você adaptar os códigos dos projetos à sua necessidade. A maior parte do trabalho já foi feita o resto é por sua conta.
*** Artigo de José Carlos Macoratti
|
Às vezes, um programador virá a mim e explicará que ele não
gosta do design de alguma coisa e que “vamos precisar fazer um monte de
refatoração” para fazer a coisa direito. Isso não parece bom. E não
parece refatoração ou…
Confira o novo refcard de refatoração! – Interrupção do curador DZone.
Refatoração, como originalmente definido por Martin Fowler e Kent Beck, é:
Uma alteração feita na estrutura interna do software para
torná-lo mais fácil de entender e mais barato para modificar sem
alterar seu comportamento observável… É uma forma disciplinada de limpar
código que minimiza as chances de introduzir bugs.
A refatoração é feita para preencher atalhos,
eliminar a duplicação e código legado e para tornar o design e a lógica
claros. Para tornar melhor e mais claro o uso da linguagem de
programação. Para tirar proveito das informações que você tem agora, mas
que o programador não tem – ou das quais eles ainda não tiraram
proveito. Simplifique sempre o código e torne-o mais fácil de
compreender. Sempre o torne mais fácil e seguro para alterar no futuro.
Corrigir quaisquer bugs que você encontrar pelo caminho não é refatoração. Otimização não é refatoração.
Intensificar o tratamento de erros e adicionar um defensive code não é
refatoração. Tornar o código mais testável não é refatoração - embora isso possa acontecer como resultado de refatoração. Todas essas são coisas boas para fazer. Mas não são refatoração.
Os programadores, especialmente os de manutenção de código, sempre
limpam o código como parte de seu trabalho. É natural e muitas vezes
necessário para realizar o trabalho. O que Martin Fowler e outros
fizeram foi formalizar as práticas de reestruturação de código, e documentar um catálogo de padrões comuns e comprovados de refatoração – as metas e as etapas.
Refatoração é simples. Proteja-se de cometer erros ao fazer testes
primeiramente onde você puder. Faça mudanças estruturais para o código
em pequenos passos, etapas independentes e seguras, e teste o código
depois de cada uma dessas etapas para garantir que você não tenha mudado
o comportamento – ainda funciona da mesma maneira, apenas parece
diferente. Os padrões e as ferramentas de refatoração em IDEs modernas
tornam a refatoração fácil, segura e barata.
A refatoração não é um fim em si mesmo
A refatoração deveria ser uma prática que suporta fazer alterações ao código. Você refatora o
código antes de fazer alterações, para que você possa confirmar a sua
compreensão do código e torná-lo mais fácil e mais seguro de aplicar a
sua mudança. Faça testes de regressão no seu trabalho de refatoração.
Então, faça suas correções ou alterações. Teste novamente. E depois,
talvez, refatore um pouco mais o código para tornar a intenção das
mudanças mais claras. E teste tudo novamente. Refatorar, em seguida, mudar. Ou mudar, então refatorar.
Você não decide refatorar. Você refatora porque você quer fazer outra coisa, e a refatoração ajuda a fazer essa outra coisa.
O escopo do seu trabalho de refatoração deve ser conduzido pela
mudança ou pela correção que você precisa fazer – o que você precisa
fazer para tornar a mudança mais segura e mais limpa? Em outras
palavras: não refatore pelo bem da refatoração. Não refatore o código
que você não está mudando ou se preparando para mudar.
Refatorando do zero para compreender
Existe também a refatoração do zero da obra Working Effectively with Legacy Code,
de Michael Feather, o que Martin Fowler chama de “Refatorar para
compreender”. É aqui que você pega o código que você não entende (ou não
suporta) e o limpa de modo que você possa ter uma ideia melhor do que
está acontecendo antes de começar a realmente trabalhar para mudá-lo de
verdade, ou para ajudar a depurá-lo. Renomeie variáveis e métodos, uma
vez que você descobrir o que eles realmente querem dizer. Apague o
código que você não quer ver (ou acha que não funciona), quebre
instruções condicionais complexas, quebre rotinas longas em outras
menores que você possa compreender.
Não se preocupe em analisar e testar todas essas mudanças. A meta é
se mover rapidamente – este é um protótipo rápido e sujo para te dar uma
visão do código e como ele funciona. Aprenda com ele e jogue fora. A
refatoração do zero também permite testar abordagens de refatoração
diferentes e aprender mais sobre as técnicas de refatoração.
Michael Feathers recomenda que você mantenha notas sobre isso em
qualquer coisa que não seja óbvia ou que foi especialmente útil, para
que você possa voltar e fazer um bom trabalho mais tarde – em passos
pequenos, disciplinados, com testes.
E a refatoração em larga escala?
Você pode obter um grande retorno em entendimento e manutenção
fazendo alterações de refatoração simples e óbvias: elimine a
duplicação, mude nomes de variáveis e de método para ser mais
significativo, extraia métodos para tornar o código mais fácil de
entender e mais reutilizável, simplifique a lógica condicional,
substitua um número mágico com uma constante, mova o código comum em
conjunto.
Existe uma grande diferença entre refatoração menor em linha como
esta e reestruturação de design mais fundamental – o que Martin Fowler
se refere como “Refatoração grande”. Mudanças grandes e dispendiosas que
carregam uma série de riscos técnicos. Isso não é limpeza de código e
melhorar o design enquanto você está trabalhando: isso é redesign
fundamental.
Algumas pessoas gostam de chamar de redesign ou reescrever ou replatforming ou reengenharia de um sistema de “Refatoração em larga escala”
porque tecnicamente você não está mudando o comportamento – a lógica do
negócio e as entradas e saídas permanecem as mesmas; “apenas” o design e
a implementação estão mudando. A diferença parece ser que você pode
reescrever o código ou até mesmo todo um sistema e, desde que faça isso
em etapas, você ainda pode chamá-lo de “refatoração”, mesmo que você
esteja lentamente encapsulando um sistema legado com o novo código, ou fazendo alterações de grande escala na arquitetura de um sistema.
As mudanças de refatoração em larga escala podem ser
feias. Elas podem levar semanas ou meses (ou anos) para completar,
exigindo mudanças em várias partes diferentes do código. Eles precisam
ser discriminados e lançados em várias etapas, exigindo andaimes
temporários e desvios, especialmente se você estiver trabalhando em
pequenos sprints Agile. É aqui que as práticas como Branch por abstração entram em ação, para ajudar você a gerenciar alterações dentro do código por um longo período de tempo.
Nesse meio tempo, você tem que continuar trabalhando com o código
antigo e com o novo juntos, tornando o código mais difícil de seguir e
mais difícil de mudar, mais frágil e cheio de bugs – o oposto do que
refatoração deve alcançar. Às vezes, isso pode continuar para sempre – o
trabalho de transição nunca é concluído porque a maioria dos benefícios
é realizada mais cedo, ou porque o consultor que deu a ideia saiu para
fazer outra coisa, ou o orçamento foi cortado, e você está preso na
manutenção de um Frankensystem (um sistema Frankenstein).
Isto é refatoração – aquilo não é
Misturar esse tipo de projeto pesado desenvolvido com a disciplina de
refatoração-as-you-go é errado. Eles são fundamentalmente tipos
diferentes de trabalho, com custos e riscos muito diferentes. Ele se
confunde com o que as pessoas pensam que refatoração é, e como a
refatoração deve ser feita.
Refatorar pode e deve ser apresentada na forma como você escreve e
mantém o código – uma parte da disciplina diária de desenvolvimento,
como a escrita de testes e a revisão de código. Isso deve ser feito em
silêncio, de forma contínua e implicitamente. Torna-se parte do custo de
fazer o trabalho, mostrando as estimativas e as avaliações de risco.
Feito corretamente, ele não precisa ser explicado ou justificado.
Refatoração que leva alguns minutos ou uma hora ou duas, como parte de uma mudança, é apenas parte do trabalho. Refatoração que pode levar vários dias ou mais não é refatoração, e sim reescrita ou redesign. Se você tiver que reservar blocos explícitos de tempo (ou um sprint inteiro!) para refatorar
código, se você tiver que obter permissão ou fazer um caso de negócio
para limpeza de código, então você não está refatorando – mesmo se você
estiver usando técnicas de ferramentas de refatoração, você está fazendo outra coisa.
Alguns programadores acreditam que é direito e responsabilidade deles
fazer alterações fundamentais e importantes para o código, reinventar e
reescrevê-lo em nome da refatoração e para o bem do futuro e para a sua
arte. Às vezes, o correto é fazer o redesign e a reescrita do código.
Mas seja honesto e claro. Não esconda isso com o nome de refatoração.
***
Texto original disponível em http://agile.dzone.com/articles/what-refactoring-and-what-it-0
|
Neste artigo, veremos como criar arquivos PDF em aplicações ASP .NET usando a
linguagem VB .NET. Para realizar essa tarefa,
vamos precisar de uma ajuda. Estou me referindo à biblioteca iTextSharp, que é gratuita e pode ser obtida no seguinte endereço: http://sourceforge.net/projects/itextsharp/.
Então, primeiro faça o download da
library para poder referenciá-la em seu projeto web. Eu fiz o
download da library e a descompactei em: C:\Program
Files\itextsharp-5.0.4-dll
Para demonstrar como usar esse
recurso, vou usar o Visual Web Developer 2008 Express Edition e criar um novo web site (New Web Site) usando o template ASP .NET Web Site chamado ASPNET_PDF
usando a linguagem Visual Basic. (poderíamos ter usado a
linguagem C#). 
Agora vamos referenciar a library iTextSharp
em nosso projeto:
No menu WebSite,
selecione Add Reference e, em seguida, clique na
aba Browse da janela Add Reference e localize o lugar onde você descompactou a
biblioteca iTextSharp, selecionando o arquivo itextsharp.dll
e clicando em OK. 
Agora vamos definir o
seguinte leiaute no arquivo Default.aspx:
Através do menu Table
-> Insert Table, inclua uma tabela com 5 linhas e 2
colunas e, a seguir, inclua os seguinte controles na tabela:
- TextBox - txtTextoPDF
- TextBox -
txtNomeArquivoPDF
- Button - btnGerarPDF

Agora no arquivo
code-behind Default.aspx.vb vamos definir os
namespaces usados no projeto:
- Imports System
- Imports System.IO
- Imports iTextSharp.text
- Imports iTextSharp.text.pdf
No evento Click do
botão de comando btnGerarPDF, vamos fazer a
chamada da rotina que iremos criar para gerar o arquivo PDF:
Protected Sub btnGerarPDF_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGerarPDF.Click gerarPDF(txtTextoPDF.Text, txtNomeArquivoPDF.Text) End Sub
A rotina gerarPDF()
está usando o texto a ser gerado no arquivo PDF e o nome do
arquivo pdf que será gerado.
A rotina gerarPDF()
possui o seguinte código:
Private Sub gerarPDF(ByVal texto As String, ByVal arquivo As String)
Dim hoje As DateTime = DateTime.Now
If (arquivo.Contains(".pdf")) Then arquivo = arquivo.Replace(".pdf", "") End If
Dim arquivoPDF = arquivo & hoje.Millisecond & ".pdf"
Dim doc As Document = New Document PdfWriter.GetInstance(doc, New FileStream(Request.PhysicalApplicationPath + "\" & arquivoPDF, FileMode.Create)) doc.Open() doc.Add(New Paragraph(texto)) doc.Close() Response.Redirect("~/" & arquivoPDF)
End Sub.
Vamos entender o código acima.
Na primeira parte do código, estou
verificando se o nome do arquivo informado possui a extensão
.pdf; nesse caso, eu removo a extensão.
A seguir, eu monto o nome do arquivo,
adicionando os milissegundos da data obtida para, dessa forma, ter
um nome único de arquivo a cada geração.
A seguir é que entra a criação do
arquivo PDF:
- criamos uma instância de um
documento através da classe Document;
- criamos um arquivo PDF usando o
nome gerado usando a propriedade Request.PhysicalApplicationPath,
que obtém o caminho do Sistema de arquivos físicos do diretório
raiz do aplicativo de servidor atualmente em execução. Dessa
forma, os arquivos serão gerados na raiz da aplicação;
- abrimos o documento e incluímos o
texto informado, e depois fechamos o documento;
- para exibir o documento, usamos o Response.Redirect.
Na figura a seguir, vemos o resultado
do arquivo PDF gerado sendo exibido: 
Viu como é simples gerar arquivos
PDF em aplicações web usando o iTextSharp? É
claro que existem outros recursos que não foram mostrados,
através dos quais podemos gerar documentos mais complexos, mas
eu pretendo mostrar isso em outro artigo.
Até o próximo artigo ASP .NET.
Pegue o projeto completo
aqui: ASPNET_PDF.zip
Eu sei, é apenas ASP .NET,
mas eu gosto...
artigo publicado originalmente no iMasters, por José Carlos Macoratti
|
Caro leitor, hoje eu vou falar e mostrar como criar gráficos
dinâmicos usando a linguagem C#, da Microsoft. O gráfico será criado
usando uma API do Google, que em resumo utiliza JavaScript e HTML5.
Utilizado para desenvolvimento:
- Ferramenta Visual Studio 2012
- Linguagem C#
- API do Google para gerar gráfico
Não é difícil criar gráficos de linha, de pizza e de blocos. O Google mesmo te ajuda a desenvolver esses tipos de gráficos. Nesse site você consegue utilizar as ferramentas sem qualquer problema.
Inclusive, o Google mostra alguns códigos fontes criados como
exemplo. O problema é o código HTML, JavaScript e C#. A dificuldade que
tive foi juntar o código C# com o HTML. Depois de vários testes,
consegui criar o gráfico pegando os dados do banco de dados. Agora vou
mostrar pra vocês como eu fiz isso.
Eu não vou mostrar aqui como pegar os dados do banco de dados, a
única coisa que precisa é de um “DataTable” ou uma variável do tipo
“numérica” mesmo. Com o “DataTable” basta fazer o “loop” usando “for” e
pronto.
Quando você cria a página .aspx no seu projeto, o primeiro passo é importar o arquivo JavaScript no topo da página. Listagem 1.
Listagem 1 – Importando JavaScript
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
O segundo passo é adicionar o componente literal na página. Listagem 2.
Listagem 2 – Literal
<asp:Literal id="ltlResultado" runat="server" />
O terceiro passo é adicionar um div com id, tamanho e largura. Listagem 3.
Listagem 3 – Adicionando div
<div id="chart_div" style="width:950px; height: 550px;"></div>
Até agora, o código escrito foi apenas o HTML dentro do arquivo
.ASPX. O próximo passo é escrever o código em C#. Listagem 4. Em
qualquer parte do código você pode chamar o método para gerar o gráfico.
No nosso caso, vou fazer no clique do botão Buscar.
Listagem 4 – Código C#
protected void cmdBuscar_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
try
{
DataTable _dt = buscaDados();
if (_dt != null && _dt.Rows.Count > 0)
{
StringBuilder str = new StringBuilder();
str.Append("<script type='text/javascript'>");
str.Append("google.load(\"visualization\", \"1\", { packages: [\"corechart\"] });");
str.Append("google.setOnLoadCallback(drawChart);");
str.Append("function drawChart() {");
str.Append(" var data = new google.visualization.arrayToDataTable([");
str.Append(@" ['Dia', 'Likes'], ");
if (_dt.Rows.Count == 1)
str.Append("['0',0], ");
for (int i = 0; i < _dt.Rows.Count; i++)
{
str.Append("['" + _dt.Rows[i]["dia"].ToString() + "'," +
_dt.Rows[i]["contador"].ToString() + "], ");
}
str.Append(@" ]);
var options = {
colors: ['#4C7951'],
series: {2: {type:'line'}}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>");
ltlResultado.Text = str.ToString().Replace("], ]", "] ]").TrimEnd(',');
}
else
ltlResultado.Text = "<Br><br> Nenhum valor encontrado.";
}
catch (Exception ex)
{
throw ex;
}
}
}
Note que existe uma variável do tipo “StringBuilder” que armazena
todos os dados em JavaScript. No início do código, eu chamo uma classe
para buscar os dados, que retorna um “DataTable”.
No meio do código eu fiz um “for” do “DataTable” e caso exista dado,
começa a escrever os valores. Para escrever os valores, bastou adicionar
o “Append” com os dados em C#. Os meus dados são: dia e contador.
No final do código eu adicionei os valores montados para o componente
literal adicionado no começo do código HTML. Existe o comando “replace”
para retirar a vírgula a fim de imprimir o gráfico corretamente no C#.
A figura 1 mostra como ficou a imagem na página. Os dados apareceram sem qualquer problema.
 gráfico dinamico
Figura 1 – Gerando gráfico
Bom, eu fico por aqui. Qualquer dúvida pode entrar em contato pelo site www.mauriciojunior.org.
|
Programar se aprende programando, certo? E nada
melhor para aprender do que ter um protótipo funcional com o código
fonte a partir do qual podemos estudar.
Este singelo projeto feito na linguagem C# realiza o acesso e as
operações de inclusão, edição e exclusão em uma base de dados SQL
Server.
Vamos ao que interessa...
O projeto poderá ser aberto nos seguintes IDEs:
Além disso você deverá instalar os seguintes recursos:
O banco de dados SQL Server
A aplicação acessa a tabela Livros de um banco de dados SQL Server
definido como Catalogo. Na figura abaixo temos a estrutura da tabela:
 O script para criar o banco de dados, as tabelas e as stored procedures no SQL Server é dado a seguir:
USE [Catalogo] GO /****** Object: Table [dbo].[Autores] Script Date: 03/28/2011 10:52:09 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Autores]( [autorid] [int] IDENTITY(1,1) NOT NULL, [nome] [nchar](10) NULL, CONSTRAINT [PK_Autores] PRIMARY KEY CLUSTERED ( [autorid] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO /****** Object: Table [dbo].[Livros] Script Date: 03/28/2011 10:52:09 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Livros]( [livroid] [int] IDENTITY(1,1) NOT NULL, [autorid] [int] NOT NULL, [titulo] [nvarchar](150) NULL, [preco] [money] NULL, CONSTRAINT [PK_Livros] PRIMARY KEY CLUSTERED ( [livroid] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO /****** Object: StoredProcedure [dbo].[SelAutores] Script Date: 03/28/2011 10:52:08 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[SelAutores] AS SELECT * FROM Autores RETURN GO /****** Object: StoredProcedure [dbo].[SchLivros] Script Date: 03/28/2011 10:52:08 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[SchLivros] AS SELECT * FROM Livros RETURN GO /****** Object: StoredProcedure [dbo].[IncluirAutor] Script Date: 03/28/2011 10:52:08 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: <Author,,Name> -- Create date: <Create Date,,> -- Description: <Description,,> -- ============================================= CREATE PROCEDURE [dbo].[IncluirAutor] @nome nvarchar(150) AS INSERT INTO Autores (nome) Values(@nome) GO
Você pode executar o script acima no SQL Server Management Studio para criar o banco de dados e as tabelas.
A interface da aplicação
A seguir temos a interface da aplicação no formulário form1.cs que utiliza os seguintes controles:
- DataGridView - dgvLista;
- TextBox - txtPesquisar, txtTitulo e txtPreco;
- Button - btnAtualizar, btnSalvar, btnCancelar, btnIncluir, btnDeletar e btnFechar;

O código da aplicação (partes principais)
No início do formulário temos a definição dos namespaces usados no projeto:
using System; using System.Data; using System.Drawing; using System.Windows.Forms; using System.Data.SqlClient;
Note que estamos referenciando o namespace para acessar as classes ADO .NET para o SQL Server.
A
seguir logo após a declaração do formulário temos a definição das
variáveis ADO .NET para conexão com o banco de dados SQL Server:
SqlConnection sqlCon = new SqlConnection(); SqlDataAdapter daLivros = new SqlDataAdapter(); DataSet dsLivros = new DataSet();
A string de conexão usada no programa é a seguinte:
sqlCon.ConnectionString = @"Data Source=.SQLEXPRESS;Initial Catalog=Catalogo;Integrated Security=True";
Se você pretende usar outro banco de dados basta alterar os nomes dessas variáveis conforme o provedor pertinente.
1 - Código da rotina SalvaMudancas() - Esta rotina verifica qual a
ação a ser realizada : inclusão ou edição dos dados. Para incluir
informações é usado os métodos NewRow()/Add e para atualizar os dados
BeginEdit()/EndEdit() e ao final o método Update();
private void SalvaMudancas() { try { SqlCommandBuilder cbLivros = new SqlCommandBuilder(daLivros);
DataTable dtLivros = dsLivros.Tables["tblLivros"]; DataRow drLivros;
if (isIncluirFlag) { drLivros = dtLivros.NewRow();
drLivros["titulo"] = txtTitulo.Text; drLivros["preco"] = Convert.ToDecimal(txtPreco.Text); dtLivros.Rows.Add(drLivros); } else if (isEditarFlag) { drLivros = dtLivros.Rows.Find(dgvLista.SelectedRows[0].Cells[0].Value);
drLivros.BeginEdit(); drLivros["titulo"] = txtTitulo.Text; drLivros["preco"] = Convert.ToDecimal(txtPreco.Text); drLivros.EndEdit(); }
daLivros.Update(dsLivros, "tblLivros"); formataGridView(); } catch (Exception ex) { MessageBox.Show(ex.Message.ToString()); }
AtualizaDataSet();
SetButtons(true); SetEnabled(false); }
2 - Código do botão Deletar - O código utiliza o método Find e a
seguir o método Delete; ao final para persistir as alterações usa o
método Update();
private void btnDeletar_Click(object sender, EventArgs e) { if (MessageBox.Show("Tem certeza?", "Deletar", MessageBoxButtons.YesNo) == DialogResult.Yes) { try { DataTable dtLivros = dsLivros.Tables["tblLivros"]; DataRow drLivros;
if (dgvLista.SelectedRows.Count > 0) { drLivros = dtLivros.Rows.Find(dgvLista.SelectedRows[0].Cells[0].Value); drLivros.Delete();
SqlCommandBuilder cbLivros = new SqlCommandBuilder(daLivros);
daLivros.Update(dsLivros, "tblLivros"); AtualizaDataSet(); } } catch (Exception ex) { MessageBox.Show(ex.Message.ToString()); } } }
3 - Código do evento Click do DataGridView
private void dgvLista_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex > -1) { txtTitulo.Text = dgvLista.Rows[e.RowIndex].Cells[2].Value.ToString(); txtPreco.Text = dgvLista.Rows[e.RowIndex].Cells[3].Value.ToString(); } }
No evento Click do controle DataGridView estamos obtendo os valores
para o titulo e preco do livro e exibindo nos controles de formulário.
Executando o projeto iremos obter:
 Enfim
uma aplicação simples mas que mostra como você pode realizar a
manutenção dos dados acessando um banco de dados SQL Server.
Pegue o projeto completo aqui: AcessoSQLServer_CSharp.zip
Eu sei é apenas C# , mas eu gosto...
artigo publicado originalmente no iMasters, por José Carlos Macoratti
|
Começarei definindo o relacionamento de Muitos para Muitos MySQL (Experts podem pular para o próximo parágrafo).
O que é um relacionamento de Muitos para Muitos MySQL
Um relacionamento de Muitos para Muitos MySQL é um relacionamento que é multi-valorizado em ambas as direções.
Esse tipo de relacionamento é auxiliado pelo uso de uma tabela de ligação. Por exemplo, uma Pergunta (Question) pode ter mais de uma Categoria (Categorie), e uma Categoria pode ter mais de uma Pergunta. CREATE TABLE link (
Question_id int unsigned NOT NULL,
Category varchar(20),
PRIMARY KEY (`Question_id `,` Category`),
KEY `category_question` (`Category`,`Question_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------+---------------+
| Question_id | Category |
+-------------+---------------+
| 1 | Animals |
| 1 | Business |
| 1 | Vehicles |
| 2 | Animals |
| 3 | Business |
| 3 | Vehicles |
| 4 | Animals |
| 4 | Vehicles |
| 5 | Business |
+-------------+---------------+ Essa é uma tabela de ligação chamada link, que nos ajuda a juntar relacionamentos entre as duas tabelas, Perguntas e Categorias.
Como podemos ver, essa tabela está refletindo um relacionamento de muitos para muitos (a pergunta 1 tem as categorias Animais, Negócios e Veículos – ‘Animals, Business and Vehicles’. A categoria Animais tem as perguntas 1, 2 e 4). O que é o problema de relação de exclusão?
Dada uma tabela de relacionamento de muitos para muitos, como você é capaz de selecionar linhas que não tenham um relacionamento específico? Em termos do exemplo pergunta-categoria, essa pergunta é traduzida no seguinte:
Como você consegue selecionar (digamos as primeiras mil) perguntas que não têm a categoria Negócios. No nosso exemplo, queremos somente que os Question_id 2 e 4 sejam retornados.
Uma solução ruim
Uma solução ruim seria:
SELECT
DISTINCT Question_id
FROM
link
WHERE
Category <> "Business"
ORDER BY
Question_id DESC
LIMIT
1000; Essa consulta irá funcionar se uma pergunta somente for permitida uma categoria. No nosso caso, como uma pergunta tem pelo menos uma categoria, desde que uma pergunta esteja associada à outra categoria que não seja Business, ela retornará. Portanto, o resultado dessa consulta é Question_id: 1, 2, 3, e 4 , que não satisfaz a relação de exclusão.
Primeira solução
SELECT
DISTINCT Question_id
FROM
link
WHERE
Question_id NOT IN (SELECT Question_id FROM link WHERE Category="Business")
ORDER BY
Question_id DESC
LIMIT
1000; A consulta dependente interna (SELECT Question_id FROM link WHERE Category<>”Business”) tem um problema de desempenho – ela será executada pela menos mil vezes e, se ela não for rápida, os atrasos são multiplicados por um número que é, no mínimo, 1.000. Quando o método de acesso (o type field no EXPLAIN statement output) é index_subquery, um index de pesquisa de otimização é usado e um monte de sobrecarga é evitada.
Quando é ampla, a sub query está sendo reexecutada, como é feita para cada linha. Você deve verificar seus . You must check your EXPLAIN details.
Segunda solução
CREATE TEMPORARY TABLE not_wanted_Question_id (
UNIQUE KEY(Question_id)
) ENGINE=MEMORY
SELECT
DISTINCT Question_id
FROM
link
WHERE
Category="Business";
SELECT
DISTINCT link.Question_id
FROM
link
LEFT JOIN
not_wanted_Question_id nw ON (link.Question_id = nw.Question_id)
WHERE
nw.Question_id is NULL
ORDER BY
link.Question_id DESC
LIMIT
1000;
DROP TABLE not_wanted_Question_id; O problema de execução de consultas internas múltiplas é reduzido a uma pesquisa uma única chave dentro de uma tabela na memória, que é basicamente uma pesquisa hash e é muito rápida. No entanto, a construção de perguntas indesejadas pode sair caro para tabelas grandes. Note que criar a tabela, selecionar e então soltar devem ser todos feitos juntos, para toda vez que você precisar dos resultados.
Terceira solução (a melhor em desempenho)Esta é minha melhor solução para esse problema e com melhor desempenho para tabelas pesadas: SELECT
Question_id ,
SUM(IF (Category="Business", 1, 0)) AS exclude
FROM
link
GROUP BY
Question_id DESC
HAVING
exclude=0
LIMIT
10000; Isso funciona muito bem no nosso caso, porque temos um index no Question_id e colunas de categorias. A função SUM está contando o número de ocorrências indesejadas de categoria para cada Question_id na ordem e o statement Having está filtrando-os.
O LIMIT termina os cálculos assim que chega no número limite.
Texto original em ingles de Hazan Ilan, disponível em http://www.mysqldiary.com/a-many-to-many-relationship-table-solving-the-exclude-relation-problem/
|
Na sequência do artigo da semana passada sobre merging e, especificamente, discutindo git merge --no-ff, vamos dar uma olhada em uma estratégia popular de Git conhecido como git flow.
Originalmente publicado como Git Flow: a successful branching model, tornou-se popular em vários projetos maiores, que utilizam branching como uma forma de introduzir características.
Branches de features: o ponto-chave no fluxo git é a criação e
utilização de branches de features. Seu propósito é permitir o
desenvolvimento de recurso paralelo (ou independente), que pode
posteriormente ser merge de volta em um branch consolidado. Claro que
Git é bem adequado para essa tarefa, uma vez que branches são livres
para criar, e o merging pode ser feito facilmente depois.
Branches de features sofrerão um merge de volta para o branch
principal de desenvolvimento, conhecido como develop no git flow. O
ponto-chave com git merge --no-ff é que ele lhe dá um merge node, mesmo
se o branch develop pode ser de, outro modo rápido, fast-foward. Esse
merge node permite que você determine em qual branch você cria a
correção em primeiro lugar.
Embora muitos considerem "feature" um termo amplo, de fato, é bem
possível pensar em uma feature micro também. Alguns desenvolvedores irão
criar um novo branch de feature para cada bug que for arquivado, que
então preserva uma ligação com o bug que foi apresentado em um bug
tracker. (Você também pode usar mensagens de commit arbitrárias para
permitir essa ligação)
Branches de lançamento: uma vez que o branch develop está pronto para
um lançamento, ele é ramificado em um branch (pré)-release. Este é
então utilizado para correções de bugs para apenas esse lançamento (que
sofrerão um merge de volta para o branch develop) em preparação para a
marcação final. Cada branch é nomeado para seu número de versão; assim
release-1.0 seria o branch utilizado para desenvolver o código antes da
versão 1.0 em si. Uma vez que o desenvolvimento da versão 1.0 é
finalizado, ele será marcado e o trabalho no branch release-1.0 será
interrompido. (Git Flow sugere que o branch é excluído nesse momento
para evitar novos trabalhos acidentais nesse branch. Uma vez marcado, é
fácil recriar, se alguma vez for necessário.)
Branches de correção: pode haver a necessidade de lançar uma nova
versão rapidamente (por vezes também conhecido patch releases) para um
problema de produção, mas antes de uma versão maior (ou menor). Branches
de correção são nomeados também para o lançamento (por exemplo
hotfix-1.0.1) e contêm apenas as correções específicas para esse
lançamento. As alterações são mescladas com o branch develop para
garantir que o bug também esteja corrigido em versões posteriores.
Tipicamente, apenas alguns commits existem em branches de correção de
cada vez, já que muitas vezes eles merge de volta para o lançamento.
O que há num nome?
Nenhum desses nomes realmente muda o que você pode conseguir com Git,
afinal, um pode facilmente criar um branch a partir de uma tag, bem
como um branch. Na verdade, o modelo git flow sugere que o trabalho seja
feito contra o branch develop em vez do branch master (que é
convencionalmente o branch principal de desenvolvimento baseado em Git) -
no git flow, o branch master é reservado apenas para as tags liberadas.
No entanto, um ponto chave é que os merge nodes armazenam o nome do
branch de onde eles fizeram merge. Isso significa que se os nomes do
branch são usados, você pode rastrear o fluxo de um recurso do branch de
feature por meio do branch develop e, finalmente, um branch de
lançamento. Há uma ótima imagem (que eu o encorajo a olhar no contexto do artigo original).
Para demonstrar como isso funciona na prática, aqui está uma
sequência abreviada de desenvolvimento no Git Flow e da merge tree
resultante.
(master) $ git log --oneline
4f5da46 Initial Commit
(master) $ git checkout -b develop
Switched to a new branch 'develop'
(develop) $ …
(develop) $ git checkout -b feature1 develop
Switched to a new branch 'feature1'
(feature1) $ …
(feature1) $ git checkout -b feature2 develop
Switched to a new branch 'feature2'
(feature2) $ …
(feature2) $ git checkout develop; git merge --no-ff feature2
Merge made by recursive.
…
(develop) $ git checkout develop; git merge --no-ff feature1
Merge made by recursive.
…
(develop) $ git checkout -b release-1.0 develop
Switched to a new branch 'release-1.0'
(release-1.0) $ echo 1.0 > version; git add version; git commit -m "Version 1.0" version
[release-1.0 c51b802] Version 1.0
(release-1.0) $ git checkout master
Switched to branch 'master'
(master) $ git merge --no-ff release-1.0
Merge made by recursive.
(master) $ git tag -a 1.0
(master) $ git checkout -b hotfix-1.0.1 master
Switched to a new branch 'hotfix-1.0.1'
(hotfix-1.0.1) $ echo 1.0.1 > version; git add version; git commit -m "Version 1.0.1"
…
(hotfix-1.0.1) $ git checkout master
Switched to branch 'master'
(master) $ git merge --no-ff hotfix-1.0.1
Merge made by recursive.
(master) $ git checkout develop
Switched to branch 'develop'
(develop) $ git merge --no-ff hotfix-1.0.1
Merge made by recursive.
(develop) $ git branch -d hotfix-1.0.1
Deleted branch hotfix-1.0.1 (was f43bb33).
Embora os edits acima não possuam qualquer trabalho real contido
nelas, o ponto dos merges nos permite gerar esta pseudo merge tree de
mundo real:
(develop) $ git log --decorate --graph --oneline
* 17e4c5f (HEAD, develop) Merge branch 'hotfix-1.0.1' into develop
|\
| * f43bb33 (hotfix-1.0.1) Hotfix2
| * 50a102d Hotifx1
| * d2fe7d6 Version 1.0.1
| * d534111 (tag: 1.0) Merge branch 'release-1.0'
| |\
* | \ 77e7eac Merge branch 'release-1.0' into develop
|\ \ \
| | |/
| |/|
| * | 9261fad (release-1.0) Release10Fix2
| * | 2562cb3 Release10Fix1
| * | c51b802 Version 1.0
* | | fbdd638 Work6
* | | 7353285 Work5
|/ /
* | 538bb9a Work4
* | cdef254 Merge branch 'feature1' into develop
|\ \
| * | 793b1bc (feature1) Feature1Work4
| * | 3f2be07 Feature1Work3
| * | 7879593 Feature1Work2
| * | 8e01f4d Feature1Work1
* | | 9239c56 Merge branch 'feature2' into develop
|\ \ \
| |_|/
|/| |
| * | 6752543 (feature2) Feature2Work3
| * | d065311 Feature2Work2
| * | 040fcaf Feature2Work1
| |/
| * a9a97be Work3
| * a4253c8 Work2
| * 163c835 Work1
|/
* 4f5da46 Initial Commit
Isso pode parecer confuso, mas podemos condensá-lo usando a flag
--merges flag do git log, o que nos restringe a apenas aos merge nodes:
(develop) $ git log --decorate --graph --oneline --merges
* 17e4c5f (HEAD, develop) Merge branch 'hotfix-1.0.1' into develop
| * d534111 (tag: 1.0) Merge branch 'release-1.0'
* 77e7eac Merge branch 'release-1.0' into develop
* cdef254 Merge branch 'feature1' into develop
* 9239c56 Merge branch 'feature2' into develop
Nesse ponto, o benefício de utilizar --no-ff torna-se claro; é uma
forma de documentar os merges de tal forma que eles poderão ser
filtrados pelo comando git log. Além disso, as convenções de
nomenclatura do Git Flow permitem um conjunto bem descrito de feature e
branches lançamento, que é identificável a partir do gráfico.
Se Git Flow é ou não ideal para você agora, vale a pena estar ciente
do que ele é (e porque ele faz o que ele faz). Mesmo que isso não seja
algo que funcione para você agora, conforme seus repositórios se ampliam
e seu uso do git cresce, pode valer a pena voltar no futuro. Há também
um conjunto de scripts disponíveis no repositório GitHub, o que torna a gestão dos branches individuais mais fácil.
⁂
Texto original de Alex Blewitt, disponível em http://alblue.bandlem.com/2011/11/git-tip-of-week-git-flow.html
|
Na realidade a URL tem a função de endereçar um determinado recurso
na internet, um site, FTP etc. Mas como oportunidade de marketing e
vendas, tornou-se importante a usabilidade, SEO (Otimização dos motores
de busca) e a acessibilidade, assim gerando a melhora da experiência do o
usuário.
Nesse artigo pretendo ensinar uma forma fácil de construir uma função
que fique responsável por formatar a URL, tornando-a dinâmica e
amigável.
Diferente das demais formas de construção de URL´s Amigáveis, essa
forma trabalha com um método de "Alias" (apelidos) para determinado
arquivo ou pasta e possibilita a o envio de variáveis via GET.
Obs.: Esse método está sendo aplicado da forma mais simples possível, justamente para melhor entendimento do processo.
Requerimento:
- Conhecimentos intermediários nas diretivas do Apache;
- Conhecimentos Intermediários em expressão Regular;
- Conhecimentos Intermediários em PHP;
- Apache com o mod_rewrite habilitado.
Primeiramente, criaremos um diretório onde ficará o projeto, vamos chamá-lo de projeto_1.
Dentro desse diretório criaremos três arquivos e um diretório:
- O arquivo .htaccess, onde criaremos a regra de reescrita da url;
- O arquivo main.php, que será responsável dela indexação do site;
- O arquivo url_response.php, onde será codificada a função para o tratamento da url;
- O diretório applications, onde serão guardados nossos aplicativos ex.: noticias.php, índex.php etc
No arquivo .htaccess vamos criar regras de url usando o mod_rewrite(módulo responsável por reescritas de url) do apache.
# Habilitamos o modo Rewrite
RewriteEngine on
#Aqui, criamos as regras de redirecionamento.
RewriteRule !\.(js|ico|txt|gif|jpg|png|css)$ main.php
Detalhando o arquivo .htaccess
Na diretriz RewriteEngine é possível habilitar(On)
ou desabilitar(off) o modo de reescrita do apache. Em RewriteRule
configuramos a regra de reescrita das urls, neste caso redirecionamos
para main.php.
Feito isso vamos criar e codificar a função responsável por tratar a URL, abra o arquivo url_response.php:
<?php
//diretório do projeto if(!defined(´PROJECT_DIR´)) define(´PROJECT_DIR´, ´projeto_1´); // diretório da aplicacao if(!defined(´APPLICATION_DIR´)) define(´APPLICATION_DIR´, ´applications´);
// URL enviado if(!defined(´REQUEST_URI´)) define(´REQUEST_URI´ ,str_replace(´/´.PROJECT_DIR,´´,$_SERVER[´REQUEST_URI´]));
/** * Função Resposável pelo tratamento da URL * * @author Camilo Teixeira de Melo * @link http://www.camilotx.com.br * @param string $urlpatterns array com os modelos de url * @return void **/ function url_response($urlpatterns){ foreach($urlpatterns as $pcre=>$app){ if(preg_match("@^{$pcre}$@",REQUEST_URI,$_GET)){ include(APPLICATION_DIR.´/´.$app); exit(); }else{ $msg = ´<h1>404 Página não existe</h1>´; } } echo $msg; return; }
?>
Neste trecho:
//diretório do projeto
if(!defined(´PROJECT_DIR´))
define(´PROJECT_DIR´, ´projeto_1´);
Definimos a constante PROJECT_DIR onde conterá o diretório do
projeto. No trecho a seguir definimos o diretório da aplicação e a url
enviada pelo browser.
// diretório da aplicacao
if(!defined(´APPLICATION_DIR´))
define(´APPLICATION_DIR´, ´applications´);
// URL enviado
if(!defined(´REQUEST_URI´))
define(´REQUEST_URI´ ,str_replace(´/´.PROJECT_DIR,´´,$_SERVER[´REQUEST_URI´]));
Por último a constituição da função url_response responsável pelo tratamento da url.
foreach($urlpatterns as $pcre=>$app){
if(preg_match("@^{$pcre}$@",REQUEST_URI,$_GET)){
include(APPLICATION_DIR.´/´.$app);
exit();
}else{
$msg = ´<h1>404 Página não existe</h1>´;
}
}
Aqui é criado um laço responsável por percorrer o array com as URLs
padrões e procurar o arquivo na pasta de aplicações, caso exista é feito
sua inclusão. Caso não exista o arquivo apresento uma mensagem de
página inexistente, ou 404.
Usando a função no arquivo main.php:
<?php include(´url_response.php´); $urlpatterns = array( ´/´=>´index.php´, ´/noticias´=>´noticias.php´, ´/noticia/(?P<id_noticia>\d+)´=>´noticias.php´, ); url_response($urlpatterns); ?>
O include não tem segredo. Na array $urlpatterns como o próprio nome diz refere-se aos padrões de url. O índice do array é a url e o valor é o arquivo que deve ser executado.
Exemplo:
´/´=>´index.php´
´/´ refere-se a raiz por exemplo www.dominio.com.br/ que será redirecionado ao índex.php
´/noticias´=>´noticias.php´
´/noticias´ refere-se a www.dominio.com.br/noticias onde executa o arquivo noticias.php
´/noticia/(?P<id_noticia>\d+)´=>´noticias.php´
Aqui eu usufruo da expressão regular para enviar um parâmetro com valor decimal
Via GET. A url ´/noticias/(?P<id_noticia>\d+)´ refere-se a
www.dominio.com.br/noticias/12. O valor é acessado via GET para o
arquivo notícias.php
Por último criamos os arquivos índex.php e noticias.php na pasta applications.
Abaixo deixo um exemplo simples dos arquivos para melhor entendimento do processo de cada arquivo. index.php
<?php echo ´você está na index´; ?>
noticias.php
<?php i f(isSet($_GET[´id_noticia´])) echo ´Exibindo a notícia de id ´ .$_GET[´id_noticia´]; else echo (´Notícias´);
?>
artigo publicado originalmente no iMasters, por Camilo Teixeira de Melo
|
Não é de hoje que as empresas deixam de dar a devida atenção ao
cadastro de um novo cliente ou então em atualizar e/ou enriquecer o seu
banco de dados, no momento em que há uma nova oportunidade de contato. Em
nossa rotina, ao conhecermos e nos apresentarmos a uma nova pessoa,
informamos o nosso nome, em alguns casos, até o que fazemos
comercialmente. Nas relações comerciais, entre cliente e empresa não é
diferente, é fundamental que ambos se apresentem. O processo de
cadastro de um novo cliente é onde nasce a informação e é o momento
ideal para as organizações identificarem as pessoas ou as empresas com
quem estão iniciando uma relação comercial.
Identificando o cliente
A primeira etapa para qualquer empresa que deseja começar a
desenvolver uma estratégia de comunicação dirigida, ou de CRM, é
identificar o seu cliente e criar um banco de dados com os mesmos. A
identificação de um cliente passa inicialmente pela definição de quais
informações cadastrais serão coletadas em decorrência da sua utilidade
para as organizações. A definição de quais dados se obter pode levar a dois caminhos: Simplista
- possibilita em alguns casos o cadastro de poucos dados, nome e e-mail
como, por exemplo, em formulários na web. Deixar nas mãos do cliente a
decisão do que deseja informar pode ser uma estratégia que não vai ao
encontro das necessidades posteriores da marca. O ideal é permitir o
cadastramento unicamente de clientes que desejam se relacionar com a
empresa e estão dispostos a informar o cadastro correto. Por isso a
importância de se utilizar as regras de consistência de entrada de
informações. Complexa - nesse caso, o número de
informações solicitadas torna-se um inibidor de cadastro ao cliente.
Ele sofre só de ver a quantidade de informações que deverá preencher ou
fornecer para efetuar o seu cadastro e às vezes desiste. Claro que
existem casos, como a solicitação de um visto Americano, que é
necessário, mas nos deparamos com situações de empresas que solicitam o
número do passaporte, sem que você entenda qual a finalidade dessa
informação para aquela empresa. Uma das principais chaves de
identificação de um cliente é o CPF ou o CNPJ. Algumas empresas deixam
de solicitar esse atributo. Se houver oportunidade, inclua essa opção no
cadastro. Claro, para aqueles clientes que estão interessados em
receber somente uma newsletter não será necessário solicitar esse
atributo. Ambos são atributos necessários para verificar se o registro
já existe na base de dados, ou mesmo posteriormente para ser utilizado
no enriquecimento da base de dados com atributos como, por exemplo: data
de nascimento, renda, profissão, classe social, telefones, e-mail etc
através de empresas de birô de informações. Ou então realizar uma ação
de co-brand, onde existe a necessidade de cruzar dois ou mais bancos de
dados de empresas parceiras. Sem essa chave, o trabalho se torna oneroso
tanto em tempo, quanto em custos às mesmas e, muitas vezes,
inviabilizando o projeto. Principalmente em São Paulo, com a
nota fiscal eletrônica, cada vez mais os consumidores estão solicitando a
inclusão do seu CPF na nota fiscal, passando a adquirir o hábito em
fornecer essa informação às empresas para qualquer que seja a natureza
de negócio e, nesse sentido, por que não fornecer a empresas onde se tem
o interesse em se cadastrar? Em pouco tempo a lei de nota fiscal
Paulista será estendida a outros estados. O importante é
solicitar ao cliente o que realmente é relevante à empresa e que ele
perceba valor no que está informando. Se ele disponibilizou o e-mail é
porque deseja receber informações relevantes da empresa por esse canal. Após
a definição de quais dados cadastrais serão capturados, o próximo passo
é adotar soluções que permitam certificar-se da qualidade e da
integridade dos dados que serão coletados, ou seja, se a informação
recebida contém os dados desejados e se é exatamente a mesma que será
colocada à disposição da empresa. E, nesse sentido, a integridade
da informação é fundamental para o êxito da comunicação e do
relacionamento entre clientes e empresas. Quanto mais atualizado estiver
seu banco de dados, maior é a chance de retorno sobre o investimento. artigo publicado originalmente no iMasters, por Arthur Guitarrari
|
Não há dúvida de que o Ajax é uma das tecnologias web disponíveis
mais interessantes, úteis e necessárias para desenvolvedores de
front-end. Infelizmente, é também uma das mais restritivas –
especialmente quando o assunto é reunir conteúdo de outros domínios. Os
desenvolvedores web não são nada se não persistentes, por isso vou
apresentar uma variedade de maneiras para contornar as restrições de
cross-origin, incluindo JSONP,
proxies do lado do servidor feitos com PHP, proxy ProxyPass,
transportes Flash, usos criativos iFrame e muito mais. O que muitos
desenvolvedores não sabem é que existe uma especificação W3C chamada“Cross-Origin Resource Sharing”, ou “CORS”, que fornece um padrão para solicitações cross-origin do Ajax com hassle mínimo.
Como a API do Ajax é diferente entre os navegadores e a maioria dos
desenvolvedores usa um kit de ferramentas do JavaScript, os exemplos
mostrados neste artigo usarão o framework MooTools JavaScript. O CORS
vai funcionar com qualquer framework JavaScript, já que a filosofia
central e o código seja configurado no servidor, e não no lado do
cliente. Devido a sua popularidade, o Apache será utilizado nos exemplos
de configuração do lado do servidor.
Solicitações básicas do Ajax
Cada um dos frameworks do JavaScript abstrai objetos XMLHttpRequest (ou, no caso do Internet Explorer, ActiveXObject ou Microsoft.XMLHTTP)
para fazer requisições do Ajax. Esses pedidos apresentam uma URL e
podem conter cabeçalhos extras, dados, tipos diferentes de solicitação (GET, POST, PUT ou DELETE), e muito mais. Um pedido Ajax básico seria mais ou menos assim:
// Create a new Ajax request
var request = new Request.JSON({
// The URL to get content from
url: "/countries.json",
// The success callback
onSuccess: function(countries) {
// Log out the content
console.log("The countries are: ", countries);
}
}).send(); // Send the request
A URL no pedido acima é local; countries.json está localizado dentro de uma mesma origem. E se a gente, ainda assim, tentar obter tweets do Twitter?
// Create a new Ajax request
var request = new Request.JSON({
// The URL to get content from
url: "http://twitter.com/statuses/user_timeline/davidwalshblog.json",
// The success callback
onSuccess: function(tweets) {
// Log out the content
console.log("The tweets are: ", content);
}
}).send(); // Send the request
A solicitação para o Twitter irá falhar porque o destino solicitado, twitter.com, não é o mesmo que o da origem. Cada navegador fornece a sua própria mensagem de erro; o Chrome irá avisá-lo com: XMLHttpRequest
cannot load
http://twitter.com/statuses/user_timeline/davidwalshblog.json. Origin
http://davidwalsh.name is not allowed by Access-Control-Allow-Origin.
No caso do Twitter, poderíamos utilizar um pedido JSONP, mas o
problema com ele é que o servidor de destino deve suportá-lo. Mesmo que o
destino suporte o JSONP, você não pode fazer um POST na URL ou enviar
cabeçalhos de requisição específicos. Como podemos resolver esse enigma?
Com o CORS, claro.
Implementando CORS
O CORS permite solicitações cross-origin com um pouco de exagero. Uma
vez que o servidor de destino for o órgão no controle e “em risco”, ele
deve ser configurado com os cabeçalhos adequados e configurações de
segurança. Alguns dos cabeçalhos principais incluem:
Access Control-Allow-Origin
A URL específica ou * que identifica que domínio (s) pode fazer solicitações cross-origin para
esse servidor (destino). (* é um valor de configuração indesejável, uma
vez que permite que toda e qualquer origem faça solicitações para o
servidor.)
Access-Control-Allow-Methods
Uma lista separada por vírgulas de métodos de solicitação permitidos.
Access-Control-Allow-Headers
Uma lista separada por vírgula de cabeçalhos de requisição permitidos.
Supondo que um site está hospedado em um servidor Apache, um host a virtual pode ser configurado da seguinte forma:
<VirtualHost *:80>
DocumentRoot "/path/to/website/root"
ServerName domain.tld
Header set Access-Control-Allow-Origin http://example.com
Header set Access-Control-Allow-Methods POST,GET
Header set Access-Control-Allow-Headers X-Authorization,X-Requested-With
</VirtualHost>
A configuração acima apenas permite pedidos remotos a partir de http://example.com, o tipo de pedido só pode ser POST ou GET, e permitiu que os cabeçalhos fossem X-Authorization and X-Requested-With.
Se você pretende permitir que qualquer um faça requisições Ajax para o
seu domínio e com qualquer tipo de pedido, você pode optar por esta
configuração:
<VirtualHost *:80>
DocumentRoot "/path/to/website/root"
ServerName domain.tld
Header set Access-Control-Allow-Origin *
Header set Access-Control-Allow-Methods POST,GET,DELETE,PUT,OPTIONS
Header set Access-Control-Allow-Headers X-Authorization,X-Requested-With
</VirtualHost>
Com o servidor de destino configurado, podemos enviar solicitações cross-origin de onde quer a gente queira:
// Create a new Ajax request
var request = new Request({
// The URL to get content from
url: "http://example.org/content.php",
// The success callback
onSuccess: function(content) {
// Log out the content
console.log("The content is: ", content); // Works!
}
}).send(); // Send the request
A grande questão é: “quais navegadores implementaram a especificação
CORS?” A maioria deles, na verdade. Firefox 3.5+, Safari 4+, Chrome 3+, e
IE9+. O IE8 não suporta o CORS padrão, mas tem um objeto XDomainRequest,
e o Opera ainda não implementou CORS. Esse nível atual de suporte, no
entanto, faz do CORS uma opção viável para muitos sites. Se você
gerencia um serviço web ou simplesmen |