Chuton: fazendo meu próprio joguinho de palavras em Vanilla Javascript

Se tem uma coisa que ainda me fascina na programação de computadores, desde quando a conheci em tenra idade, é a possibilidade de construir coisas do zero apenas com um computador pessoal e as coisas que ele já lhe oferece. Escolha uma linguagem de programação, aprenda-a e veja suas idéias tomarem vida. Simples assim. O mesmo não é possível para quem constrói carros, prédios ou foguetes, pois isso tudo exige materiais, espaço, logística, orçamentos, por mais simples que seja o protótipo. Eles que lutem.

E se tem uma linguagem de programação que já há algum tempo está ao alcance de qualquer pessoa que tenha um computador, é o Javascript puro, ou Vanilla Javascript, utilizando o navegador de internet para executar o código criado. Não precisa instalar nenhuma SDK ou ferramental para fazer funcionar, não precisa usar nenhuma grande IDE se não quiser, também não é obrigado a usar gerenciador de pacotes e nem recorrer a bibliotecas de terceiros. Tem tudo ali, acredite! Com o passar dos anos, a quantidade de APIs padronizadas pela W3C e suportadas pelos navegadores modernos se tornou enorme, de modo que com Javascript puro você consegue persistir dados, sintetizar som, renderizar cenas 2D e 3D, acessar GPS do dispositivo ou até mesmo saber quantidade de bateria nele disponível, dentre outras dúzias de coisas interessantes que atiçam a criatividade. Apesar de todo aparelhamento moderno que a linguagem recebeu com o advento do Node.js e a era das Single Page Applications (SPA), é importante lembrar que ainda é possível simplesmente criar um bom e velho script e incluí-lo manualmente num HTML para fazer maravilhas. E assim eu faço, vez ou outra, para programar pequenos projetos pessoais cuja a janela do navegador é suficiente como camada de apresentação (com a vantagem de também funcionar no celular de forma responsiva com um mínimo de esforço no CSS).

Pois bem. No início de 2022 rolou a febre dos jogos de palavras baseados no Wordle, onde você tem 6 chances para descobrir uma palavra de 5 letras, recebendo dicas visuais sobre as letras certas e erradas presentes no seus chutes. Alguns joguinhos desse tipo brotaram também para Português, sendo o mais famoso deles o Term.ooo, seguido de outros como Palavra do Dia, Charada, Letreco, Palavrês. Num determinado fim de semana de fevereiro desse mesmo ano, me deu na telha fazer mais uma dessas incursões no Javascript para programar um joguinho desses, por puro passatempo, sem utilizar nenhuma biblioteca de terceiros, programando tudo “do zero”.  Então investi uma ou duas horas para ter uma versão inicial apresentável, depois joguei o jogo sozinho diariamente por cerca de 10 dias e fui melhorando a interface visual com pinceladas diárias após o expediente. Quando achei que estava redondo o suficiente, batizei o joguinho de Chuton (uma forma jocosa de falar chutão), e divulguei o link para amigos, recebendo alguns feedbacks especialmente sobre problemas de responsividade em algumas telas de dispositivos móveis específicos.

Chuton
Chuton: minha versão do famoso joguinho de adivinhar palavras de 5 letras.

Geralmente, nesse tipo de projetinho passatempo, começo fazendo como rascunho o Javascript mais rápido que resolve o problema, usando como output o próprio log do console. Depois vou enfiando elementos visuais para melhorar a UX. Num primeiro momento o código fica enorme, pouco modularizado e fortemente acoplado ao HTML. Daí vou tentando refatorar, transformando o projeto num grande playground de decisões de code design para que tudo chegue em seu devido lugar. Particularmente, acho bem prazeroso refatorar código “mal feito” que faço às pressas na direção de um código mais organizado. É quase um jogo de puzzle infinito onde sempre que você passa o olho vê oportunidade de melhorar algo, tentando deixar mais compreensível e coeso cada elemento ou aspecto da solução. E assim foi com o Chuton.

O código do Chuton está disponível no meu GitHub. Para quem quiser passar o olho, toda a lógica conceitual do jogo está isolada no arquivo chuton-core.js, que possui apenas 100 linhas. A “camada de persistência” no cache local está isolada no arquivo chuton-data.js. A cola de tudo com a renderização visual do jogo e com a captura dos eventos de UI está no arquivo chuton.js. Além do código em Vanilla Javascript, fiz também um script Python bem rudimentar para fazer web scraping de palavras de 5 letras de alguns sites com listas de palavras que também está versionado por lá (incluindo as listas de palavras extraídas). Pode entrar lá, fique à vontade, é pobre mas é limpinho!

