Desenvolvimento - Visual Basic
Construa o núcleo de um projeto
Construa seu aplicativo complexo como uma casa. Se você tentar colocar as portas antes de terminar a estrutura, ela pode cair.
por Ron SchwarzCriar um aplicativo complexo é como construir uma casa. Começa-se pelo projeto, o trabalho prossegue em estágios e, depois de pronta, ainda é preciso conservá-la. É normal ocorrerem alterações no projeto; algumas vezes, elas ocorrem porque você ou o construtor pensaram em algo mais benéfico; outras, porque fatores inesperados lhe forçaram a modificar ou interromper a construção.
Qualquer aplicativo menos trivial passa por uma série de fases naturais de construção. Pense nesses estágios como camadas (como as camadas de uma cebola). Por exemplo, os programadores VB costumam se concentrar primeiro na interface com o usuário, mesmo sendo esta a camada mais externa. Se você estivesse construindo uma casa, jamais poderia colocar as paredes, janelas e vigas do telhado sem antes terminar a estrutura da casa. No entanto, o VB permite que você vá embromando e prossiga com a criação do programa – mas não por muito tempo.
O principal motivo de o VB ser tão criticado por sua característica de “linguagem protótipo” reside no fato de que os programadores freqüentemente tendem a colocar as janelas, divisórias e vigas antes de terminar a estrutura da casa para então, ex post facto, assistirem em pânico ao desmoronamento de toda a construção quando tentam inserir a estrutura.
Neste artigo, descreverei (usando meu próprio exemplo de trabalho) como e por que elaborar um projeto a partir do núcleo. Explicarei os procedimentos usados e por que motivo utilizei-os. Meu projeto pode ser comparado a um horrível canteiro de obras, repleto de entulhos. Ele não utiliza códigos bonitinhos nem códigos de exemplo. Ele usa códigos verdadeiros, em seu processo inicial de gestação. Você verá códigos defeituosos e bagunçados, feios e até inacabados, sem saída (embora eu tenha tentado localizar a maioria deles). Chamarei sua atenção para a maior parte deles e explicarei por que estão ali. Isso certamente não será uma visão agradável; na verdade, corresponde a uma visão do lado obscuro e sujo do mundo da programação.
O objetivo é que você compreenda o processo não o projeto. Quando eu analiso um fragmento de código, não o faço para explicar o VB, mas sim para explicar o processo de desenvolvimento da linguagem. Explicarei as minhas soluções, meus motivos e os objetivos que influenciaram na minha decisão. Em geral, somos tentados a nos satisfazer com qualquer coisa que pareça um produto final. No entanto, a meu ver essa abordagem é totalmente errada quando se está ainda na fase de construção da estrutura, e não há justificativas para esse tipo de programação.
O código que acompanha este artigo (clique aqui para fazer o download.) representa a camada do núcleo de um aplicativo comercial que estou desenvolvendo. O produto consiste em um navegador personalizado, destinado a simplificar os trabalhos de pesquisa, acompanhamento e lances em leilões on-line. A camada interna corresponde à parte que busca as páginas de listagem, extrai os dados-chave e expõe cada fragmento significativo como uma propriedade de uma classe VB.
Criei esse programa de exemplo porque percebi que precisava dele para meu próprio uso, e não encontrava nada no mercado que atendesse às minhas necessidades. Depois de conversar com algumas pessoas mais esclarecidas, cuja opinião prezo bastante, concluí que tinha uma chance de desenvolver um aplicativo que não apenas poupasse meu tempo e me tornasse mais produtivo como também me desse uns trocados se eu o comercializasse.
Durante a criação da camada interna do aplicativo (núcleo), incluí a interface de usuário mais despojada com a qual pudesse trabalhar: uma janela de navegador IE, um controle de grade e um controle Label para exibir estados de ocupado (observe a Figura 1). Você precisará lutar para conservar a simplicidade em todas as camadas do aplicativo, mas isso é fundamental quando se está iniciando um projeto.
Nos estágios de desenvolvimento iniciais, a interface do usuário deve ser menos do que espartana. É contraproducente embelezá-la nesse ponto. Isso desvia seu tempo e atenção e o força a se deslocar desnecessariamente entre as camadas da cebola.
Figura 1: Não Priorize a Beleza
Quando você trabalha em um navegador personalizado como esse, é melhor cuidar primeiro dos códigos de manipulação de dados e de transporte antes de mergulhar nos recursos orientados a usuário. Lembre-se, primeiro a fundação, por último a pintura. Se você estiver se desgastando com o posicionamento dos controles, tamanho de fontes, imagens de segundo plano e telas de abertura de multimídia, mas o programa propriamente dito apresentar falhas vitais no funcionamento e estiver cheio de bugs, é hora de pisar com força no freio, e rápido.
Quando você se concentra primeiro na camada interna, não se diverte tanto. É um trabalho duro, e a maior parte dele é frustrante. Você se deparará com uma infinidade de códigos inacabados até encontrar o caminho para um fragmento de código elegante. Se for paciente e resistir à tentação de “fazer o acabamento em um ou dois cômodos” antes de terminar a fundação, você será bem recompensado nos estágios finais do desenvolvimento.
A pior filosofia de projeto é adicionar a funcionalidade à medida que der vontade, ignorando totalmente o núcleo. Quando isso acontece, as pessoas geralmente se referem ao resultado como “código espaguete”, mas eu acredito que o termo câncer seja mais apropriado. Os pedaços e fragmentos de código crescem e se espalham de cima a baixo, tornando impossível identificar as camadas.
Buscando e Analisando
A camada-núcleo da cebola neste projeto é o localizador-analisador. Para fins de conveniência, você quer um programa independente que funcione como uma “zona de recebimento” para os URLs arrastados do Internet Explorer. A sua meta é ser capaz de arrastar um URL de uma linha Address ou de um link em uma página Web e fazer com que o programa busque o HTML, analise-o e forneça os dados relevantes em forma de campos. Esses campos não são objetos de campo do banco de dados real, mas velhas variáveis VB que você poderá usar mais tarde, quando e como julgar mais conveniente.
A classe clsItem expõe os campos e faz aquele trabalhinho pesado, necessário para extrair os dados que serão inseridos nos campos.
Cada campo possui um procedimento PropertyGet. Se você achar necessário adicionar mais campos, pode adicionar facilmente propriedades Property e tags de análise. Manter o código de campo de nível inferior centralizado nesta camada significa que, quando expandir o programa, você não precisará lutar com uma massa de espaguete. No entanto, uma certa quantidade de “células doentes” consegue sempre se infiltrar nos projetos durante seu crescimento. Isso é inevitável, a não ser que você fique tão obcecado com as minúcias do projeto que se desvie de seus objetivos reais. Alguns dos códigos infectados passam desapercebidos até que seja tarde demais para tomar alguma providência, a não ser conviver com eles.
Os defeitos de projeto constituem uma doença crônica, da qual todos os aplicativos complexos sofrem e à qual, esperançosamente, sobrevivem. Se você duvida do que estou dizendo, experimente executar qualquer versão de software comercializada no mercado. Essas doenças fazem parte do processo de desenvolvimento e você precisará lidar com elas da mesma forma como lida com os aspectos mais glamourosos de seu produto.
A primeira etapa da criação da camada de transporte é incluir um controle WebBrowser em um formulário. Embora seja mais simples “soltar” o controle e fazê-lo navegar na direção de um URL, você perceberá rapidamente que será necessário ter um certo jogo de cintura para impedir que os usuários danifiquem seus dados (intencionalmente ou acidentalmente) quando estiverem trabalhando com um navegador razoavelmente especializado. Um controle IE WebBrowser é uma ferramenta poderosa a ser considerada.
Infelizmente, não é fácil dominar áreas que não estejam relacionadas a um aplicativo específico. Nesse caso, é preciso se proteger contra danos de usuários navegando até outra URL ou acionando recursos WebBrowser que não estejam relacionados especificamente ao aplicativo. Basicamente, você precisa ter a função de controle em um modo estritamente “apenas-exibição”, o que, infelizmente, não é fácil de conseguir.
Consegui descobrir o kit de ferramentas WBCustomizer de seu Knowledge Base on-line, mas ele não é fácil de usar e possui alguns efeitos colaterais indesejáveis. No entanto, permite desativar a maior parte da funcionalidade que seria inadequada para um cenário somente-exibição. Infelizmente, se você quiser eliminar os efeitos indesejáveis, terá que mergulhar no C++, reparar a fonte e recompilar o DLL do WBCustomizer. Eu recomendaria outra abordagem, mas você pode preferir verificar o WBCustomizer e conferir por si mesmo.
Felizmente, a empresa O’Reilly & Associates enviou-me recentemente um exemplar do Visual Basic Shell Programming, de J. P. Hamilton (consulte Fontes de referência). Enquanto estudava atentamente o livro, descobri que o controle WebBrowser é carregado com recursos que se tornam indisponíveis quando você apenas “solta” o controle no formulário. É pena que não foram bem documentados. Hamilton também descobriu isso e, depois de fazer uma expedição completa nas entranhas do navegador, orienta o leitor nesse processo. O autor fez uma quantidade enorme de pesquisas. Se você estiver envolvido com qualquer tipo de trabalho mais sério com IE – seja no modo independente (standalone) ou como um controle WebBrowser – não deve deixar de ler este livro.
Eu encontrei a salvação para o meu projeto no objeto HTML-Document citado no livro, disponível quando você inclui uma referência ao Microsoft HTML Object Library em um projeto VB. Quando você declara essa referência com a palavra-chave WithEvents, expõe uma enorme quantidade de eventos (que de outro modo estariam indisponíveis), como o evento oncontextmenu, que é acionado quando o usuário clica no botão direito do mouse. Não sei por que esses eventos não aparecem no WebBrowser padrão. O motivo pode estar relacionado ao fato de alguns desses eventos (inclusive o oncontextmenu) não serem caracteristicamente eventos VB. Da mesma forma que alguns dos eventos DHTML, oncontextmenu constitui um procedimento Fucntion, e não um subprocedimento. Para alterar o comportamento do evento, você define o nome da função como True ou False, em vez de definir um argumento Cancel.
No entanto, você não perceberá nenhuma evidência do evento oncontextmenu no código que acompanha este artigo. Porém, notará um monte de vestígios comentados do código WBCustomizer. Isso acontece porque fiz experiências com o objeto HTMLDocument em um projeto de plataforma de teste separado e, depois que descobri como funcionava, voltei ao projeto principal e descartei o código WBCustomize. Nesse estágio do programa, eu não estava interessado na funcionalidade, mas precisava saber se ela ocorreria no momento em que estivesse pronto para liberar a primeira versão beta. Acredito ser boa idéia deixar alguns trechos inúteis comentados no código enquanto estiver trabalhando em seções mais complicadas. Você nunca sabe quando desejará rever os códigos em que trabalhou antes, mesmo que seja apenas para lembrar de um código inacabado e evitar ter de passar por ele novamente. E, principalmente, para evitar perder a sua linha de raciocínio. Quando você está no meio de um processo criativo, não quer ter sua atenção desviada para futilidades. Deixe o trabalho de limpeza para depois que o código estiver funcionando apropriadamente.Escreva o Código “de busca”
Agora que você sabe que não há obstáculos intransponíveis, é hora de começar o trabalho propriamente dito: montar o código de busca. Coloque um controle Internet Transfer no formulário e escreva alguns códigos para guiar o controle usando os resultados de uma operação OLEDragDrop. Essa é uma área onde é permitido fazer uma pequena concessão à usabilidade, já que é você quem estará usando o programa e, quanto menos batalhas tiver de enfrentar, mais facilidade terá para se concentrar na tarefa que estiver fazendo. Para evitar ter de colocar o URL em uma “zona de recebimento” específica, você deverá incrementar seu código com eventos OLEDragDrop que instruam um procedimento central a fazer o trabalho comum. Observe o procedimento GetURL que busca o HTML bruto (consulte a Listagem 1). Depois que esse procedimento busca o HTML, ele chama o procedimento UpdateIE para capturá-lo e, em seguida, o procedimento AddListing, que carrega os campos na tabela.
O formulário frmBuyer representa mais uma plataforma de teste do que uma interface de usuário. Ele constitui na verdade um receptor “arrastar e soltar”, que aceita URLs auto-sustentáveis de um navegador IE, executa verificações superficiais, envia-os para processamento e, por fim, insere em uma grade os campos processados e carrega na janela do navegador o HTML processado.
Listagem 1: Formulário frmBuyer
Option Explicit "Dim CustomWB As WBCustomizer Dim HTMLArray() As String Private Type tItem Number As String Description As String Picture As String DateStart As Date DateEnd As Date End Type Dim Primed As Boolean Dim Item As tItem Dim URL As String Dim UrlText As String Private Sub Form_Load() flxItems.FormatString = _ "ItemNumber " & "|" & _ "Category " & "|" & _ "Title " & "|" & _ "Seller " & "|" & _ "TimeLeft " & "|" & _ "URL" """" Set CustomWB = New WBCustomizer """" CustomWB.EnableAllAccelerators = False """" CustomWB.EnableContextMenus = False """" Set CustomWB.WebBrowser = iePage Set clsItem = New clsItem_T iePage.Navigate2 "about:blank" Do Until iePage.ReadyState = _ READYSTATE_COMPLETE DoEvents Loop End Sub Private Sub Form_OLEDragDrop(Data As _ DataObject, Effect As Long, Button _ As Integer, Shift As Integer, x As _ Single, y As Single) If Data.GetFormat(vbCFText) Then Busy = True lblStatus = "Loading Page..." URL = Data.GetData(vbCFText) GetURL URL End If End Sub Private Sub _ iePage_NavigateComplete2(ByVal _ pDisp As Object, URL As Variant) If Not Primed Then "aciona na primeira vez que o mecanismo de "mapeamento (rendering) é carregado Primed = True End If End Sub Private Sub iePage_NewWindow2(ppDisp _ As Object, Cancel As Boolean) Cancel = True End Sub Private Sub _ iePage_BeforeNavigate2(ByVal _ pDisp As Object, URL As Variant, _ Flags As Variant, TargetFrameName _ As Variant, PostData As Variant, _ Headers As Variant, Cancel As Boolean) Dim ThisURL As String If Primed Then Cancel = True "não carregue a URL no controle do IE ThisURL = URL Busy = True lblStatus = "Loading Page..." GetURL ThisURL End If End Sub Private Sub lblbuyer_OLEDragDrop(Data _ As DataObject, Effect As Long, _ Button As Integer, Shift As _ Integer, x As Single, y As Single) If Data.GetFormat(vbCFText) Then Busy = True lblStatus = "Loading Page..." URL = Data.GetData(vbCFText) GetURL URL End If End Sub Private Sub flxItems_OLEDragDrop(Data _ As MSFlexGridLib.DataObject, _ Effect As Long, Button As Integer, _ Shift As Integer, x As Single, y As Single) If Data.GetFormat(vbCFText) Then Busy = True lblStatus = "Loading Page..." URL = Data.GetData(vbCFText) GetURL URL End If End Sub Private Sub GetURL(URL As String) If Left$(URL, 16) <> "http://cgi.ebay." Or _ InStr(URL, _ "/aw-cgi/eBayISAPI.dll?ViewItem&item=") = 0 Then "oh, não, em uma página de listagem de itens Busy = False lblStatus = "" Exit Sub End If DoEvents UrlText = "" UrlText = itcFetch.OpenURL(URL) Busy = False lblStatus = "" UpdateIE URL AddListing URL End Sub Private Sub AddListing(URL As String) Static GridKludge As Boolean With clsItem .HTML = UrlText flxItems.AddItem .ItemNumber _ & vbTab & .Category & vbTab & _ .Title & vbTab & .Seller & vbTab _ & .TimeLeft & vbTab & URL ReDim Preserve _ HTMLArray(flxItems.rows - 1) HTMLArray(flxItems.rows - 1) = UrlText If Not GridKludge Then GridKludge = True If flxItems.rows = 3 Then "remove blank row HTMLArray(flxItems.rows - 2) = _ HTMLArray(flxItems.rows - 1) flxItems.RemoveItem 1 End If End If End With End Sub Private Sub UpdateIE(TxtData As String) iePage.Document.open iePage.Document.write _ "<HTML><BASE HREF=" & TxtData & "> " & UrlText iePage.Document.Close End Sub Private Sub flxItems_RowColChange() If Busy Then Exit Sub End If "col 5 = "URL" UrlText = flxItems.TextMatrix(flxItems.Row, 5) UpdateIE HTMLArray(flxItems.Row) End Sub
Como o programa foi projetado para permitir buscas locais, ele precisa orientar o WebBrowser a partir de dados locais, em vez de orientá-lo a fazer o download de dados remotos por meio de HTTP. Novamente, isso pode parecer simples, mas, na verdade, não é tão intuitivo assim. Observe o procedimento UpdateIE na Listagem 1:
Listagem 2: método UpdateIE
Private Sub UpdateIE(TxtData As String) iePage.Document.open iePage.Document.write _ "<HTML><BASE HREF=" & TxtData & "> " _ & UrlText iePage.Document.Close End Sub
Ocorre que você não consegue colocar apropriadamente uma string HTML em um navegador. Você precisa abrir o objeto Document do WebBrowser, usar o método Document.write para inseri-lo e depois fechar o objeto Document. No entanto, se precisar que o controle seja capaz de carregar objetos gráficos incorporados, ele falhará, já que não tem como saber onde estão os gráficos a não ser que receba endereços HTPP absolutos explícitos. E, como na vida real a maioria dos controles não conhece a localização de objetos gráficos, você precisa incluir algum código HTML para apontar o “BASE HREF” da página para o endereço a partir do qual a página foi obtida.
Quando usar o WebBrowser para exibição local, você deverá considerar ainda outro aspecto: não é possível executar uma chamada para um método Document.write a não ser que já exista uma documento no qual se possa escrever. Isso significa que você precisará forçar o controle a carregar seu mecanismo de mapeamento. Você pode fazer isso navegando até uma página Web real ou forçando-o a carregar a página em branco padrão:
Listagem 3: Carregando página em branco padrão
iePage.Navigate2 "about:blank" Do Until iePage.ReadyState = _ READYSTATE_COMPLETE DoEvents Loop
Esse código é executado uma vez no evento Form_Load da Listagem 1.
Você precisará lidar com mais uma “armadilha”: o controle WebBrowser, embora explicitamente capaz de receber uma URL OleDragDrop, não possui nenhum evento correspondente que permita que você intercepte o URL. É possível “enganá-lo” usando o evento iePage_BeforeNavigate2 para capturar o URL, guiar o procedimento GetURL e cancelar o download do WebBrowser.
Vamos ao que Interessa
Por fim, é hora de fazer alguma coisa com o HTML. Na Listagem 1, o procedimento AddListing passa o HTML para o evento HTML da classe clsItem. Nesse ponto, todos os campos estão disponíveis como propriedades da mesma classe. Em seguida, ainda no procedimento AddListing, você carregará alguns dos campos na grade chamando seu método AddItem. Como a grade não permite a inclusão de uma linha fixa sem que haja pelo menos uma linha não-fixa, você pode “enganar” e fazer com que a grade comece com uma linha em branco abaixo da linha de título. E, pelo fato de o método AddItem adicionar um novo registro depois das linhas existentes, será exibida uma linha em branco no início da lista. Para contornar esse problema da linha em branco, você poderá usar um kludge, que pode ser observado no procedimento AddListing. Você também precisa armazenar fora da grade cada HTML bruto do registro; use um vetor de string como a HTMLArray da Listagem 1. Esse atalho é necessário porque as células da grade não conseguem armazenar a fonte HTML completa sem truncá-la. Veja o resultado desse processo em tempo de execução na Figura 2.
Figura 2: O Formulário Funciona
Veja aqui o mesmo formulário no modo runtime, carregado de dados. Não há muito a ser visto, mas ele cumpre a finalidade a que se propõe: permite que você saiba se a camada de nível inferior da cebola está funcionando. Se observar com atenção a captura de tela, você identificará um bug. É justamente essa a finalidade do formulário.
É provável que você use essa classe em vários formulários e, por esse motivo, deve criar um módulo BAS para armazenar sua declaração. Inclua também o sinalizador Busy:
Listagem 4: Declaração do sinalizador Busy
Option Explicit Public Busy As Boolean Public clsItem As clsItem_T
Por fim, você provavelmente vai armazenar os dados em um banco de dados. Ainda não é hora de fazer isso porque esse processo está relacionado a uma camada mais externa da cebola. Antes de passar para as camadas mais externas, você deve assegurar que o localizador e o analisador estejam funcionando perfeitamente. É importante evitar ao máximo ficar saltando entre as camadas. Um dos motivos é que isso significará uma coisa a menos para se preocupar quando estiver brigando com a tarefa atual. Significa também não precisar fazer constantes reengenharias no código do banco de dados à medida que o código de análise do HTML evolui.
A busca, o mapeamento e o código da tabela são as etapas que exigem mais esforço. No entanto, você também precisará trabalhar para criar o código de análise. Analisar o HTML é simples, mas tedioso. Esse processo consiste basicamente em procurar uma tag exclusiva que termine um pouco antes dos dados do campo desejado e, em seguida, por uma tag que apareça imediatamente após o campo. Você então extrai todos os dados existentes entre as duas tags, atualiza seus ponteiros definindo a nova posição de início em relação à posição de fim e passa para a análise do próximo campo.
Não vou mais ocupar seu tempo com detalhes sobre os mecanismos de análise.
Sugiro que você observe o procedimento GetSlobs Sub, que armazena todas as tags. Não é aconselhável criar rotinas específicas para fragmentos e retalhos de HTML bruto e mantê-las dentro de uma classe.
Por outro lado, para que você não sofra tanto ao desembaraçar os algoritmos com os quais trabalha, é aconselhável permanecer em uma camada da cebola o máximo de tempo possível. Na hora em que estiver arrancando os cabelos com os testes de erro/acerto das tags, você achará mais fácil descarregar o HTML de teste no procedimento GetGlobs – rápido, curto e grosso. Isso tornará o pesadelo de ir e vir um pouco menor do que se você tentar escrever códigos INI e de banco de dados ao mesmo tempo. Quando terminar com a camada atual, é hora de decidir sobre o cenário de armazenamento para, em seguida, escrever o código real dentro da classe.
Se quiser brincar com o código, esteja à vontade. Ele ainda está longe de ser utilizável, mas lhe dará uma vantagem inicial em qualquer código de captura/análise que precise criar, independentemente do local. Lembre-se, o meu objetivo não é a maneira como você analisa o HTML, mas sim a maneira como lida com projetos complexos.
Uma vez adicionada a camada de análise, você precisa adicionar a próxima camada – o código para armazenar e recuperar os dados de item.
A camada seguinte será o código que permite que os usuários enviem lances para itens selecionados. E, depois desta, a camada que permite que os usuários atribuam uma data e hora para enviar um lance automaticamente.
Distribua a Versão Beta
Neste ponto, você completou a funcionalidade básica do programa e o aplicativo será enviado para os sites de versões beta para ser submetido àqueles testes arrasadores. Ele ainda está longe da fase de comercialização, o que só acontecerá depois que todos os bugs inevitáveis tiverem sido erradicados.
Enquanto o programa passa pelas fases de teste, é hora de começar a trabalhar nas próximas camadas – ainda as camadas internas. Essas camadas adicionam recursos, tais como consultas a novos itens e acompanhamento do andamento das listagens selecionadas. Em seguida, você precisa reativar um pouco mais a funcionalidade básica (pense nisso como uma volta ao porão, para instalar a fornalha e o aquecedor de água), a fim de permitir que os usuários mergulhem nas listagens e examinem históricos de lances, arquivos de resposta e outras listagens relacionadas ao vendedor ou artigo selecionado.
Quando os analistas terminarem de apontar novos bugs (que você consertará à medida que forem aparecendo), envie a segunda versão beta, com todos os bugs consertados e com novas camadas adicionadas.
Depois de passar por essa seqüência de criação e testes, camada por camada, o programa pode ser considerado totalmente funcional. Finalmente, é hora de enfeitar a interface. Comece pelo dimensionamento dos controles, sua aparência e posicionamento. Em seguida, certifique-se de que a ordem da tabulação esteja correta, livre de desvios indesejáveis. Depois, adicione as teclas aceleradoras, tentando combinar ao máximo a funcionalidade da operação com o mnemônico mais sugestivo. A partir daí, vá para o menu Editor e atribua teclas de atalho para itens de menu. Por fim, adicione uma barra de ferramentas. O aplicativo agora está pronto para retornar aos sites de versões beta.
Nesta etapa, você pedirá aos analistas que dêem um retorno sobre a funcionalidade, além dos relatórios sobre bugs. Ao final desse ciclo de testes, examine os feedbacks e tente implementar o máximo de recursos solicitados, desde que não exijam uma reengenharia completa do aplicativo.
Quando terminar, envie o aplicativo de volta como um RC - Release Candidate (candidato à liberação).
Enquanto isso, continue trabalhando nas ferramentas internas para facilitar o desenvolvimento posterior do projeto. Ferramentas próprias para tarefas como análise do software gerador de tags facilitam muito a sua vida.
Se você detectar algum bug neste ciclo, conserte-o e envie uma nova versão para RC. Teoricamente, o programa estará pronto para ser enviado para a produção.
Agora que o produto está sendo usado no mundo real, você começa a receber novos relatórios de bus e pedidos de recursos. Crie uma lista dos relatórios de bugs por prioridade, com base na gravidade e na freqüência destes. Utilize critérios de avaliação similares para os pedidos de recursos; classifique-os por freqüência e custo de implementação. Obviamente, se um usuário fizer um pedido muito absurdo, ignore. Porém, se 100 usuários pedirem uma tecla de acesso para uma lista de vendedores ou artigos, você deverá fazer o máximo de esforço para incluir esse recurso na próxima versão principal.
Enquanto a primeira versão estiver em produção, conserte novamente os bugs e estude a melhor forma de implementar os novos recursos. É possível que alguns recursos úteis não sejam viáveis devido às características inerentes ao projeto original. Deixe-os de lado, mas não os esqueça.
À medida que trabalhar com o código no estágio de produção (basicamente consertando bugs) você vai apreciar algumas seções de seu projeto e detestar outras. Algumas soluções e atalhos adotados durante as fases iniciais do desenvolvimento poderão irritá-lo profundamente, mas não há nada mais a fazer, já que eles fazem parte da fundação. Uma coisa é instalar um novo aquecedor de água no porão. Porém, incluir uma fossa sanitária ou furar um poço já é algo totalmente diferente.
A próxima versão principal consiste na versão original do projeto contendo uma massa de bugs consertados e uma quantidade suficiente de novos recursos, os quais encorajarão atualizações e novas vendas. No entanto, os principais defeitos da estrutura ainda estarão lá. Se o programa for promissor em termo de vendas, é hora de encarar os fatos e começar a reescrever um novo projeto. Ou seja, é hora de construir uma nova casa. Dessa vez, evite aquelas armadilhas da primeira casa, que só apareceram depois que era tarde para consertá-las.
Sobre o Autor
Ron Schwarz se esconde na área rural de Michigan. Quando não está ocupado com a montanha de e-mails de sua caixa de correio, Ron se diverte (e ganha dinheiro) restaurando câmeras clássicas.
Download do código referente a este artigo
- Sou programador, o mágico atende na sala ao ladoPHP
- System Tray - O seu ícone ao lado do relógio do WindowsVisual Basic
- Criando Aplicações Limitadas a Uma Única Instância (Single Instance)C#
- Criando um pacote de instalação com o INNO SETUPVisual Basic
- Nota Fiscal Eletrônica: Construindo um "Servidor de Assinatura Digital" com o NFeExpr...Visual Basic