1 ESCOLA SUPERIOR ABERTA DO BRASIL – ESAB GAMBAS: uma linguagem alternativa livre para desenvolvimento de aplicações GUI em Linux José Robson Araujo Silva1 Fábio Luiz Bigati2 Resumo Este artigo visa a apresentar a linguagem GAMBAS, que é uma variante do BASIC, como alternativa para desenvolvimento de aplicações com interface gráfica (GUI – Graphical User Interface), em ambiente GNU/Linux, em oposição a linguagens comerciais mais conhecidas, como Java e C/C++, as quais possuem curvas de aprendizagem bem mais íngremes. Para isso, desenvolveu-se uma interface gráfica CRUD (Create/Read/Update/Delete) para o banco de dados de demonstração livre, Chinook, em sua versão para SQLite. Concluiu-se, através deste experimento, que a linguagem GAMBAS tem um grande potencial para o desenvolvimento de aplicações do tipo front-end, pois além da facilidade no aprendizado, por ter uma ótima documentação online e offline, embutida num bom ambiente integrado de desenvolvimento (IDE), totalmente escrito em GAMBAS, com suporte a arrastar e soltar controles em uma interface WYSIWYG (What You See Is What You Get), também apresenta suporte nativo aos bancos de dados Postgres, MySQL, SQLite, além de suportar conexões via ODBC. Palavras-chave: GAMBAS. BASIC. SQLite. GNU/Linux. Aplicações GUI. 1 Introdução Diante da popularização crescente do sistema operacional GNU/Linux, cresce também a demanda por aplicações e ferramentas de desenvolvimento, sobretudo, ferramentas que possibilitem o desenvolvimento rápido de aplicações (RAD – Rapid Application Development). Em razão deste cenário, o presente artigo objetiva a apresentar o projeto Gambas como uma ferramenta alternativa às tradicionais para desenvolvimento de aplicações com interface gráfica em ambiente GNU/Linux, com foco restrito a aplicações gráficas do tipo front-end com acesso a banco de dados, delimitando assim o escopo deste trabalho. Com 1 2 Pós-graduando em MBA Profissional em Sistemas de Informação na Escola Superior Aberta do Brasil – ESAB. ([email protected]). Mestrando em Educação, Especialista em Novas Tecnologias da Educação, Bacharel em Sistemas de Informação e Licenciado em Pedagogia. 2 vistas a atingir o objetivo proposto, apesar da escassez de material bibliográfico formal acerca do tema, por tratar-se de um projeto alternativo em software livre, realizou-se uma pesquisa bibliográfica em materiais disponíveis na internet, a qual subsidia a exposição descritiva do tema, bem como realizou-se, complementarmente, o desenvolvimento de um projeto simples dotado de uma interface gráfica e capaz de realizar as operações CRUD (Create/Read/Update/Delete) em um banco de dados SQLite, com o objetivo de experimentar e demonstrar, na prática, o uso e a aplicação tanto da linguagem quanto do ambiente integrado de desenvolvimento do Gambas na resolução do problema proposto, respeitando seu escopo e, posteriormente, realizando uma análise qualitativa acerca da maturidade e usabilidade da ferramenta em comento. 2 Desenvolvimento de aplicações GUI em GNU/Linux O sistema operacional GNU/Linux, popularmente conhecido apenas como Linux, tem aumentado cada vez mais sua participação em ambientes domésticos, organizações sem fins lucrativos, empresas e órgãos governamentais. Entre os fatores responsáveis por esse aumento estão a necessidade dos usuários de diminuir custos com licenças de software, aumentar a segurança na rede, a busca por estabilidade, desempenho estável, economia de recursos de hardware, facilidade na instalação de software, drivers de dispositivos e atualizações, bem como acesso ao código-fonte, além de ter diversas opções de customização e poder escolher entre múltiplos ambientes de área de trabalho como KDE, Gnome, Unity, Cinnamon, Mate, XFCE, LXDE, entre outros (WIKIPÉDIA, 2015c). Com o aumento da adoção do Linux, sobretudo em desktops e workstations, aumenta também a demanda por aplicações para usuários finais, e com isso, surge a necessidade de ferramentas que permitam o desenvolvimento prático e rápido de aplicações, não só para consoles ou terminais (CLI – Command Line Interface), mas também, com interface gráfica (GUI – Graphical User Interface). Porém, como explicitam Matthew e Stones (2007), desenvolver aplicações gráficas em ambiente Linux não é uma tarefa simples, já que o suporte a interfaces gráficas é proporcionado pelo X Window System (mais comumente chamado de X11, ou apenas X), que por sua vez, ao contrário do que parece, não implementa nenhuma interface gráfica, mas provê meios para que se possa implementar um ambiente gráfico completo (desktop), através de sua estrutura composta por X Server, X Client (qualquer 3 aplicação para X), X Protocol e pela biblioteca Xlib, que por possuir uma API de nível muito baixo, inviabiliza sua utilização direta para desenvolvimento de aplicações. Por esse motivo, é necessário utilizar bibliotecas gráficas com API de nível mais alto (toolkits), que facilitam sobremaneira o desenvolvimento, e dentre as quais, historicamente destacam-se as bibliotecas Motif, OpenLook e Xt, bem como as mais modernas GTK+ e Qt. Note-se, também, que esta abordagem genérica adotada pelo X Window System dificultou, por muito tempo, o surgimento de ambientes desktop, tanto em Linux quanto em UNIX, até o surgimento de dois projetos de desktops que ganharam enorme evidência entre os usuários de Linux: o GNOME e o KDE, os quais foram construídos sobre as bibliotecas GTK+ e Qt, respectivamente. Neste contexto, temos, como principais opções, dois toolkits com características bem distintas. O GTK+ (GIMP Toolkit), escrito em linguagem C, e o Qt, escrito em linguagem C++, sendo que ambos possuem suporte, tanto oficial quanto desenvolvido por terceiros, a uma ampla variedade de linguagens de programação, como C, C++, Java, C#, Javascript, Python, Ruby, entre outras. Uma terceira opção é desenvolver em Java, utilizando uma de suas bibliotecas gráficas embutidas, AWT, SWING ou JavaFX. O problema em escolher uma destas três linguagens e seus toolkits reside na demasiada e, em muitos casos, indesejada complexidade destas ferramentas tradicionais, sendo que, até mesmo engenheiros de software experientes podem demonstrar frustração com tal complexidade. Nesse sentido, Pike (2010) afirma que, tendo a linguagem C e o UNIX tornado-se um padrão dominante em ambientes de pesquisa, o desejo por uma linguagem de mais alto nível levou à criação do C++, o qual trouxe uma implementação de orientação a objetos ao C, e mesmo sendo uma implementação pobre, isto permitiu que o C++ se tornasse a linguagem preferencial escolhida por parte da indústria e por muitas universidades pesquisadoras. Posteriormente, surgiu o Java, que era como se fosse uma versão mais clara e enxuta do C++, e por volta do final dos anos 90, a necessidade de uma linguagem para ensino, que fosse didática e que tivesse relevância, fez com que o Java fosse escolhido para esse fim. Pike (2010) afirma, ainda, que estas linguagens (C/C++ e Java), apesar de serem ótimas nas mãos de experts e funcionarem bem em grandes projetos, são muito difíceis de usar, pois são difíceis de compreender, confusas e verbosas. E que esta forma desajeitada, inerente às principais linguagens, causou uma certa reação, favorecendo o surgimento de várias linguagens mais simples, como Ruby, Python, Lua, Javascript, Erlang e outras, as quais tornaram-se populares e bem-sucedidas, em parte, como uma rejeição às linguagens padrão. 4 Diante do cenário apresentado, a linguagem Gambas surge como uma opção bastante adequada para pequenos projetos, pois apresenta características que favorecem sua adoção por pessoas que possuem pouca ou nenhuma experiência no desenvolvimento de aplicações GUI em Linux, já que mascara C, C++, X, GTK+ e Qt, estrutura sobre a qual ela é construída, como será demonstrado adiante. 3 O projeto Gambas A palavra Gambas é um acrônimo recursivo em inglês, Gambas Almost Means BASIC, que significa, em tradução livre, “Gambas é quase BASIC”. A linguagem Gambas foi criada por um programador francês, chamado Benoît Minisini (seu primeiro nome é pronunciado [bənwa], em francês, segundo a Wikipédia (2015b)), em virtude de sua frustração com o Microsoft Visual Basic, por causa da enorme quantidade de bugs e inconsistências que a linguagem apresentava. Por ser um entusiasta da linguagem BASIC, Benoît Minisini construiu o Gambas buscando aperfeiçoar a sintaxe do Visual Basic e implementando também diversos recursos do ambiente integrado de desenvolvimento da Microsoft, pois Gambas além de ser uma linguagem com total suporte à programação orientada a objetos, é também um ambiente de desenvolvimento construído sobre um interpretador de BASIC e, além disso, é um software livre, de código-fonte aberto, disponibilizado sob a licença GNU GPLv2 (GNU General Public License, version 2), conforme definida pela Free Software Foundation (1991). Quanto à sua arquitetura, Gambas é amplamente inspirado pelo Java, sendo assim, um programa escrito em Gambas nada mais é do que um conjunto de arquivos, onde cada arquivo representa uma classe que será compilada para ser executada posteriormente pelo interpretador. A arquitetura do Gambas é composta basicamente por um compilador, um interpretador, um arquivador, um componente GUI e um ambiente de desenvolvimento, organizados como mostra a figura 1, a seguir: 5 Figura 1: Arquitetura do ambiente Gambas. Fonte: Minisini (2015b)3. A linguagem Gambas possui algumas características interessantes, elencadas por Minisini (2015a), que a diferem de outras linguagens disponíveis e demonstram sua versatilidade, tais como: Cada projeto é armazenado em um único diretório e o arquivador transforma todo o conteúdo do respectivo diretório em um único arquivo executável; Recompilar um projeto requer apenas a compilação das classes que sofreram alguma modificação e cada referência externa de uma classe é resolvida dinamicamente em tempo de execução; A arquitetura em componentes permite que a linguagem seja estendida com bastante facilidade, já que qualquer um pode escrever componentes em forma de bibliotecas compartilhadas que adicionam dinamicamente novas classes nativas ao interpretador, podendo escrevê-las em C, C++ ou simplesmente em Gambas, contando com a documentação online e com o código-fonte dos componentes originais; Os projetos podem ser traduzidos facilmente para qualquer idioma, pois o Gambas foi concebido com a internacionalização em mente e por isso tem suporte a strings (cadeias de caracteres) codificadas no padrão UTF-8; O modelo de objeto implementado é simples, mas é bastante poderoso. O Gambas está em sua terceira versão, mais precisamente, na versão 3.7.1, e por ser 3 Projeto Gambas: arquitetura. Disponível em: <http://gambas.sourceforge.net/en/architecture.html> Acesso em: 30 jun. 2015. 6 um projeto em desenvolvimento, apesar de completamente funcional e estável, ainda possui componentes minimamente desenvolvidos ou inacabados, a exemplo do componente GTK+, e outras desvantagens inerentes à forma como o projeto foi implementado, como a alta dependência de bibliotecas de terceiros. Por isso, tendo sido desenvolvido originalmente para ambiente Linux, Gambas está profundamente ligado ao padrão POSIX, bem como a várias bibliotecas, entre as quais destacam-se: Qt4, Qt5, GTK+, SDL (Simple DirectMedia Layer), Video4Linux, etc. Há ainda o problema da incompatibilidade entre projetos criados na segunda versão e os criados na terceira versão do Gambas, pois houve aprimoramentos significativos e substanciais, tanto na sintaxe da linguagem, quanto na estrutura do ambiente de desenvolvimento, e por esse motivo, estão disponíveis para download no site do projeto Gambas, tanto a segunda versão (2.24.0), quanto a terceira (3.7.1). Mas, apesar de estar em desenvolvimento e ser mantido por uma pessoa apenas, não por uma empresa ou organização, o projeto evolui com bastante agilidade, sendo que a penúltima versão (3.7.0) foi lançada em 14 de março de 2015, corrigindo 267 bugs reportados e adicionando 299 novas funcionalidades, além de 7 otimizações, ao passo que a última versão (3.7.1) foi lançada em 1 de abril de 2015, menos de um mês depois, corrigindo todos os bugs reportados desde o lançamento da versão anterior e trazendo mais funcionalidades, de acordo com Minisini (2015b). Quanto à compatibilidade, verifica-se que, devido à sua grande quantidade de dependências, o projeto Gambas não é considerado multiplataforma, pois mesmo compilando e instalando com pouca ou nenhuma dificuldade em diversas distribuições Linux diferentes, há uma certa dificuldade em portar o código-fonte para outros sistemas operacionais, mesmo para os mais populares, baseados em Unix, como aqueles derivados do BSD (FreeBSD, OpenBSD, NetBSD), bem como o Solaris e o Mac OS X, além do Microsoft Windows, o qual não é compatível em arquitetura nem com Linux nem com Unix/BSD. É possível observar os níveis de compatibilidade do projeto Gambas com os principais sistemas operacionais no quadro 1, abaixo: Sistema Operacional Nível de compatibilidade Observação Debian – Linux OK Ver arquivo README.DEBIAN no pacote de códigofonte. Fedora – Linux OK - Mandriva – Linux OK - 7 OpenSUSE – Linux OK - RedHat – Linux OK Ver arquivo README.REDHAT no pacote de códigofonte. Slackware – Linux OK Pode apresentar um pouco de dificuldade para compilar ou instalar na versão 10.1 do Slackware. Ubuntu – Linux OK Gambas 2 está disponível no repositório padrão do S.O. Gambas 3 está disponível via repositório PPA. FreeBSD OK Gambas 1 e 2 estão disponíveis oficialmente. Gambas 3 pode ser compilado sem problemas. OpenBSD Incerto Trabalho em progresso… NetBSD Incerto Trabalho em progresso… Mac OS X em PowerPC Ruim É possível que compile normalmente, mas não funcionará corretamente devido a bugs no gerenciamento de terminação (endianness management) Solaris Incerto Gambas compila normalmente, mas pode não funcionar corretamente. Windows Ruim As versões estáveis do compilador e do interpretador do Gambas podem ser compilados através da ferramenta CygWin, mas os componentes não podem. Desta forma, é possível que aplicações sem interface gráfica funcionem. Quadro 1: Níveis de compatibilidade do projeto Gambas com diversos sistemas operacionais. Fonte: Adaptado de Minisini (2015a)4. Observando-se todas as características da linguagem apresentadas, nota-se que é necessário um bom ambientes de desenvolvimento para que um programador possa usufruir amplamente de todo o potencial encerrado na linguagem, e nesse quesito, o projeto Gambas também não decepciona. 4 O ambiente integrado de desenvolvimento O projeto Gambas contém, além da linguagem, um ambiente integrado de desenvolvimento (IDE), cuja interface foi completamente desenvolvida na própria linguagem Gambas, utilizando o componente de interfaces gráficas, ou seja, ao utilizar a interface do IDE, o usuário recebe uma amostra do quão complexa pode ser uma aplicação desenvolvida com tal ferramenta. O ambiente integrado do Gambas foi criado com base no IDE do Microsoft Visual Basic, sendo, portanto, muito semelhante a este. Ao executar o IDE do Gambas, visualiza-se 4 Documentação do Projeto Gambas: distribuições e sistemas operacionais. Disponível em: <http://gambaswiki.org/wiki/doc/distro?w&l=en> Acesso em: 7 jul. 2015. 8 antes de tudo, a janela Tips of the day (Dicas do dia), a qual permite navegar por 30 dicas muito úteis sobre a linguagem. Dispensada a dica do dia, nota-se que o IDE traz uma tela inicial através da qual é possível criar novos projetos, abrir projetos existentes, abrir aplicações de exemplo, gerenciar aplicações baixadas da Software Farm e acessar a Software Farm (fazenda de aplicações), que é um repositório de aplicações desenvolvidas em Gambas. Após a criação de um novo projeto ou abertura de um projeto criado anteriormente, verificase que a interface principal do IDE está dividido em seções e que cada uma delas tem uma função específica dentro do ambiente para que o programador possa realizar diversas tarefas inerentes ao desenvolvimento de software com facilidade e eficiência. Na lateral esquerda do IDE existe uma seção, chamada de project explorer (explorador de projeto) que permite que o programador possa pesquisar ou explorar a estrutura do projeto em uso – suas pastas, arquivos, conexões de bancos de dados, etc. Na parte superior da lateral direita encontra-se a properties window (janela de propriedades), a qual está dividida em duas abas, sendo que a primeira aba permite a visualização e alteração das propriedades dos controles selecionados, exibindo a descrição detalhada de cada propriedade destacada em sua porção inferior, ao passo que a segunda aba permite observar e organizar a hierarquia dos controles presentes nos forms (formulários). Abaixo da janela de propriedades está localizada a toolbox (caixa de ferramentas) que, por sua vez, armazena todos os controles disponíveis para o programador, organizados em diversas categorias (form, view, chooser, container, data, etc.), permitindo que o programador encontre com facilidade, entre muitos, o controle desejado. Ao centro, na parte inferior, quase como um rodapé, está acomodado o console, que é uma ferramenta bastante versátil, na qual concentram-se todas as tarefas relativas a testes e detecção de erros (debug). Esta ferramenta possui diversas abas através das quais o programador extrai da aplicação, durante a execução em modo de debug (depuração), todas as informações necessárias para correções de erros, podendo realizar várias tarefas como verificar na saída do console as mensagens postas no código-fonte para controle, inspecionar variáveis, gerenciar breakpoints (pontos de interrupção), controlar o fluxo da aplicação em teste, observar o stack backtrace (controle da pilha), etc. O console possui ainda um avaliador de expressões. Por último, a maior parte da porção central do IDE abriga uma seção reservada para que o programador possa desenhar interfaces gráficas, chamadas de formulários (forms), bem como editar documentos de texto de qualquer natureza, sejam eles classes, módulos, documentos HTML, XML, CSS, etc. Esta seção permite que o programador possa abrir quantos formulários ou 9 classes e módulos julgar necessários, já que os organiza em abas especializadas e, sendo assim, as abas que possibilitam a criação e edição formulários trazem funcionalidades específicas para estas tarefas, bem como um editor de menus, ao passo que as abas que comportam documentos de texto trazem funcionalidades voltadas para edição e navegação pelo código-fonte, além de recursos mais avançados e complexos como highlight, que destaca trechos do código-fonte e palavras reservadas da linguagem em cores diferentes definidas de acordo com suas funções, e sugestões para completação do código digitado exibidas em conjunto com a ajuda online em uma janela pop-up. O IDE do Gambas proporciona ao programador a possibilidade de distribuir suas aplicações em diversos formatos, já que além de poder executar a aplicação em modo de depuração, o programador pode gerar, a partir de seu projeto, um único arquivo executável, um arquivo compactado contendo todos os arquivos do projeto ou um pacote de instalação, sendo que neste último caso, há opção de gerar pacotes (.rpm, .deb, etc.) para diversas distribuições Linux disponíveis atualmente como Archlinux, Debian, Mageia, OpenSUSE, Ubuntu / Mint, Fedora / RedHat / CentOS, Mandriva e Slackware, podendo ainda gerar arquivos para instalação através da ferramenta Autotools. Diante das características apresentadas, pode-se observar que o ambiente integrado de desenvolvimento que acompanha a linguagem Gambas é, sem sombra de dúvida, uma ferramenta extraordinária, como também elogia Nicholson (2011, p. 3). Resta agora verificar na prática se é possível desenvolver aplicações úteis e funcionais utilizando-se tal ferramenta e linguagem, e com que grau de facilidade ou de dificuldade consegue-se concluir esta tarefa. 5 Desenvolvendo uma aplicação simples Desenvolveu-se para a produção deste artigo, como um test drive do ambiente integrado de desenvolvimento e da linguagem BASIC presentes no projeto Gambas, uma aplicação simples que consiste numa interface gráfica para um banco de dados de teste chamado Chinook Database, que é uma alternativa livre ao banco de dados de exemplo disponibilizado pela Microsoft em conjunto com seus produtos Access e SQL Server, chamado Northwind Traders Database, que contém dados das transações de uma empresa fictícia homônima, do ramo de importação e exportação de alimentos. O banco de dados Chinook, cujo modelo é apresentado na figura 2, contém, por sua vez, dados fictícios de uma 10 loja que venderia músicas em meio digital para download, organizados em onze tabelas, sendo que aqueles referentes ao acervo foram importados de uma biblioteca real (ROCHA, 2012). Figura 2: Modelo de dados, ou esquema, do banco Chinook. Fonte: Rocha (2012)5. A aplicação desenvolvida, intitulada “Chinook CRUD” para referência, permite ao usuário final, como o título sugere, a realização das quatro operações básicas no banco de dados Chinook, quais sejam: criar, ler, atualizar e excluir (CRUD – Create / Read / Update / Delete). Com foco no projeto Gambas, e não no banco de dados em si, optou-se pela versão para SQLite da base de dados Chinook, pois o SQLite é um motor de banco de dados SQL (structured query language) transacional, autossuficiente, sem servidor, e sem necessidade de configuração ou instalação, além de ser um software em ampla utilização no mundo inteiro e 5 Documentação do projeto Chinook: esquema. Disponível em: <https://chinookdatabase.codeplex.com/wikipage?title=Chinook_Schema> Acesso em: 21 jul. 2015. 11 cujo código-fonte é de domínio público (Kreibich, 2010), características que contribuem para um ambiente de desenvolvimento mais simples e ágil, em oposição aos sistemas de gerenciamento de bancos de dados (SGBD) mais robustos MySQL e Postgres ambos também suportados pelos drivers nativos do projeto Gambas. Apesar de a linguagem Gambas permitir a criação de controles como botões e caixas de texto em tempo de execução, a interface, ou front-end Chinook CRUD foi totalmente desenhada no editor de formulários do IDE, sem a necessidade de se escrever uma única linha de código-fonte, através de recursos gráficos como “arrastar e soltar” usando o mouse e posicionando os controles no formulário utilizando as teclas de seta, com o objetivo de experimentar as comodidades que o Gambas proporciona ao programador que possui pouca ou nenhuma experiência com esta ferramenta, e o resultado apresentou-se de forma bastante satisfatória, como se pode constatar na figura 3, abaixo. Esta interface foi construída de forma bastante simples e ágil, aproveitando-se a eficiência e praticidade do editor de formulários, e utilizando-se um conjunto reduzido de controles, como é possível notar, já que foram utilizados apenas: cinco botões (buttons) que permitem carregar ou limpar os dados exibidos em cada aba, inserir novos registros, excluir registros existentes e salvar ou cancelar as alterações realizadas; uma caixa de marcação (checkbox) para alternar entre o modo de visualização e leitura dos registros e o modo que possibilita a edição dos mesmos; um divisor em abas (tabstrip) responsável por separar cada tabela do banco de dados em uma aba diferente; onze visualizadores de tabela (tableviews) que foram posicionados um a um nas abas do divisor e têm a capacidade de exibir os registros carregados do banco de dados; além de uma caixa de texto (textbox) que fica oculta ao usuário, sendo exibida somente no momento da edição dos dados. Estes controles, além de terem sido organizados conforme apresentados na figura 3, utilizando-se o editor de formulários, também tiveram algumas de suas propriedades modificadas em relação a seus valores padronizados, através da janela de propriedades, pois esta abordagem previne a inserção de linhas de código desnecessárias, deixando o código-fonte mais simples, limpo e fácil de compreender. Apesar de a linguagem permitir que o programador altere as propriedades dos controles em tempo de execução, de forma programática, tal abordagem é melhor aproveitada nas ocasiões em que se deseja que estas alterações ocorram de forma condicional, durante a execução e uso da aplicação e não quando a intenção é apenas definir valores estáticos iniciais para estas propriedades. Desta forma, para reproduzir corretamente a interface exibida na figura 3, é necessário observar 12 também, as informações apresentadas no Apêndice A, intitulado “Propriedades dos controles no formulário FPrincipal”. Figura 3: Interface Chinook CRUD exibindo registros carregados do banco de dados Chinook em SQLite. Fonte: Elaboração própria (2015). Após desenhada a interface e configuradas as propriedades de seus controles, desenvolveu-se o código-fonte da aplicação Chinook CRUD, apresentado nos Apêndices B, C e D. Como o IDE do Gambas trata de forma diferenciada os formulários (gráficos) e seus códigos-fonte (textos), cada formulário criado gera automaticamente no projeto uma classe homônima vinculada a este, através da qual é possível referenciar diretamente o respectivo formulário, bem como seus controles, como sendo objetos, acessando assim suas propriedades ou invocando seus métodos. Na pasta do projeto Chinook CRUD, por exemplo, o arquivo “FPrincipal.form” representa o formulário em si, que é apenas um elemento visual estático, conforme visto na figura 3, acima, enquanto que o arquivo “FPrincipal.class” representa uma classe que encerra a lógica de programação responsável pela automação do formulário, ou 13 seja, contém o código-fonte que faz com que, por exemplo, o botão “Salvar” grave efetivamente as alterações realizadas no banco de dados. Dito isto, entende-se que, já que o projeto em questão possui apenas um formulário, toda a lógica estaria armazenada no arquivo “FPrincipal.class”, cujo conteúdo está reproduzido integralmente no Apêndice B, nomeado de “Código-fonte da classe FPrincipal”, porém, apesar de tal abordagem ser possível, devido à heterogeneidade do código-fonte como um todo, em nome da legibilidade e da facilidade de compreensão do mesmo, optou-se por seccioná-lo, mantendo na classe associada ao formulário apenas a lógica referente ao próprio formulário, seus controles, propriedades, ações e eventos, migrando-se o restante do código-fonte para outros dois arquivos. O primeiro deles é “CDados.class”, que contém tanto a lógica de acesso ao banco de dados quanto das operações CRUD, e seu teor pode ser observado detalhadamente no Apêndice C, rotulado como “Código-fonte da classe CDados”. Esta classe acessa o arquivo “Chinook.sqlite”, que contém o banco de dados e o representa, dependendo para tal tarefa, tanto do sistema operacional, quanto do sistema de arquivos e até mesmo do hardware em si, mais especificamente, do disco rígido (hard disk ou hard drive). Por este motivo, sua lógica tem maior probabilidade de falhar, já que a aplicação pode não conseguir acessar o banco de dados pelos mais diversos motivos, como falta de permissão, erro do sistema operacional, inexistência do arquivo no disco, e mesmo que seja possível acessar o arquivo e realizar a conexão, a lógica ainda pode falhar se alguma operação CRUD solicitada ao banco de dados falhar ou for impossível de ser realizada, a exemplo da inserção de uma data inválida como “31/02/2015”. Tendo em mente a possibilidade de falha, a classe CDados foi implementada utilizando-se, em parte, o controle de erros que a linguagem proporciona através das palavras reservadas try, catch e finally, sendo necessário observar, ainda, que a linguagem também permite o controle de erros através do uso de rótulos (labels) em conjunto com as palavras reservadas “On Error Goto” e “On Error GoSub”. O segundo arquivo é “MBiblio.module” que contém toda a lógica reaproveitável e não associada ao banco de dados nem ao formulário e seus elementos especificamente. Note-se que este aquivo não representa uma classe, mas sim um módulo, que em Gambas é como uma biblioteca, ou seja, contém funções que podem ser reutilizadas, evitando assim que haja repetição de um mesmo trecho de código dentro do projeto, favorecendo a tarefa de manutenção do código-fonte. O Apêndice D – Código-fonte do módulo MBiblio – traz esta lógica, permitindo uma melhor compreensão da abordagem em comento. 14 Por fim, entende-se desnecessária a criação de um menu, que pode ser criado com extrema facilidade utilizando-se o editor de menus disponível no IDE do Gambas, por ser o Chinook CRUD uma aplicação simples, que não implementa qualquer tipo de funcionalidade ou configuração avançadas. Cumpre-se assim o escopo proposto, qual seja, a implementação, em Gambas, de uma interface gráfica capaz de realizar as operações CRUD no banco de dados Chinook em SQLite. Note-se, no entanto, que esta aplicação pode ser aperfeiçoada, pois ainda restam arestas que não foram aparadas, intencionalmente, em respeito ao prazo e ao escopo propostos. 6 Conclusão Após a implementação bem-sucedida do projeto Chinook CRUD pelo autor, mesmo sem que este possuísse domínio prévio sobre a ferramenta (IDE do Gambas) ou sobre a linguagem (Gambas BASIC), concluiu-se que o projeto Gambas cumpre seu papel, sem a menor sombra de dúvida, permitindo que um usuário mediano do sistema operacional GNU/Linux, não necessariamente um programador formado, possa desenvolver aplicações simples, sobretudo interfaces do tipo front-end, com bastante facilidade e poucos contratempos, já que Gambas é um dialeto BASIC e herda deste suas principais características (ser fácil, de uso geral, extensível, interativo, amigável, veloz na execução, transparente e seguro (MARCONI, 2015; WIKIPÉDIA, 2015a)). Usuários avançados de suítes de escritório como Microsoft Office ou LibreOffice acostumados a escrever macros, para automatizar planilhas por exemplo, não terão dificuldade em desenvolver pequenos projetos em Gambas, já que ambas as suítes citadas adotaram implementações da linguagem BASIC para automatização via macros cujos dialetos diferem minimamente daquele implementado por Benoît Minisini. Este artigo não pretende ser e, por consequência, não é um manual didático da linguagem Gambas BASIC, mas pretende, no entanto, apresentar as características do projeto como um todo, mantendo o foco na linguagem, no ambiente integrado de desenvolvimento e no escopo das aplicações do tipo front-end com acesso a banco de dados. Mesmo assim, os Apêndices B, C e D possibilitam um vislumbre da sintaxe da linguagem e de como funciona sua lógica. Este artigo pretende, ainda, contribuir de forma significativa para a popularização do Projeto Gambas e da filosofia do software livre, pois, apesar do escopo limitado deste 15 trabalho, o Gambas é muito mais versátil do que isto, podendo ser utilizado para desenvolver aplicações de linha de comando, aplicações web (CGI), jogos e até mesmo scripts não compilados, o que, sem dúvida, proporciona um ambiente rico e inspirador para trabalhos vindouros, especialmente nas áreas de desenvolvimento web e de criação de jogos para GNU/Linux utilizando a biblioteca SDL (Simple DirectMedia Layer). Abstract This article aims to present the GAMBAS language, which is a variant of BASIC, as an alternative for developing graphical user interface (GUI) applications, on GNU/Linux environment, as opposed to well-known commercial languages, like Java and C/C++, those of which have more steep learning curves. For that purpose, a graphical CRUD (Create/Read/Update/Delete) interface for the free demonstration database Chinook, in its version for SQLite, was developed. It was concluded, through this experiment, that the GAMBAS language has a great potencial for the development of applications of the front-end type, for besides of its easiness of learning, for having a great online and offline documentation, built in a good integrated development environment (IDE), totally written in GAMBAS, with support to drag and drop controls in a WYSIWYG (What You See Is What You Get) interface, it also brings native support to Postgres, MySQL and SQLite databases, plus support to ODBC connections. Keywords GAMBAS. BASIC. SQLite. GNU/Linux. GUI Applications. Referências FREE SOFTWARE FOUNDATION. GNU General Public License, version 2. Boston: Free Software Foundation Inc., 1991. Disponível em: <http://www.gnu.org/licenses/oldlicenses/gpl-2.0.html> Acesso em: 30 jun. 2015. KREIBICH, J. A. Using SQLite: Small. Fast. Reliable. Choose Any Three. 1. ed. O'Rilley Media, 2010. MARCONI, A. M. History of BASIC: History of the BASIC Programming Language by Andrea M. Marconi. Disponível em: <http://q7basic.org/History%20of%20BASIC.pdf> Acesso em: 28 ago. 2015. MATTHEW, N.; STONES, R. Beginning Linux® Programming 4th Edition. 4. ed. Wrox Press e Wiley Publishing, 2007. 16 MINISINI, B. Documentação do Projeto Gambas. Disponível em: <http://gambaswiki.org/wiki/doc/intro> Acesso em: 3 jul. 2015. ______. Projeto Gambas. Disponível em: <http://gambas.sourceforge.net/en/main.html> Acesso em: 30 jun. 2015. PIKE, R. Public Static Void. In: O'Reilly Open Source Convention (OSCON), 12, 2010, Portland. Disponível em: <http://www.oscon.com/oscon2010> Acesso em: 26 jun. 2015. ROCHA, L. Projeto Chinook Database. Califórnia: CodePlex (Microsoft), 2012. Disponível em: <https://chinookdatabase.codeplex.com> Acesso em: 20 jul. 2015. RITTINGHOUSE, J. W.; NICHOLSON, J. A Beginner's Guide to Gambas – Revised Edition. 2. ed. Infinity Publishing, 2011. Disponível em: <http://whiteislandsoftware.com/index.php?page=cedi&type=misc&id=64> Acesso em: 19 jul. 2015. WIKIPÉDIA. BASIC. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://pt.wikipedia.org/wiki/BASIC> Acesso em: 26 jul. 2015. ______. Benoît. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://en.wikipedia.org/wiki/Beno%C3%AEt> Acesso em: 30 jun. 2015. ______. Linux adoption. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: <https://en.wikipedia.org/wiki/Linux_adoption> Acesso em: 26 jun. 2015. 17 APÊNDICE A – Propriedades dos controles no formulário FPrincipal Nome do controle Tipo do controle btnCarregar btnInserir btnExcluir btnSalvar btnCancelar chkEditar Button Button Button Button Button CheckBox Nome da propriedade Valor da propriedade Height 32 Text Carregar Dados Width 120 X 16 Y 8 Enabled False Height 32 Text Inserir Linha Width 120 X 211 Y 8 Enabled False Height 32 Text Excluir Linha Width 120 X 344 Y 8 Enabled False Height 32 Text Salvar Width 120 X 16 Y 392 Enabled False Height 32 Text Cancelar Width 120 X 144 Y 392 Enabled False 18 Nome do controle Tipo do controle chkEditar txtEditor tabTabelas TableView1 a TableView11 CheckBox TextBox TabStrip TableViews Nome da propriedade Valor da propriedade Height 24 Text Editar Width 70 X 139 Y 13 Height 32 Visible False Width 120 X 272 Y 392 Count 11 Height 328 Tag Chinook Album / Artist / Customer / Employee / Text (Obs.: cada aba tem Genre / Invoice / sua propriedade Text.) InvoiceLine / MediaType / PlayList / PlaylistTrack / Track Width 496 X 16 Y 56 Group TableViews Header Horizontal Height 264 Mode Single Width 464 X 16 Y 24 19 APÊNDICE B – Código-fonte da classe FPrincipal ' Gambas class file Static Private estaTableView As TableView Static Private intSequencia As Integer Public Sub _new() End Public Sub Form_Open() CDados.Preparar() End Public Sub btnCarregar_Click() MBiblio.DesCarregar(tabTabelas) End Public Sub tabTabelas_Click() If btnSalvar.Enabled = True And tabTabelas.Index <> btnSalvar.Tag Then tabTabelas.Index = btnSalvar.Tag Message("Há dados não salvos nesta aba!") Return Endif estaTableView = tabTabelas.Children[0] btnCarregar.Text = IIf(Right(tabTabelas.Caption) = "*", "Limpar Dados", "Carregar Dados") chkEditar.Enabled = Right(tabTabelas.Caption) = "*" btnInserir.Enabled = Right(tabTabelas.Caption) = "*" btnExcluir.Enabled = Right(tabTabelas.Caption) = "*" If Right(tabTabelas.Caption) <> "*" Then chkEditar.Value = False btnSalvar.Enabled = False btnCancelar.Enabled = False Endif If chkEditar.Value Then btnInserir.Enabled = False 20 btnExcluir.Enabled = False Endif End Public Sub chkEditar_Click() If chkEditar.Value Then CDados.GerenciarTransacoes("Iniciar") btnExcluir.Enabled = False estaTableView.Tag = "Editando" Else CVariant(tabTabelas.Children[0]).Cancel() btnInserir.Enabled = True btnExcluir.Enabled = True Endif End Public Sub TableViews_Click() If chkEditar.Value And Last.Column <> 0 Then btnSalvar.Tag = tabTabelas.Index If Right(Last[Last.Row, 0].Text, 1) <> "*" Then Last.EditWith(txtEditor) Endif Endif End Public Sub txtEditor_Change() If txtEditor.Text <> estaTableView.Current.Text Then btnSalvar.Enabled = True btnCancelar.Enabled = True Endif End Public Sub TableViews_Save(Row As Integer, Column As Integer, Value As String) btnSalvar.Enabled = True btnCancelar.Enabled = True Last[Row, Column].Text = Value 21 If estaTableView.Tag = "Editando" Then CDados.editarCelula(Left(tabTabelas.Caption, -1), Last.Columns[0].Title, Last[Row, 0].Text, Last.Columns[Column].Title, Value) Endif End Public Sub btnInserir_Click() CDados.GerenciarTransacoes("Iniciar") TableViews_Insert() End Public Sub TableViews_Insert() If intSequencia = 0 Then intSequencia = CDados.IntObterSequencia(Left(tabTabelas.Caption, -1)) estaTableView = tabTabelas.Children[0] btnSalvar.Tag = tabTabelas.Index If chkEditar.Value = False Then chkEditar.Value = True btnSalvar.Enabled = True btnCancelar.Enabled = True If estaTableView.Tag = "Inserindo" Then estaTableView.Rows.Count += 1 estaTableView[estaTableView.Rows.Count - 1, 0].Text = intSequencia + estaTableView.Rows.Count estaTableView.MoveTo(estaTableView.Rows.Count - 1, 1) Else estaTableView.Tag = "Inserindo" estaTableView.Clear() estaTableView.Rows.Count = 1 estaTableView[estaTableView.Rows.Count - 1, 0].Text = intSequencia + 1 estaTableView.MoveTo(estaTableView.Rows.Count - 1, 1) Endif estaTableView.EditWith(txtEditor) txtEditor.SetFocus() End 22 Public Sub btnSalvar_Click() Dim i As Integer If txtEditor.Text <> estaTableView.Current.Text Then estaTableView.Current.Text = txtEditor.Text Endif If estaTableView.Tag = "Editando" Then CDados.editarCelula(Left(tabTabelas.Caption, -1), estaTableView.Columns[0].Title, estaTableView[estaTableView.Row, 0].Text, estaTableView.Columns[estaTableView.Column].Title, txtEditor.Text) estaTableView.Tag = "" Endif If estaTableView.Tag = "Inserindo" And estaTableView.Rows.Count > 0 Then For i = 0 To (estaTableView.Rows.Count - 1) CDados.InserirRegistro(MBiblio.StrGerarInsert(Left(tabTabelas.Caption, -1), estaTableView, i)) Next estaTableView.Tag = "" Endif CDados.GerenciarTransacoes("Salvar") btnSalvar.Enabled = False btnCancelar.Enabled = False intSequencia = CDados.IntObterSequencia(Left(tabTabelas.Caption, -1)) End Public Sub txtEditor_Leave() If txtEditor.Text <> estaTableView.Current.Text Then estaTableView.Current.Text = txtEditor.Text If estaTableView.Tag = "Editando" Then CDados.editarCelula(Left(tabTabelas.Caption, -1), estaTableView.Columns[0].Title, estaTableView[estaTableView.Row, 0].Text, estaTableView.Columns[estaTableView.Column].Title, txtEditor.Text) Endif Endif 23 End Public Sub btnCancelar_Click() CDados.GerenciarTransacoes("Cancelar") btnCarregar_Click() btnSalvar.Enabled = False btnCancelar.Enabled = False btnInserir.Enabled = False btnExcluir.Enabled = False End Public Sub btnExcluir_Click() If Right(estaTableView[estaTableView.Row, 0].Text, 1) <> "*" btnSalvar.Tag = tabTabelas.Index CDados.GerenciarTransacoes("Iniciar") CDados.ExcluirRegistro(Left(tabTabelas.Caption, -1), estaTableView.Columns[0].Title, estaTableView[estaTableView.Row, 0].Text) estaTableView[estaTableView.Row, 0].Text &= "*" btnSalvar.Enabled = True btnCancelar.Enabled = True Endif End 24 APÊNDICE C – Código-fonte da classe CDados ' Gambas class file Private Const cstTipoBD As String = "sqlite" Private Const cstNomeBD As String = "Chinook" Static Private Con As New Connection Static Private Res As Result Static Private blnEmTransacao As Boolean Static Public arrTabela As Variant Static Public arrCampos As String[] Static Public arrLarguraCampos As Integer[] Static Public Sub Preparar() Con.Type = cstTipoBD Con.Host = Application.Path Con.Name = cstNomeBD & "." & cstTipoBD End Static Public Sub Conectar() If Not Con.Opened Then Try Con.Open() If Error Then Message("Não foi possível conectar ao banco '" & Con.Name & "' em " & Con.Host & ".") Quit Endif Endif End Static Public Sub Desconectar() If Con.Opened Then Try Con.Close() If Error Then Message("Erro ao fechar conexão com o banco.") 25 Quit Endif Endif End Static Public Sub ObterTabela(strTabela As String) Dim i, j As Integer Res = Con.Find(strTabela) arrTabela = New Variant[Res.Count, Res.Fields.Count] arrCampos = New String[Res.Fields.Count] arrLarguraCampos = New Integer[Res.Fields.Count] For i = 0 To (Res.Fields.Count - 1) arrCampos[i] = Res.Fields[i].Name arrLarguraCampos[i] = Res.Fields[i].Length Next For i = 0 To (Res.Count - 1) For j = 0 To (Res.Fields.Count - 1) arrTabela[i, j] = Res[arrCampos[j]] Next Res.MoveNext() Next End Static Public Sub EditarCelula(strTabela As String, strColunaID As String, strValorID As String, strColunaEditada As String, strNovoValor As String) Res = Con.Edit(strTabela, strColunaID & " = &1", strValorID) Res[strColunaEditada] = strNovoValor Res.Update() Catch Message("Não foi possível atualizar o valor da coluna " & strColunaEditada & " para " & strNovoValor & ".") End Static Public Sub InserirRegistro(strInsert As String) Try Res = Con.Exec(strInsert) 26 If Error Then Message("Não foi possível inserir registro.") Endif End Static Public Sub ExcluirRegistro(strTabela As String, strColunaID As String, strValorID As String) Try Res = Con.Exec("DELETE FROM " & strTabela & " WHERE " & strColunaID & " = " & strValorID) If Error Then Message("Não foi possível excluir o registro de " & strColunaID & " = " & strValorID & " da tabela " & strTabela & ".") Endif End Static Public Function IntObterSequencia(strTabela As String) As Integer Res = Con.Find("sqlite_sequence", "Name = &1", strTabela) Return Res["seq"] End Static Public Function GerenciarTransacoes(strAcao As String) If strAcao = "Iniciar" And blnEmTransacao = False Then blnEmTransacao = True Try Con.Begin() If Error Then blnEmTransacao = False Message("Não foi possível Iniciar a transação.") Endif Endif If strAcao = "Salvar" And blnEmTransacao Then blnEmTransacao = False Try Con.Commit() If Error Then blnEmTransacao = True Message("Não foi possível Salvar a transação.") 27 Endif Endif If strAcao = "Cancelar" And blnEmTransacao Then blnEmTransacao = False Try Con.Rollback() If Error Then blnEmTransacao = True Message("Não foi possível Cancelar a transação.") Endif Endif End 28 APÊNDICE D – Código-fonte do módulo MBiblio ' Gambas module file Const LarguraFixa As Integer = 100 Public Sub DesCarregar(estaTabStrip As TabStrip) Dim i, j As Integer Dim estaTableView As TableView estaTableView = estaTabStrip.Children[0] If Right(estaTabStrip.Caption) <> "*" Then CDados.Conectar() CDados.obterTabela(estaTabStrip.Caption) estaTableView.Columns.count = CDados.arrCampos.Count For i = 0 To (CDados.arrCampos.Max) estaTableView.Columns[i].text = CDados.arrCampos[i] estaTableView.Columns[i].width = IIf(CDados.arrLarguraCampos[i] > 10, CDados.arrLarguraCampos[i] + LarguraFixa * 1.5, LarguraFixa) Next estaTableView.Rows.Count = (CDados.arrTabela.Bounds[0]) For i = 0 To (CDados.arrTabela.Bounds[0] - 1) For j = 0 To (CDados.arrTabela.Bounds[1] - 1) estaTableView[i, j].Text = CDados.arrTabela[i, j] Next Next Else estaTableView.Clear() estaTableView.Rows.Count = 0 estaTableView.Refresh() CDados.Desconectar() Endif estaTabStrip.Caption = IIf(Right(estaTabStrip.Caption) = "*", Left(estaTabStrip.Caption, -1), estaTabStrip.Caption & "*") 29 FPrincipal.tabTabelas_Click() End Public Function StrGerarInsert(strNomeTabela As String, estaTableView As TableView, intLinha As Integer) As String Dim i As Integer Dim strRetorno As String strRetorno = "INSERT INTO " & strNomeTabela & " (" For i = 1 To (estaTableView.Columns.Count - 1) strRetorno &= estaTableView.Columns[i].Text & "," Next strRetorno = Left(strRetorno, -1) strRetorno &= ") VALUES (" For i = 1 To (estaTableView.Columns.Count - 1) strRetorno &= "'" & estaTableView[intLinha, i].Text & "'," Next strRetorno = Left(strRetorno, -1) strRetorno &= ")" Return strRetorno End