Para minha surpresa, pouco depois dessa aventura descobri que Wordle originalmente era um programa escrito na linguagem Basic e que foi publicado na revista Creative Computing na década de 80 (fonte). E para minha surpresa, o código e funcionamento do jogo original se mostrou muito próximo do que fiz no módulo core do meu código. Veja a página abaixo:

Wordle
Código em Basic do jogo Wordle publicado numa revista de informática nos anos 80

Sim, é isso mesmo, no começo da era dos computadores pessoais você comprava revistas onde estava impresso os códigos para você digitar no seu computador e construir tais programas (análogo ao que faziam as revistas de Eletrônica com projetos de circuitos). Esse fato cutucou em cheio minha nostalgia pois comecei a programar justamente com o Quick Basic, um editor/compilador de Basic que já vinha instalado no MS-DOS para que as pessoas pudessem criar seus próprios programas em seus computadores, exatamente como havia enaltecido no começo desse texto. Tomei conhecimento da ferramenta pois entrava lá para mandar executar o joguinho gorilla.bas , até que um dia meu pai me disse que aquilo era um código-fonte e que era possível aprender a escrever aquilo tudo e fazer meus próprios programas. Desde então, lá se vão mais de 20 anos programando. Viva a programação o empoderamento que ela nos proporciona!

10 Anos na Mesma Empresa, Processos de Desenvolvimento de Software, Rituais, Astrologia e Pandemia.

[Alerta: texto caótico]

No meio da pandemia fiz aniversário de uma década trabalhando na empresa onde estou. Uma anomalia para os dias de hoje no mercado de TI? Talvez. Mas duas coisas certamente tornaram a experiência suportável. Uma delas foi a oportunidade de, mesmo estando na mesma empresa, ter trabalhado em diversos projetos diferentes ao longo de todo esse tempo, o que sem dúvidas foi um antídoto para a mesmice. A outra foi a construção de grandes amizades com uma vasta gama de pessoas incríveis com as quais pude ter conversas excelentes.

Uma coisa que pude observar ao longo dos anos nessa empresa foi que o processo de desenvolvimento de software foi sempre alvo de constantes mudanças e revoluções. A empresa chegou a ser certificada CMMI naquela época em que o mercado e o governo exigia esse selo para fechar grandes contratos. Logo, é de se imaginar que o processo de desenvolvimento era engessado e cheio de exigências. Mas a cada ano algo novo prometia ser a grande solução para alguma atividade, fosse a forma de escrever os requisitos, a prototipação, o teste, o versionamento do código, a documentação técnica. Com o passar do tempo entraram em cena elementos das metodologias ágeis, Scrum, Kanban, Design Thinking e outros. Se muitas foram as promessas de revoluções e tendências absorvidas, maior ainda foi a quantidade de ferramentas e aplicativos utilizados para implantá-las.

Eu sempre achei que, acima de qualquer processo de desenvolvimento, método ou ferramenta, um fator muito mais crítico para que as coisas funcionem é a vontade do time de fazer as coisas bem feitas, com capricho e responsabilidade. Pouco importa se estão sendo utilizados post-its coloridos, planilhas no Excel ou cronogramas no MS Project. Quem constrói o software são as pessoas, e não os meios que elas utilizam. Provavelmente ainda vão surgir muitas outras formas de desenvolver software, e todas elas irão colecionar uma gama de cases de sucesso que, para os mais ingênuos e exaltados, parecerá confirmar que essa é a melhor saída. Mas isso é uma percepção enviesada, sem a menor dúvida.

Dito isso, e tendo observado uma miríade de práticas adotadas e descartadas ao longo do tempo, penso que um processo de desenvolvimento, seja ele qual for, em qualquer tempo ou lugar, precisa minimamente promover rituais úteis e significativos que ajudem a canalizar o foco e a força de trabalho em torno de aspectos chave do que precisa ser construído ou mantido. Rituais. A reunião diária do Scrum, por exemplo, é um ritual que promove comunicação entre o time, o acompanhamento constante do cronograma e a identificação e solução rápida de impedimentos que poderiam culminar na concretização de certos riscos. Mas isso também pode ser feito de inúmeras outras formas criativas. Certamente vai agradar e funcionar melhor para uns que para outros. Mas usar algum ritual para cuidar de algum aspecto relevante num projeto vai sempre ser melhor que não usar nada e apenas confiar nas cabeças atarefadas e caóticas das pessoas e apostar na comunicação eficiente entre elas.

