Pessoal, o motivo deste post é apenas a minha percepção da realidade, então, caso discordem, façam o favor de deixar registrado aqui!! :). Durante os últimos anos tenho me esforçado para ir ao máximo de eventos e treinamentos que posso, visando sempre melhorar meu nível profissional e conhecer novas pessoas, melhorando o networking.
Infelizmente, os grandes eventos ainda são concentrados no eixo sul-sudeste, mas não acho que seja um motivo para ter tão poucos de nós presentes neles. Por exemplo, ano passado no Rails Summit, o maior evento de Ruby que já aconteceu aqui no Brasil, só encontrei 5 baianos, enquanto que só do Amapá, eu encontrei os mesmos 5. Nada contra o Amapá, a galera que tava lá sacava bastante, mas nosso estado é muito maior, provavelmente com muito mais profissionais, e teoricamente deveria ter uma maior presença.
Esse post serve realmente como um convite, vamos nos organizar e “descer de galera” para os eventos. Apenas alguns para vocês pensarem: Falando em Java, Just Java, FISL 10, entre varios outros que devem ter por aí. Até a próxima!!!!
Continuando o último tópico, sobre melhorar na carreira, investi mais um pouco nos projetos open source. Eu e Vinicius criamos o projeto JavaAdvancedQueryFilter, cujo objetivo é facilitar a criação de queries dinâmicas. A idéia é que, de forma simples e única, possam ser criadas queries dinâmicas sem a necessidade daqueles ifs chatos que verificam se determinado critério é para ser utilizado ou não. Com o filtro criado, ele pode ser “parseado” para qualquer provider como: JDBC/SQL, Hibernate/Criteria, Hibernate/HQL, JPAQL e por aí vai.
Agora vamos ver um exemplo de como seria determinada query fazendo do jeito padrão e usando o QueryFilter.
private void testCreateSimpleFilterWithUserNameAndEmailAttributesOnlyIfTheyArentNullUsingTheCommonWay(
User user) {
Criteria criteria = sessionSharedBetweenAllMethods
.createCriteria(User.class);
if (user.getName() != null) {
criteria.add(Restrictions.eq("name", user.getName()));
}
if (user.getEmail() != null) {
criteria.add(Restrictions.eq("email", user.getEmail()));
}
System.out.println(criteria.list());
}
private void testCreateSimpleFilterWithUserNameAndEmailAttributesOnlyIfTheyArentNullUsingTheFilter(
User user) {
Criteria criteria = sessionSharedBetweenAllMethods
.createCriteria(User.class);
Filter filter = new Filter();
filter.add(new Condition("name", user.getName(), Operation.EQUALS,new NotAcceptNullValueClosure())).add(new Condition("email", user.getEmail(), Operation.EQUALS,new NotAcceptNullValueClosure()));
System.out.println(filter.apply(criteria).list());
}
Agora um exemplo mais bem elaborado, onde deve-se buscar por todos usuarios que tenham residências em determinados endereços.
private void testFindUserThatLiveInSomeOfThatAddressUsingTheCommonWay(
Address[] addresses) {
Criteria criteria = sessionSharedBetweenAllMethods.createCriteria(User.class);
if(addresses.length>0){//have to test if the array is not empty, if it is, you can not pass for "in" expression
Collection<String> descriptions = new ArrayList<String>();
for (Address address : addresses) {
descriptions.add(address.getDescription());
}
criteria.createAlias("addresses", "address").add(
Restrictions.in("address.description", descriptions));
}
System.out.println(criteria.list());
// TODO Auto-generated method stub
}
private void testFindUserThatLiveInSomeOfThatAddressUsingTheFilterWay(
Address[] addresses) {
Criteria criteria = sessionSharedBetweenAllMethods.createCriteria(User.class);
Filter filter = new Filter().addAlias("addresses", "address").add(new Condition("address.description", CollectionHelper.extractTheObjectsBasedInGetterAttributeOrOtherMethod("description",addresses), Operation.IN,new NotAcceptEmptyCollectionOrArrayClosure()));
System.out.println(filter.apply(criteria));
// TODO Auto-generated method stub
}
O projeto está hospedado no sourceforge e como foi útil para mim espero que seja para vocês também.
Em algum momento do ano passado eu li o post “Be Your Start-up” do Jay Fields. Ele fala sobre coisas que você deve fazer para melhorar na sua carreira, e aborda três tópicos: Writing,Presenting,Contributing. Vou falar sobre um pouco de cada coisa que fiz e como isso me fez melhorar profissionalmente.
Para abordar o primeiro, criei o blog aqui da Settech, no começo achei que ia ser tranquilo escrever pelo menos um post toda semana, com conteúdo realmente de qualidade para as pessoas. No primeiro mês foi até fácil, no segundo começou a ficar mais dificil e depois daí só piorou, esse é o primeiro depois de um bom tempo. Para resolver isso, tenho que estudar mais do que fiz no ano passado. Consequentemente vou me aprimorar e ainda treino minha escrita!, coisa que realmente não é meu ponto forte. Já estou na politica de adquirir no minímo um livro por mês, tomara que consiga ler na mesma intensidade.
Em relação a fazer apresentações, ele fala de um ponto importante, você só pode apresentar caso tenha alguém que queira lhe ouvir!. Para resolver isso, temos que fazer coisas interessantes, que nos façam ser um pouco diferente, para que os outros queiram nos ouvir. Ele fala de por exemplo criar um projeto open source que faça algum sucesso ou escrever coisas realmente interessantes para que possamos atrair público. No meu caso, fiz os dois primeiros, mas nada ainda que faça alguém querer me ouvir :), então para complementar, me esforço em participar de treinamentos e eventos de qualidade onde quer que eles aconteçam, por enquanto só estou no Brasil, apesar de estar com planos de algum internacional esse ano. Isso me faz criar uma boa rede de relacionamentos e conversar com pessoas que são expoentes da nossa comunidade de desenvolvimento de software, sempre aprimorando minhas idéias e fazendo com que alguns queiram me ouvir falar. Bom, realmente ainda preciso melhorar nesse quesito :).
O último realmente é o melhor. Você escolhe um projeto que tem a ver com suas necessidades, ou não, começa a usar e de repente já pode contribuir. No meu caso está acontecendo com o Caelum Stella, ele tem varias funcionalidades relativas a softwares desenvolvidos com foco no Brasil, como validações de diversos documentos, geração de boletos e integração de algumas dessas coisas com frameworks como Hibernate,JSF, etc… Resolvi participar do projeto, já contribuí com algumas coisas e o melhor é interagir com pessoas com outros conhecimentos e que estão dispostas a compartilhar isso com você, muito válido! Além de aumentar sua rede de relacionamentos, com um bom networking você pode ultrapassar muitas barreiras.
Bom pessoal, foi mal pelo post meio grande, mas também depois de tanto tempo… Quem já tomou essas medidas continue melhorando, e quem não tomou, como sugestão, pelo menos tente, vai melhorar bastante como profissional.
Ontem eu estava no blog do John Resig vendo o que ele anda fazendo com Javascript e tinha um post de uma brincadeira que ele fez com a parte de datas. Por exemplo, você chama
prettyDate("2008-12-03T20:24:17Z")
e a resposta é “Yesterday”. Eu acho isso muito legal no sentido que fica mais próximo da linguagem real do usuário.
Pois bem, nos comentários do post foi indicado o Datejs, uma api que usa uma DSL para facilitar a construção de datas em Javascript. Aqui vai um exemplo retirado do próprio site.
// What date is next thrusday?
Date.today().next().thursday();
// Add 3 days to Today
Date.today().add(3).days();
// Is today Friday?
Date.today().is().friday();
// Number fun
(3).days().ago();
// 6 months from now
var n = 6;
n.months().fromNow();
// Set to 8:30 AM on the 15th day of the month
Date.today().set({ day: 15, hour: 8, minute: 30 });
// Convert text into Date
Date.parse(‘today’);
Date.parse(‘t + 5 d’); // today + 5 days
Date.parse(‘next thursday’);
Date.parse(‘February 20th 1973′);
Date.parse(‘Thu, 1 July 2004 22:30:00′);
Um site que utiliza bastante este recurso é o Remember the milk e, particularmente, eu acho bem interessante. Outra coisa legal é a parte de testes que eles fizeram
Date.Specification = new Specification({
'Overview': {
setup: function() { this.baseline = new Date('7/8/2004') },
'July 8th, 2004 : Typical': {
run: function() { this.date = Date.parse('July 8th, 2004') },
assert: function() { return this.baseline.equals( this.date ) }
},
'jul-08-04 : Abbreviated': {
run: function() { this.date = Date.parse('jul-8-04') },
assert: function() { return this.baseline.equals( this.date ) }
},
'07/08/04 : Numeric': {
run: function() { this.date = Date.parse('07/08/04') },
assert: function() { return this.baseline.equals( this.date ) }
}
)
Não sei a opinião de vocês, mas eu não gosto muito do tratamento de datas em Javascript e essa biblioteca fornece uma boa ajuda. Espero que gostem e façam bom proveito impressionando seus usuários
Remember the Milk é um site para você organizar sua lista de “to do”. Antes de escrever fui dar uma pesquisa no alexa.com e ví que apenas 0.4% dos usuários são do Brasil. Na minha opinião deveria ser maior :). Vou escrever algumas das funcionalidades oferecidas nele aqui.
A principal utilidade do site é a criação de coisas a fazer. Nessa parte já aparece umas coisas legais como: tempo para terminar a tarefa, localidade da tarefa(especificada no google maps para posterior consulta de tarefas por localização),tags da tarefa para criar relacionamentos entre as mesmas, url amigável entre outras coisas. Depois que sua lista está criada, tem a opção de compartilhar a mesma com outros pessoas cadastradas no site, criando assim sua rede de contatos que estão interessadas em suas tarefas. Outro item muito bom que ele tem são os avisos. É possível configurar a ferramenta para lembrar você sobre suas tarefas, informando antecendência e para onde os alertas devem ser enviados. Por exemplo, celular(tim ou claro),email,skype,msn,gtalk entre outros. Por fim, aí ja fazendo um upgrade na sua conta, $25 por ano, é possível fazer sincronização com IPhone,BlackBerry,Windows Mobile e IpodTouch.
Finalizando, acho que esta ferramenta pode ser usada no minímo para duas situações: pessoas desorganizadas ou até numa empresa para promover uma maior comunicação entre os colaboradores, fato que está acontecendo aqui na Settech :). Bom, espero que gostem da ferramenta, tá sendo bem útil para mim. Só um último lembrete, para quem gostar muito, ele já tem acesso via webservices para integração com outros projetos.
Quando estava no workshop sobre DDD na Caelum, o Phillip falou que na Thoughtworks eles usavam o Mockito para criar os mocks dos objetos. Só uma esclarecida rápida, objetos mock são aqueles criados para simularem algum comportamento. O cenário preferido é aquele onde um objeto depende de outro para funcionar. Você tem um ServiceQQ onde o mesmo depende de um objeto que use algum webservice, como naquele momento você não tem isso implementado, então é criado um mock e passado para seu Service.
Baseado nisso, montei um exemplo para calcular as multas referentes a um carro. Existe o objeto do tipo Detran(orgão responsável pelo trânsito na Bahia) que usa um serviço para saber as multas de determinado carro e, caso existam multas, o valor total é associado ao mesmo. Como eu queria só testar a associação do valor total, não queria usar a implementação verdadeira da interface VerificadorDeMultas, então criei um mock. Abaixo segue o código.
package br.com.settech.exemplo;
import java.math.BigDecimal;
import java.util.Collection;
public class Detran {
private VerificadorDeMultas verificadorDeMultas;
public Detran(VerificadorDeMultas verificadorDeMultas){
this.verificadorDeMultas = verificadorDeMultas;
}
public Carro verificaMultasDoCarro(Carro carro){
Collection<Multa> multas = this.verificadorDeMultas.verificaMultas(carro);
if(multas.size()>0){
BigDecimal valorMultas = BigDecimal.ZERO;
for(Multa multa : multas){
valorMultas = valorMultas.add(multa.getValor());
}
carro.setValorDasMultas(valorMultas);
}
return carro;
}
}
package br.com.settech.exemplo;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class TestVerificadorMultas {
@Test
public void testVerificacaoDeMultas(){
Carro carro = new Carro("jpg-4060","Celta");
VerificadorDeMultas verificadorDeMultas = Mockito.mock(VerificadorDeMultas.class);
List<Multa> multas = new ArrayList<Multa>();
multas.add(new Multa(new BigDecimal(50),"Passou no vermelho"));
multas.add(new Multa(new BigDecimal(100),"Sem cinto"));
//adicionando comportamento
/*
* Quando chamarem o metodo verificaMultas, então é retornado minha colecao.
*/
Mockito.when(verificadorDeMultas.verificaMultas(carro)).thenReturn(multas);
Detran detran = new Detran(verificadorDeMultas);
Assert.assertEquals(new BigDecimal(150),detran.verificaMultasDoCarro(carro).getValorDasMultas());
}
@Test
public void testCarroSemMulta(){
Carro carro = new Carro("jpg-4060","Celta");
VerificadorDeMultas verificadorDeMultas = Mockito.mock(VerificadorDeMultas.class);
Detran detran = new Detran(verificadorDeMultas);
Assert.assertEquals(BigDecimal.ZERO,detran.verificaMultasDoCarro(carro).getValorDasMultas());
}
}
Em um projeto aqui na empresa, estava precisando acessar o webservice do SugarCRM. O problema aconteceu quando descobri que o estilo de binding dele era rpc/encoded e que os projetos em Java mais atuais não estavam dando suporte a isso, alguns exemplos são : Axis2 e CXF.
Então foi que pensei, deixa eu ver se tem jeito de fazer isso em Ruby, e descobri que era até meio ridiculo…
require('md5')
require 'soap/wsdlDriver'
@wsdl = "http://localhost/settech_orcamentos/soap.php?wsdl"
@soap = SOAP::WSDLDriverFactory.new(@wsdl).create_rpc_driver
resultado = @soap.login({:user_name=>"login",:password=>MD5.new("password"),:version=>"5.1.0a"},"SugarCRM")
puts resultado.id
Isso porque o Ruby faz o parse do wsdl em tempo de execução e cria uma classe para você naquele momento, na verdade um proxy, e permite que todos os metodos sejam acessados. Ainda conta a ferramenta wsdl2ruby para fazer algo similar ao wsdl2java.
Com isso em mãos, resolvi fazer o mix de Java com Ruby, usando o Java como linguagem, mas também como plataforma para execução de código, nesse caso o Ruby através da sua implementação em Java, JRuby. Isso oferece um potencial incrível pois, por exemplo, podemos usar o potencial do Ruby para fazer algo que Java não seja muito bom ou até querer manter um código em Java que seja dinâmico, sim é permitido acessar as API’s do Java através do Ruby. Abaixo segue o código que fiz. A primeira parte em Ruby e a segunda em Java. As variaveis no código Ruby que estão com $, foram compartilhadas do código em Java para o Ruby
require('java')
include_class('br.com.settech.sugarsoap.Result')
include_class('br.com.settech.sugarsoap.helper.ContextSoapComunication')
require 'soap/wsdlDriver'
require 'MD5'
module IntegracaoSugarCRM
class SugarCRM
def initialize(name_value_pairs)
@name_value_pairs = name_value_pairs
@params = Array.new
end
def params
@name_value_pairs.each {|name_value_pair| @params.push({:name=>name_value_pair.name,:value=>name_value_pair.value})}
@params
end
end
class Integrador
def initialize
if not $context
@soap = SOAP::WSDLDriverFactory.new($info.url_wsdl).create_rpc_driver
end
end
def login
result = @soap.login({:user_name=>$info.login,:password=>MD5.new($info.password),:version=>$info.version},$info.app_name)
ContextSoapComunication.new(Result.new(result.error.number,result.error.description,result.id),@soap)
end
def logout
#logout aqui
end
#Usa as variaveis definidas no codigo java.
def executa_metodo
params = SugarCRM.new($name_value_pairs).params
result = $context.driver.set_entry($context.login_id,$which_module,params)
Result.new(result.error.number,result.error.description,result.id)
end
end
end
if not $context
IntegracaoSugarCRM::Integrador.new.login
else
IntegracaoSugarCRM::Integrador.new.executa_metodo
end
public class JRubyIntegrationTest {
private ContextSoapComunication contextSoapComunication;
private BSFHelper helper;
@Before
public void testCreateLogin() throws BSFException,IOException{
helper = new BSFHelper();
SugarInfo sugarInfo = new SugarInfo("login","password","SugarCRM","5.1.0a","http://localhost/settech_orcamentos/soap.php?wsdl");
helper.declareBean("info",sugarInfo);
this.contextSoapComunication = (ContextSoapComunication)helper.evalFile("C:\\ambiente\\ruby_project\\IntegracaoSugarCRM\\lib\\integrador.rb");
this.contextSoapComunication.loginId();
}
@Test
public void testExecuteJRubyCode() throws BSFException,IOException{
NameValuePairCreator lista = new NameValuePairCreator();
this.helper.declareBean("which_module",ModuleTypes.OPPORTUNITIES);
this.helper.declareBean("name_value_pairs",lista.addNameValuePair("lead_source","Self Generated").addNameValuePair("name","Projeto integracao2").addNameValuePair("amount","53500.55").nameValuePairList());
this.helper.declareBean("context",this.contextSoapComunication);
Result result = (Result)helper.evalFile("C:\\ambiente\\ruby_project\\IntegracaoSugarCRM\\lib\\integrador.rb");
System.out.println(result.createdId());
helper.finalize();
}
}
Para acessar o script através do Java, uso o projeto BSF(Bean Scripting Framework), ideal para quem, como eu, está no Java 5 ainda. A classe BSFHelper foi extraída do site ociweb.com. A única ressalva que faço, é que para usar um script que faça uso do require ou algo parecido, devemos forncer ao BSF a localização das bibliotecas. Para fazer isso, coloque o seguinte código:
System.getProperties().put("jruby.lib",jrubyBase+"\\lib");
System.getProperties().put("jruby.home",jrubyBase);
Bom, por hoje é isso, desculpem o tamanho do post, mas queria mostrar algo que foi realmente útil para mim e acho que pode ser para vocês também.
Na terça (28/10/08) fiz uma ponte áerea Salvador/São Paulo para o workshop sobre DDD (Domain Driven Design) realizado na Caelum com o Phillip Calçado.
O workshop foi bem interessante. Usamos um sistema para alocação de vagas em estacionamentos como exemplo. Foram utilizados alguns cartões estilo
CRC para fazer a modelagem. A cada User Story fomos refatorando nossos cartões para adequá-los, com a preocupação sempre de manter o modelo o mais próximo possível do domínio do cliente.
Uma fato durante esse processo foi bem legal. Após uma hora de modelagem, tendo passado por 3 ou 4 histórias, cada equipe foi apresentar seu modelo e, como já era de se esperar, todas colocaram a classe Carro. Duas equipes colocaram o carro com placa, modelo e cor enquanto que a terceira optou apenas pela placa e ainda ironizou: “Não sabíamos que o modelo e a cor eram importantes para se achar o carro…” O pior é que isso acontece o tempo todo. Ao invés de ficarmos focados em atender o problema, imaginamos o que pode acontecer e criamos código realmente desnecessário, como os atributos, cor e modelo (pelo menos no atual momento). Neste caso foi simples, mas que já impacta na persistência, formulário web e, nas horas de trabalho como um todo, horas extras que o CLIENTE NÃO PAGOU!!!
No final do treinamento eu estava bem cansado, mas valeu muito a pena. Falei com o Philip que ele deveria realizar outro workshop, mostrando como fazer o cliente realmente participar do processo de criação do software, porque é nesse ponto que eu vejo muita dificuldade. Quase nunca o cliente quer participar da modelagem do seu sistema, e, em DDD, praticamente quem faz isso é ele!
Estudando Ruby, nós do Java ou .NET, vemos umas coisas que nos parecem meio estranhas. Por exemplo, todo metodo retorna algo, mas para que eu quero que meu metodo setter retorne alguma coisa?. Bem, inicialmente pode não fazer sentido, mas se parar e der uma olhada, verá que não faz diferença nenhuma para seu código se seu metodo pessoa.setNome(”Alberto”) retornar uma referencia para ele mesmo(this).
Você usa o retorno se quiser, querendo pode fazer algo besta, mas na minha opinião muito mais legivel,
pessoa.setNome("Alberto").setSobreNome("Souza").qqCoisaAqui(...);
É isso que venho colocando na minha cabeça, aprender uma linguagem nova é muito legal, mesmo que não coloquem em produção, não custa nada dar uma olhada, ver uma forma diferente de fazer algo.
Participar de um evento como o Rails Summit(http://www.locaweb.com.br/railssummit) realmente abre sua cabeça. Estar em contato com pessoas de todo o Brasil, inclusive alguns de fora do país, faz vc ver o que estão fazendo por aí e lhe empolga a tentar fazer coisas + legais.
Os caras mais importantes da comunidade Ruby do mundo estiveram por lá, como o Chad Fowler e Obie Fernandez entre outros, por sinal este ultimo fechou o evento com uma palestra sensacional falando sobre a empresa dele, que chama HashRocket, realmente muito bom trabalhar num ambiente daqueles. Vendo tudo aquilo, só me fez ter certeza que o Ruby chegou para ficar, por enquanto com o Rails… que é o framework do momento como já tivemos varios em Java(Struts,JSF,Struts2…), mas vamos começar a ver muita coisa muito mais legal sendo feita com essa linguagem.
Eu já estou me aprontando, meio(muito) atrasado, mas o importante é começar, fazer alguns projetos, criar um senso critico e depois resolvo. O melhor de tudo é que aprendendo uma linguagem nova, vc aprende a pensar de um jeito diferente e de alguma forma isso irá transformá-lo num melhor profissional.
