Primeira versão estável do ObexFTP front-end está disponível!
Este blog deixou de ser mantido, mas o autor continua escrevendo aqui. Não deixe de assinar o novo feed!
É com grande satisfação que anuncio a primeira versão estável da minha mais recente empreitada Open Source: ObexFTP front-end! Por isso, se você usa Linux mas ainda precisa enviar e baixar arquivos do seu celular (e se este é compatível com o ObexFTP), fica aqui o convite a você para fazer um teste. Eu lhe asseguro de que irá gostar da ferramenta. (afinal, você prefere digitar comandos no terminal ou usar uma interface gráfica?)
Aos mais atentos já vou respondendo que sim, mudei o nome do projeto. Há algum tempo atrás eu batizei o projeto de OpenObex front-end, mas mudei pelo fato de que a aplicação usa apenas o ObexFTP, e não os outros aplicativos que fazem parte do OpenObex.
Aproveito para avisar que não usarei mais o blog para anunciar possíveis releases nem mostrar os recursos implementados no projeto até então. Foi justamente por este motivo que eu decidi hospedar o projeto no SourceForge.net!
Então, se você gostou do projeto e quer acompanhar o andamento do mesmo, basta visitar a página do projeto no SourceForge.net. Você pode também assinar os feeds para ficar sincronizado com as mudanças e avanços que estão por vir.
Se ficou curioso, visite o site do projeto no SourceForge.net e baixe uma cópia. Se você é desenvolvedor Java e gostaria de olhar o código-fonte, basta configurar seu cliente CVS e baixar o código… apesar de não estar perfeito, o código está razoavelmente bem testado (mais de 90 test cases) e documentado.
Antes de me despedir, eu gostaria muito se recebesse feedback das pessoas que baixaram e testaram a aplicação. Qualquer coisa: se estou no caminho certo (ou se não estou), se funcionou (ou se só deu problemas), enfim, elogios, críticas e sugestões de qualquer natureza. Por isso que eu considero o Open Source algo extremamente valioso: qualquer pessoa pode ajudar a mudar as coisas para melhor, nem que seja apenas apontando o caminho!
PS: Rafael, troquei o look and feel! ![]()


25 de julho de 2007 às 8:51 pm
Daniel, essa está sendo uma semana atípica, e não consegui ver o ObexFTP. Assim que puder, vou fuçar!
Aproveita e retribui.
See ya!
25 de julho de 2007 às 9:08 pm
Com o maior prazer! Vou tentar baixar o código do ModelMat aqui e, assim que sobrar um tempo, vou dar uma olhada nele e te dar um retorno.
Um abraço.
2 de agosto de 2007 às 3:26 am
Estou todo atrasado mesmo… Parar pra ver o OpenFTP não vai fazer muita diferença.
Primeiro, coisas que percebi logo de cara:

1) Ainda bem que você trocou o look and feel! Ufa! Está com o visual bem legal, limpo.
2) Na diálogo About, cadê nome, descrição e links das bibliotecas e imagens que você utilizou?
3) Pra que Logger? Vai ser útil pra alguém? No caso do OpenFTP eu acho que não, mas, se eu estiver errado, me explique onde isso é útil.
4) Aquele “Do you really want to quit?” é impertinente. É quase como “Você tem certeza que quer encerrar o aplicativo? Tem certeza? Certeza mesmo? Olha, hein…”.
Seria útil se o usuário estivesse no meio de uma operação, ou com alguma coisa não-salva. De outra forma, nem…
Depois:
o que dificulta a leitura.
- Senti falta da barra de estado. Aquelas animações maneiras que você utiliza, para mim, deveriam estar apenas na status bar. Tá tentando inovar, né?
- Tem documentação, mas em alguns lugares o código ultrapassa aquela linha demarcatória uns 3km
- Use PMD e FindBugs para dicas bem interessantes.
Os handlers que as views do OpenFTP implementam mostram que você concorda comigo: Swing é M + VC, e não M-V-C. Aliás, de onde veio a história que Swing é MVC de raiz, e não MVC-like?
Impressionante! Acho que todo mundo que programa em Swing utiliza Observer e Command como ligação entre as partes do aplicativo. Acho que é porque a gente aprende assim. Só que eu ando evitando ao máximo esses dois padrões.
Gosto de usar o que já está pronto no Swing, mas não de implementar e, sobretudo, odeio ler porque é difícil. Não tem um workflow bem definido, então você fica indo pra lá e pra cá entre classes e invocações de métodos tentando pegar a seqüência de atividades do programa.
No ModelMat eu consegui retirar todos Commands e Observers! Tá bom, tá bom… Isso só mostra que eu abuso deles, mas no geral eles podem mesmo ser substituídos por algo mais simples e funcional.
Que tal mover todo ou quase todo o comportamento das views para um presentation model?
Finalizando, o software está show! Se você pensa mesmo em atrair colaboradores, considere simplificar ao máximo a arquitetura dele, principalmente porque esses colaboradores provavelmente serão iniciantes, ou terão pouco tempo, ou curtem trabalhar apenas com GUI, ou tudo isso junto, fora alguma coisa.
Obs: Estou aprendendo a ser verboso assim programando em Java!
2 de agosto de 2007 às 4:19 am
Uau!
1) Também achei!
2) Bem observado, mas acho que tais informações deveriam ficar em outro lugar, tipo no arquivo README.txt.
3) Se eu te falar que o Logger já me salvou você acredita? Um amigo meu está fazendo uns testes no celular dele. Nada de mais, mas moramos em cidades diferentes, e eu não tenho como ir lá ver a coisa funcionar, o que complica um pouco as coisas. Até agora, graças aos logs, todos os problemas que tive que resolver foram localizados em alguns segundos, sem que fosse necessário debugar.
A outra razão de eu usar um nível pesado de logging é pq eu não conheço as entranhas do ObexFTP… por isso, se acontecer algo estranho, eu posso corrigir minha aplicação e ter informações suficientes para reportar um possível bug ao projeto ObexFTP.
4) Obrigado pelo toque.. eu mesmo odeio essas coisas, mas, como sempre tive que fazer isso pq me pediam, acabei me deixando levar pelo hábito. Mas vou habilitar a mensagem somente se existir um comando sendo executado no momento.
Afinal, o que é esse troço de barra de estado?? Pq do jeito que está não vejo a necessidade dela, seja ela lá o que for. Ainda mais se for um componente não-padrão (SwingX e primos). A idéia é trabalhar com os componentes-padrão do Swing.
Se quanto a falta de documentação você se refere a comentários no código… bom, eu odeio comentários! Se o código não ficou claro para você é porque ele precisa ser refatorado, e não de comentários. Ainda não fui atrás de instalar plugins nessa versão do NetBeans que eu estou usando.. como é a versão 6 M10, estou com receio de deixar o ambiente ainda mais instável.
Mas irei melhorar o código com certeza… é que agora estou focando mais na documentação ao usuário final (escrevendo um help e tal), e não a possíveis colaboradores.
Sobre a arquitetura, bom, ela está o mais limpa possível considerando o não-uso de frameworks e bibliotecas relacionadas a isso. Aqui volta o problema do refactoring, onde eu precisaria distribuir melhor o código (um exemplo claro é o frame principal). E olha que eu não sou muito chegado em espalhar Observers pelo código! É que, dadas os requisitos e restrições, foi a única opção.
Valeu pelas dicas preciosas! E fica tranquilo q eu não esqueci de te dar feedback quanto ao ModelMat… afinal, uma mão lava a outra.
Abraço.
2 de agosto de 2007 às 5:42 am
Foi mal, troquei o nome do seu software. Olha a errata aí gente!! Não é OpenFTP e sim ObexFTP!
É o sono, e isso só pode significar uma coisa: preciso…
… de mais café!
Ok, boa sacada a do logger…
Barra de estado == status bar
Tem documentação sim. Estava me referindo a formatação do código, porque tem algumas linhas extensas.
Ás vezes um framework pode ajudar o código ficar mais claro, graças a abstração e pelo fato da API ser mais bem conhecida.
Mas é isso aí, vamos discutindo…
2 de agosto de 2007 às 12:26 pm
Também, olha a hora!
É o problema da refatoração… existem alguns trechos de código fazendo mais coisas do que deveriam, daí esse problema.
2 de agosto de 2007 às 5:58 pm
Só esqueci de falar a respeito do uso do padrão Command. Bom, no meu caso foi mandatório, como explicarei a seguir.
Nessa aplicação, o usuário pode solicitar — quase que ao mesmo tempo — o download de um arquivo, o upload de outro arquivo e a remoção de um terceiro. Como nada é perfeito, a execução de uma dessas operações pode falhar e, se isso acontecer, a aplicação mostra uma mensagem para o usuário informando da falha e perguntando se ele deseja tentar executar a operação novamente. (odeio fazer a mesma coisa duas vezes enquanto uso um programa).
Como a solicitação foi convertida em um objeto Command, basta que eu inclua o Command que falhou novamente na fila de Commands pendentes e esperar que o CommandConsumer (objeto que observa a fila de Commands pendentes) o tente executar novamente. Se o usuário optar por não tentar novamente, esse Command que falhou é descartado e o próximo Command da fila é processado pelo CommandConsumer.
Também sou contra o uso de Commands disfarçados de Strategies/State. Mas, neste caso, estou usando um Command Command mesmo, que me permite fazer essa manipulação mais alto-nível. Além do mais, futuramente, o usuário poderá visualizar a fila de Commands pendentes e cancelar Commands abitrários. Então, no caso desta aplicação, os patterns foram usados conscientemente.
Só lembrando que essa característica “serial” de execução dos Commands é necessária, uma vez que estou executando processos que trabalham com a leitura e escrita de streams de dados em um dispositivo, e disparar vários processos manipulando o mesmo dispositivo ao mesmo tempo costuma fazer com que tanto o dispositivo quanto o processo se confundam.
2 de agosto de 2007 às 6:39 pm
Eu sei que você aplicou concientemente Command. Como disse antes, ler e implementar é que é difícil, depois fica fácil pra usar.
O que eu quis deixar no ar é que você fez no braço algo que já poderia ter pronto. Portanto, Command poderia ser evitado. Mas você também já comentou sobre isso ao dizer que decidiu tornar o ObexFTP “puro” Swing, sem frameworks, etc.
O diabo com Command e Observer é a dificuldade que eles causam para ler o código. Pensa só, se eu consegui até trocar o nome do ObexFTP lá prás cinco da matina, imagine então entender o workflow do software. Mesmo a estrutura não fica tão clara (IMHO), quanto mais o workflow.
Uma vez me disseram que eu “gostava de sofrer”, isso há um bom tempo atrás quando eu disse que preferia C++ a .NET ou Java. Bem, eu cansei da vida de sofredor. Na lista de opções, eu utilizo frameworks, depois patterns, depois faço no braço.
Já que vai ficar com Command, você podia aproveitar o gancho e fazer um tutorialzinho sobre ele, usando o ObexFTP como exemplo!
Abraços!
2 de agosto de 2007 às 6:58 pm
Não estou certo disso. O que sei é que eu poderia fazer o controle do ciclo de vida, obtenção dos Actions e binding com frameworks como o Swing Application Framework e Beans Binding, por exemplo. Mas também eu não estou renegando ao mundo, até pq essa arquitetura que montei eu não montei tudo do zero; tudo é feito com classes já fornecidas pelo Java, como
BlockingQueue, Threads/SwingWorker(de fato, elas fazem o grosso do trabalho). De qualquer forma, mesmo que resolvesse utilizar algum(ns) framework(s), não tenho conhecimento de um framework desktop que, por exemplo, torne desnecessária a utilização do pattern Command, dadas as circunstâncias.Também acho! Foi justamente por isso que imitei a semântica dos Listeners Swing onde precisei de observers, com classes nomeadas
xxxListenerexxxEvent, e métodosadd/removeXxxListener. Não digo em todos, mas em quase todos os locais onde apelei para Subject/Observers foram por pura necessidade. Dois exemplos: na parte de configuração, existem objetos precisam ser notificados caso as configurações mudem. O outro exemplo é a parte de notificação do ciclo de vida de um Command: quando um Command é adicionado/removido da fila e executado (com falha ou com sucesso), existem objetos “ouvindo” esses eventos e que dependem deles para fazer determinadas coisas (mostrar/ocultar animação de “loading” é uma delas).Enfim, também acho que objetos desse tipo devem ser evitados ao máximo pois dificultam a localização de possíveis erros. Mas, para compensar isso, os eventos gerados e consumidos geram entradas no log.
Também pensei nisso, pois muita gente ainda acha que Commands se resume a objetos com um método
execute()(eu mesmo pensava desse jeito). É um assunto importante e difícil de se abordar… talvez futuramente eu escreva algo sobre isso.Valeu.