Isso me faz lembrar de algo inusitado. Certa vez, numa conversa incrível com um desses amigos que fiz na empresa, ele expôs um ponto de vista interessante sobre os signos do zodíaco e a astrologia. Para ele, mesmo que você não leve a sério o tema, conversar sobre o signo de alguém é um excelente ritual para se conectar com aquele indivíduo e mostrar-se atencioso e interessado. Não está em jogo aqui se astrologia é uma ciência e toda aquela discussão. Funcionando ou não, usar um papo sobre signos como ritual para obter conexão e promover empatia é, sem dúvidas, uma grande sacada.

Rituais têm esse poder. Se nos entregamos sem resistência, mesmo não dando crédito para seus meios, ele conduz a nossa mente, direciona o nosso foco e energia, promove o gatilho de determinados processos, raciocínios, sensações e sentimentos, sela compromissos, une pessoas, vira páginas, encerra capítulos. Eles podem ser potentes. Certas construções, desconstruções e viradas de chave me parecem muito difíceis de ocorrer sem um ritual marcante. Abrir mão deles pode ser uma grande prepotência, e isso ficou ainda mais evidente para mim durante a pandemia.

No isolamento, trabalhando em casa, levou algum tempo até eu conseguir ajustar os rituais que sinalizavam para minha mente uma separação simbólica entre trabalho e vida pessoal. Também precisei criar algumas estratégias para que os sábados e domingos tivessem sabor de fim de semana e não só mais dois  dias no mesmo cenário. Sei de pessoas que terminaram a faculdade mas cuja breve cerimônia online não preencheu a lacuna deixada pela falta da formatura presencial. Sei ainda de pessoas jovens que passaram no vestibular e tiveram que estudar dois ou mais períodos iniciais da faculdade de forma completamente remota, sem aquele sabor único de passar a frequentar um campus universitário, sendo calouro.

Falando nisso, sabe o amigo que falou sobre a utilidade do papo sobre signos como ritual de conexão? Faleceu no início da pandemia. O velório foi restrito a poucos familiares, dadas as circunstâncias. E com isso não foi possível para mim viver o ritual da despedida como de costume. Até hoje me falta algum evento que ajude a fazer essa ficha cair. Para agravar, o trabalho remoto na pandemia me fez perder contato visual com muitos colegas, logo ficou difícil assimilar que mais um dos “sumidos” na verdade se foi para sempre. Então, mais do que nunca, digo com propriedade: rituais são úteis e muitas vezes necessários.

Criando um Ajax Loading no Angular usando Http e Observables

Quando fazemos uma requisição HTTP assíncrona em JavaScript (Ajax) é interessante dar um feedback visual, uma vez que que o navegador não dá nenhum. Aliado a isso, pode ser interessante também bloquear a tela para uso enquanto a requisição não retorna, evitando que o usuário clique em alguma coisa indesejada nesse período.

Nesse post vou demonstrar como fazer um Ajax Loading (aquela janelinha que geralmente diz “Carregando…“, “Loading…“, ou exibe um GIF girando) no Angular 2+. A solução apresentada evita que os pedidos de mostrar/esconder o Loading fiquem espalhados por diversos pontos do código, atuando diretamente na camada de chamada ao serviço Http, sem poluir o código de cada tela/componente. É possível que já exista alguma biblioteca ou componente pronto para isso, mas achei muito interessante registrar a solução pura pois ela aborda decisões de design de classes que podem inspirar a resolução de outros problemas parecidos.

Em linhas gerais, a idéia é simples:

  • Criar uma classe wrapper em torno da classe Http do Angular.
  • Criar um LoadingService cujo estado controla quando o Loading deve ser exibido ou escondido.
  • Criar um recurso visual no template raiz da aplicação que só é exibido quando o LoadingService indica positivo.

Existem outras abordagens possíveis para resolver essa situação, e elas serão discutidas no final do artigo.

Primeiramente vamos construir nosso LoadingService:

import { Injectable } from '@angular/core'

@Injectable()
export class LoadingService {

    private loading: number = 0;

    showLoading() {
        this.loading++;        
    }

    hideLoading(){
        this.loading--;
        if(this.loading < 0){
            this.loading = 0;
        }
    }

    isLoading(){
        return this.loading > 0;
    }
}

No código acima, basicamente, sempre que alguém chama showLoading(), incrementa-se 1 unidade numa propriedade numérica privada. Quando alguém chama hideLoading(), subtraímos 1 unidade. Essa estratégia foi feita pois podem ocorrer diversas requisições HTTP assíncronas, logo, o Loading deve ser exibido enquanto todas elas não terminarem, ou seja, quando esse número volta a ser zero. O método isLoading() permite observar se está ou não acontecendo alguma chamada.

Agora vamos trabalhar na nossa classe wrapper do Http. Um wrapper, como o nome já indica, é um Padrão de Projeto onde uma classe embrulha um objeto, permitindo adicionar tratamentos a esse objeto. O Angular já fornece através do módulo @angular/http uma classe para o programador fazer requisições HTTP do tipo GET/POST/PUT/DELETE, geralmente utilizado para fazer chamadas à API REST que dá suporte à aplicação. Essas chamadas na verdade retornam Observables, que são objetos que permitem ao chamador do método programar o que vai acontecer quando a chamada assíncrona termina. Vamos criar um wrapper chamado HttpService que embrulha o Http do Angular. Veja como fica o código:

import {Injectable} from '@angular/core';
import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/do';

import { LoadingService } from './loading.service';

@Injectable()
export class HttpService {

    constructor( private loadingService: LoadingService, private http: Http ) { }

    get(url: string): Observable<Response> {
        return this.watch(this.http.get(url));
    }  
    
    //fazer também para o post, put, delete ...

    private watch(response: Observable<Response>): Observable<Response> {

        this.loadingService.showLoading();

        return response.do(
            next => {
                this.loadingService.hideLoading();
            }, 
            error => {   
                //faça aqui seu tratamento de erro
                this.loadingService.hideLoading();
            }            
        );
    }
}

Observe no código acima que o tanto o Http quanto o LoadingService estão sendo injetados no HttpService. A classe deve oferecer métodos para GET/POST/PUT/DELETE, e esses métodos por sua vez delegam a chamada para os respectivos métodos do serviço Http do Angular. No entanto, perceba que quando vamos chamar o método get() do Http por exemplo, na verdade apenas passamos como parâmetro sua chamada para a função watch que irá adicionar um tratamento: antes de executar a chamada pedimos ao LoadingService para exibir o Loading; depois que a chamada é executada, seja com sucesso ou erro, perdimos para esconder o Loading. Esse tipo de chamada pode parecer estranho para quem não está habituado com a parte funcional do JavaScript, já que na verdade não estamos executando método algum, mas apenas anexando coisas à uma chamada que só será feita no futuro, quando de fato alguma código quiser fazer uma chamada a uma URL.

Agora falta preparar o tempalte raíz da aplicação para ter algum elemento visual que será exibido sempre que o LoadingService indicar que tem requisições. Para isso, basta incluirmos alguns controles no componente raiz da aplicação Angular. Veja o código abaixo:

import { LoadingService } from './loading.service';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <div id="loading" [class.hidden]="!loading">Loading...</div>
    <div>
      <h1>Angular Loading Test</h1>

      <child-component></child-component>

      <footer>by Rafael Odon (rafaelodon.com)</footer>
    </div>
  `,
  styles: [`
    .hidden{
      display: none;
    }

    #loading {      
      position: fixed;                  
      top: 0px;
      left: 0px;
      width: 100%;
      height: 100%;                           
      color: red;
      background-color: black;
      opacity: 0.5;
      font-size: 5em;      
      text-align: center;            
    }    
  `]
})
export class AppComponent {

  constructor( private loadingService: LoadingService ){}

  get loading(){
    return this.loadingService.isLoading();
  }
}

Observe primeiro o código da classe do componente e ignore o código do template HTML. A classe AppComponent injeta o LoadingService. Definimos a propriede chamada loading, que na verdade não é um atributo interno, mas apenas a definiçaõ de um get. Esse get na prática delega a obtenção dessa informação para o método isLoading() do nosso LoadingService. Com isso, tornamos possível que no nosso template HTML seja possível observar o estado do LoadingService.

No template HTML do componente raiz, basicamente você precisa criar um elemento visual que só é exibido se a propriedade loading do componente for verdadeira. Isso pode ser feito de várias formas. Eu fiz uma DIV que ganha a classe .hidden sempre que a propriedade loading é falsa. No CSS, defini que a classe .hidden esconde o elemento. Ademais, personalizei essa DIV no CSS para que ela ocupe toda a tela, com uma opacidade de 50%, bloqueando o usuário de clicar em outras coisas.

Com essa estrutura montada, qualquer código que que acione o HttpService, direta ou indiretamente, por consequência fará com que o Loading apareça. Veja o código abaixo um componente filho que foi criado para exemplo:

import { HttpService } from './http.service';
import { LoadingService } from './loading.service';
import { Component } from '@angular/core';

@Component({
  selector: 'child-component',
  template: `
    <button (click)="onClick()">Perform a slow request...</button>
    <p>{{message}}</p>
  `  
})
export class ChildComponent {
  
  message:String = "";

  constructor( private httpService: HttpService ){}

  onClick(){
    this.message = "";
    this.httpService.get("http://www.fakeresponse.com/api/?sleep=1").subscribe(
      next => this.message = "Done!"
    );
  }
}

Por fim, vamos ver como fica a configuração do módulo de aplicação:

import { HttpModule } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { HttpService } from './http.service';
import { LoadingService } from './loading.service';

import { AppComponent } from './app.component';
import { ChildComponent } from './child.component';

@NgModule({
  declarations: [
    AppComponent,
    ChildComponent    
  ],
  imports: [
    BrowserModule,
    HttpModule
  ],
  providers: [    
    HttpService,
    LoadingService
  ],
  bootstrap: [AppComponent]
})
export class AppModule {

}

Perceba que estamos importando o módulo HttpModule, já que, no fundo no fundo, as chamadas HTTP da aplicação passam por esse recurso nativo do Angular. Mas estamos provendo para toda a aplicação o HttpService. A idéia então é, quando for necessário fazer uma chamada assíncrona HTTP que exiba o Loading, utilize o HttpService ao invés do Http nativo do Angular.

Alguns podem questionar se não seria possível herdar o Http ao invés de injetá-lo dentro de um wrapper. É uma questão de escolha. Mas ao usar herança será preciso configurar no Angular a sua sub-classe criada como uma alternativa a ser provida no lugar da outra. Uma outra alternativa que tem sido muito apresentada para resolver problemas parecidos é o uso de Interceptors HTTP, mas no entanto isso faz com o que o tratamento dado na interceptação da requisição HTTP sempre aconteça, exigindo algumas manobras para torná-lo condicional. Ao resolver o Loading via wrapper, além de simples, fica mais fácil para o programador decidir quando usar ou não os tratamentos criados.

Um detalhe importante dessa solução é que o Angular provê a mesma instância do LoadingService para toda a aplicação. Como declaramos o LoadingService no módulo da aplicação, ele funcionará como um singleton, conforme é explicado na própria documentação. Isso garante que o estado desse serviço (o número interno que incrementa e decrementa) seja compartilhado e acessado de qualquer ponto da aplicação.

O código completo pode ser visto em: https://github.com/rafaelodon/angular-loading

Teste unitário com múltiplas threads no JUnit

Em um projeto que participo, há um conjunto de EJBs stateless reponsáveis por atender chamadas. Foi preciso disponibilizar para todas as camadas um contexto de mensagens cujo escopo é uma chamada ao serviço. Como não seria possível usufruir de um bean com escopo de Request, que exigiria trabalhar com beans stateful, simulei esse contexto através de ThreadLocal. Conforme a teoria, esse recurso “provides thread-local variables (…) each thread has its own, independently initialized copy of the variable.

Por ser um ponto crítico do sistema, desejei criar um teste automatizado para garantir o comportamento ao longo das mudanças. Em linhas gerais, o teste deveria criar várias threads utilizando seus contextos de mensagens e certificar que eles não se sobrepusessem. Durante a prospecção soube que o framework TesteNG fornece a opção de testes com múltiplas threads, mas julguei que seria um teste muito simples para precisar de uma biblioteca adicional.

Dessa forma, meu teste com JUnit da seguinte forma:

import org.junit.Assert;
import org.junit.Test;

public class ContextoTest {

    private static final int QTD_THREADS = 1000;

    @Test
    public void contextoDeveSerExclusivoDaThread() throws InterruptedException {

        Thread[] threads = new Thread[QTD_THREADS];
    
        // Cria e roda as threads
        for (int i = 0; i < QTD_THREADS; i++) {
            threads[i] = new ThreadTeste();
            threads[i].start();
        }

        // Aguarda a execução de todas das threads
        for (Thread t : threads) {
            t.join();
        }
    }

    class ThreadTeste extends Thread {

        @Override
        public void run() {
            Contexto.inicializar();

            // Dorme por um tempo aleatório para forçar paralelismo
            esperarUmTempoAleatorio();

            // Adiciona o nome da thread corrente no contexto
            Contexto.adicionarMensagem(Thread.currentThread().getName());

            // Contexto deve ter apenas 1 mensagem, contendo nome da thread
            Assert.assertEquals(1, Contexto.getMensagens().size());
            Assert.assertEquals(Thread.currentThread().getName(), Contexto.getMensagens().get(0));
        }

        private void esperarUmTempoAleatorio() {
            try {
        	Thread.sleep((long) (1000 * Math.random()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Um ponto interessante é introduzir algum grau de desordem no paralelismo, oque foi feito fazendo a thread dormir por um tempo aleatório antes de realizar o teste. Além disso, é primordial fazer join() das threads criadas ao fim do teste unitário para certificar que o JUnit não prosseguirá para outros testes enquanto ainda existem threads rodando do teste atual.

Configurando um projeto mínimo com Drools 6 no Maven

Em um projeto que participo surgiu a necessidade de utilizar um motor de regras de negócio para fornecer ao cliente a possibilidade de gerenciar as regras de um processo por conta própria. Como o sistema é em Java, o Drools, mais especificamente o sub-produto Drools Expert, se mostrou uma opção interessante, principalmente pela possibilidade de criar uma Linguagem Específica de Domínio (DSL).

Ao estudar a ferramenta na Web, percebi uma vasta gama de tutoriais, cada um com sua forma de criação e configuração do projeto, muitas vezes ainda apegado a versões inferiores a 6 da ferramenta.

Apresento aqui uma forma bem enxuta, usando o Eclipse como IDE e o Maven como gerenciador de dependências e builds:

1. No Eclipse, criar um projeto Maven, pulando a seleção de arquétipo.

2. No pom.xml do projeto, colocar como dependências o drools-compiler, bem como uma biblioteca de log compatível com SLF4J (sugiro a Logback), conforme o trecho abaixo:

	<dependencies>
		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-compiler</artifactId>
			<version>6.3.0.Final</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.1.5</version>
		</dependency>
	</dependencies>

3. Sugiro ainda que no pom.xml você determine como configuração de build a versão do Java desejada, aqui no caso a 1.7. Para isso faça conforme o trecho abaixo:

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

2. Acionar botão direito no projeto, Maven > Update Project para que o Eclipse perceba as novas configurações

3. Criar o arquivo src/main/resources/META-INF/kmodule.xml com o conteúdo:

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule" />

4. Criar o arquivo src/main/resources/regras.drl com o conteúdo:

rule "olá"
	when
		$texto : String()
	then
		System.out.println("Olá "+$texto);		
end

5. Criar uma classe executável para testar. Ex:

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class Main {
	
	public static void main(String[] args) {
		
		KieServices ks = KieServices.Factory.get();
		KieContainer kcontainer = ks.getKieClasspathContainer();				
		KieSession ksession = kcontainer.newKieSession();
		
		String texto="Rafael";		
		ksession.insert(texto);
		
		ksession.fireAllRules();				
	}
}

6. Se desejar utilizar o plugin do Drools no Eclipse, que facilita algumas tarefas mas não é essencial, instale os artefatos desejados do update site:
http://download.jboss.org/drools/release/6.3.0.Final/org.drools.updatesite/

No meu github coloquei um exemplo completo de Drools usando tanto DRL (linguagem de regra do Drools) e DSL (linguagem específica de domínio) para aplicar regras de negócio num exemplo de carrinho de compras com descontos no preço e no frete: https://github.com/rafaelodon/poc-drools

O Ciclo de Sabotagem das Tecnologias de Desenvolvimento de Software

Esses dias eu estava super cliché, meio crítico com o fato de surgir tanta tecnologia nova o tempo todo. Praticamente a cada 4 anos a gente precisa se renovar para não ter o aspecto técnico do currículo anulado nos 4 anos seguintes. Tudo bem que muitas dessas novidades advém de um movimento natural promovido pelas grandes inovações (desenvolvimento mobile por exemplo). Mas é comum assistir tecnologias morrendo e dando lugar a outras que produzem o mesmo resultado, sem justificativas convincentes.

Por um instante cheguei a formular a hipótese que na verdade isso era um fenômeno de procrastinação coletiva promovido pelo [in]consciente coletivo dos profissionais de TI, que acham super recompensador gastar seu tempo tendo que reaprender como fazer o mesmo de forma diferente. Talvez tenha um pouco disso também. Mas pensando melhor, percebo também um padrão de sabotagem  que é descrito no ciclo abaixo:

#1 –  The dawn of man: Surge uma Nova Tecnologia ®, ainda incipiente , mas que promete suprir uma deficiência do ferramental vigente.

#2 – O buzz: A Nova Tecnologia ® atrai a atenção de acadêmicos e entusiastas que se aproveitam do pioneirismo para surfar na crista da onda, publicando em revistas, palestrando em eventos, etc. Mas tudo se resume ao buzz. O mercado corporativo ainda olha com desconfiança.

#3 – Mordendo a maçã: Versões novas são lançadas, boas práticas são disseminadas, cursos, artigos, tutoriais, tópicos em fóruns, perguntas e respostas saturam a web. Convencidos pelos gurus, vai surgindo na manada de profissionais espectadores o desejo de adotar a Nova Tecnologia ®, tanto pelo prazer de aprender algo novo quanto pela necessidade de manter seus currículos atualizados.

#4 – As invasões bárbaras: Com o mercado de trabalho recheado de defensores da Nova Tecnologia ®, corporações de impacto passam a adotá-la em projetos relevantes que apresentam desafios reais, em escala real. E esses projetos introduzem um outro fator crucial: a pressão por prazo. Prazo leva à pressa que leva ao aumento de recursos. Nesse clima, uma manada de profissionais sub-qualificados e por vezes sub-remunerados, forçam pro-ativamente o uso indiscriminado da Nova Tecnologia ®. Tudo é resolvido da forma mais imediata o possível, com muita gambiarra, sem avaliar alternativas, sem conhecer recursos avançados, buscando resultados rápidos que salvem o projeto (e também seus empregos). Julgando-se produtivos e confortáveis com a Nova Tecnologia ®, está formado um batalhão de martelos que acha que tudo é prego.

#5 – Sodoma e Gomorra: Com o colapso de grandes projetos que adotaram a Nova Tecnologia ®, começam a sair cases de insucesso, artigos que condenam seu uso e o famoso anúncio: “a Nova Tecnologia ® morreu“. Por mais que os gurus afirmem que são os profissionais que usaram de forma errada, e que as novas versões incluam recursos que suprem as deficiências e introduzem melhorias, a tecnologia continua estigmatizada por suas restrições conceituais e efeitos colaterais do uso costumeiro.

#6 – Let’s twist again: Volte ao Passo #1.

Arquiteto ou apenas bom desenvolvedor?

Sempre fui crítico com o rótulo arquiteto de software. Se a gente parar pra pensar, é um nome um tanto quanto mal escolhido. Na engenharia civil, o arquiteto é o desenhista do prédio, o artista do concreto. Oscar Niemeyer rabiscava formas modernistas no papel e pouco se importava em como aquilo viraria realidade, o que de fato seria um problema para os engenheiros.

Esboço de Oscar Niemeyer
Esboço de Oscar Niemeyer

Já na área de software, quem costuma imaginar coisas difíceis de por em prática é o cliente, o demandante. Para executar suas idéias mirabolantes há de se contar com super-heróis capazes de eleger plataformas, tecnologias, protocolos, padrões, componentes, topologias e de projetar como isso tudo vai conversar. O curioso é que o nome que se dá para esse super-herói é justamente arquiteto de software.

Eu particularmente acredito que essas atribuições sejam apenas a descrição de um bom desenvolvedor, ou para ser mais justo ao argumento, um bom engenheiro de software. O curioso é que quase não se vê o termo engenheiro de software circulando em vagas de emprego no mercado brasileiro. Acredito que isso se dê por alguns fatores.

O primeiro deles advém da própria distinção que os desenvolvedores gostam de ter em relação às demais engenharias. Há todo um brio envolvido no domínio da arte de desenvolvedor sistemas, principalmente quando você fica anos estudando muito além da programação. Talvez não queiramos ser confundidos com engenheiros civis ou mecânicos. Enquanto isso, na mão contrária do nosso ego, o mercado de trabalho acha ótimo que nos consideremos apenas desenvolvedores, uma vez que engenheiros tem conselho, piso salarial e algum respeito perante a sociedade. Engenheiros constroem prédios. Nós “mexemos” com informática.

Mas então, se formamos uma manada de desenvolvedores egocêntricos, quem são os famosos arquitetos de software? Pessoalmente ainda acho que um arquiteto é nada mais nada menos que um bom engenheiro de software, com experiência, senso crítico e visão micro e macro sobre a pilha de tecnologias envolvidas num sistema. O que percebo é que os que se dizem arquitetos buscam nesse rótulo uma distinção, não querem ser confundidos com meros programadores, uma atividade mais básica. Da mesma forma, os desenvolvedores também não querem se responsabilizar por decisões que irão assombrar o projeto pelo resto dos dias, podendo trazer impactos diretos na performance e disponibilidade do sistema. E é nesse contexto que a arquitetura de software vai se tornando ocultista e mística, fazendo com que os programadores se distanciem do que deveria ser o grande objetivo: se tornar um excelente profissional.

Abandonando os rótulos, o fato é que todo sistema desenvolvido terá uma arquitetura, quer você queira ou não. Cabe a você deixar de ser um simples fabricador de telas e querer absorver e contribuir com as decisões técnicas dos projetos em que você colabora. Busque formar o tal senso crítico, viver experiências, conhecer e experimentar as tecnologias de forma contínua. Não perca de vista o norte da excelência, independente do nome que eles inventam para ela.

O Ócio Nocivo nas Redes Sociais

Aqui vou eu fazer um post criticando os posts da Internet. Mas creio ser uma contradição razoável.

Talvez você, assim como eu, esteja sentindo mais desprazer do que prazer ao usar as redes sociais. Mas antes de abonimá-las, lembremo-nos de que o mal quase sempre está no homem, nunca nas coisas. O pai da aviação, Santos Dumont, suicidou-se aos 59 anos, angustiado por ver seu invento usado em guerra. E nós? Que uso estamos dando para esse ambiente moderno de fácil comunicação que é a Internet? Sob essa luz lanço um desafio: vamos trocar esse novo vício de ficar contemplando por horas a timeline e os perfís das pessoas no Facebook por outra atividade, de preferência fora da Internet? O prêmio é ser feliz.

Vá ler livro ou uma revista, pode até ser de fofoca, ou mesmo um quadrinho antigo da Turma da Mônica. Aprenda um instrumento musical, ou pratique uma nova música. Aprofunde-se em outro idioma. Veja um filme ou uma série. Tire um cochilo no sofá. Arrume uma gaveta. Separe roupas que você não usa para um bazar beneficente. Imprima as fotos daquela viagem, faça um álbum e convide alguém pra ver. Visite um parente. Cuide de uma planta. Adote um animal. Faça uma caminhada até à padaria e espere a próxima fornada quentinha do pão. Cozinhe uma receita nova. Lave a louça, se estiver afim. Debruce na varanda ou sente-se no banco da praça e veja o vai-e-vem das pessoas. Monte um quebra-cabeça. Faça um artesanato. Faça uma planilha com as finanças. Organize na prateleira os livros que você nunca vai ler por ordem alfabética de autor. Depois reorganize-os por ordem de tamanho, ou cor. Olhe pro teto ou pro chão por horas, imaginando o que fazer caso ganhasse na mega-sena, mesmo que você nunca jogue. Enfim. Só não se perca novamente lá nas redes sociais, colhendo infelicidades gratuitas o tempo todo.

Tá certo que toda tecnologia sofre críticas quando surge, e já sobrevivemos a muitas delas: televisão, telefone, computador pessoal, video-game, celular e a própria Web. Mas algo me sugere que o ócio já foi muito menos nocivo para a nossa psique antes de toda essa hipnose nas redes sociais. Talvez não estejamos preparados para tamanha facilidade de interação social que essas plataformas nos proporcionam. Pensar, discutir e argumentar é saudável. Mas decididamente não precisamos conhecer a opinião de todos sobre tudo o tempo todo, assim como não precisamos formar e emitir opinião sobre tudo o tempo todo. Essa pressão está nos implodindo!

Evitar log de LoginException quando usuário errra senha

Passamos a conviver com um número excessivo de exceções de login do JAAS no Jboss EAP 6.0.1 quando algum usuário errava a senha. Essas exceções não indicam erros do sistema propriamente ditos, e estavam enchendo o log e tornando difícil a análise de outros problemas de produção.

Login failure: javax.security.auth.login.LoginException: Login Failure: all modules ignored
	at javax.security.auth.login.LoginContext.invoke(LoginContext.java:921) [rt.jar:1.6.0_45]
	at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186) [rt.jar:1.6.0_45]
	at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683) [rt.jar:1.6.0_45]
	at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.6.0_45]
	at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680) [rt.jar:1.6.0_45]
	at javax.security.auth.login.LoginContext.login(LoginContext.java:579) [rt.jar:1.6.0_45]
	...

A opção foi abaixar o nível de log do pacote org.jboss.security para FATAL para todo o Jboss. Isso pode ser feito no standalone.xml seguinte na seção de logging:

<subsystem xmlns="urn:jboss:domain:logging:1.1">
    ...
    <logger category="org.jboss.security">
        <level name="FATAL"/>
    </logger>
    ...
</subsystem>