Translate

terça-feira, 1 de abril de 2014

Mutex - Exclusão mútua em Java para controle transacional absoluto

Mutex é uma abreviação de exclusão mútua em inglês (mutual exclusion). Seu propósito é evitar que duas ou mais threads acessem simultaneamente o mesmo recurso compartilhado.

Para exemplificar um problema de falta de Mutex, imagine um sistema central multi thread responsável por apoiar o processamento de pedidos de um portal de compras. Neste cenário, o usuário pode clicar duas vezes e submeter duas vezes a requisição por uma questão de impaciência, ainda a rede de comunicação pode conter falha que redunde a requisição ou a aplicação servidora pode conter algum bug capaz de emitir mais de uma vez a requisição para o sistema de processamento final.

Se você for um programador desatento pode não acreditar na possibilidade de uma requisição redundante ocasionar impacto financeiro ao usuário e até mesmo a instituição responsável pelo portal sem contar o transtorno para administrar o problema.

Para todo efeito, o problema existe e somente um controle transacional delegado a um banco de dados não resolve porque uma nova transação em banco de dados só sabe da existência de uma anterior se esta (anterior) sofrer uma confirmação ou commit. O controle transacional via banco de dados só surtirá efeito se as requisições redundantes fossem em sequencia, mas a realidade de requisições redundantes é em grande parte paralela.

A esta altura a exclusão mútua deve fazer maior sentido caso você não a tenha compreendido.

O Mutex normalmente é aplicado no serviço central (aplicação) para impedir justamente impactos gerados por falhas em algum sistema intermediário (ex.: web-container) ou sistema terminal (ex.: browser ou usuário).

Construíndo uma controladora Mutex

A fim de tornar a Mutex mais eficiente, vamos fazer o uso da coleção com limpeza automática por tempo de espera chamada WTConcurrentLinkedQueue publicada no artigo Java - Limpeza automática de coleções. Essa classe possui dependência da classe WTTimeObject também publicada no mesmo artigo.

Agora vamos ao exemplo de uma classe para controle Mutex.

import java.io.IOException;

public class MutexControl {

    private static Integer LOCKTIMEOUT_SECS = 120;

    private static String CARDPREFIX = "_CARD";
    private static String TRANSACTIONPREFIX = "_TRANSACTION";

    private static MutexControl mutexControl;

    static {
        mutexControl = null;
    }
   
    private static synchronized MutexControl getInstance() {
        if (mutexControl == null) {
            mutexControl = new MutexControl();
        }
        return mutexControl;
    }

    private WTConcurrentHashMap<String, Long> list;

    private MutexControl() {
        list = new WTConcurrentHashMap<String, Long>("MutexControl");
    }

    public WTConcurrentHashMap<String, Long> getList() {
        return list;
    }

    private static synchronized void lock(String id, Integer expirationSecs) throws IOException {

        Long obj = getInstance().getList().get(id);

        if (obj != null) {
            if (obj < System.currentTimeMillis()) {
                getInstance().getList().remove(id);
            } else {
                throw new IOException(String.format("A chave de operação (%s) simultânea está em uso.", id));
            }
        }

        Long timeout = System.currentTimeMillis() + (expirationSecs * 1000L);
        getInstance().getList().put(id, timeout);

    }
   
    private static synchronized void unlock(String id) {
        getInstance().getList().remove(id);
    }

    public static void cardLock(Long cardLogicalNumber) throws IOException {
       
        String key = String.format("%s%d", CARDPREFIX, cardLogicalNumber);
       
        lock(key, LOCKTIMEOUT_SECS);

    }

    public static void cardUnlock(Long cardLogicalNumber) throws IOException {

        String key = String.format("%s%d", CARDPREFIX, cardLogicalNumber);

        unlock(key);

    }

    public static void transactionLock(Long transactionId) throws IOException {
       
        String key = String.format("%s%d", TRANSACTIONPREFIX, transactionId);
       
        lock(key, LOCKTIMEOUT_SECS);

    }

    public static void transactionUnlock(Long transactionId) throws IOException {

        String key = String.format("%s%d", TRANSACTIONPREFIX, transactionId);

        unlock(key);

    }
   
    public static void main(String[] args) {

        /****************************************************
         * Testar bloqueio/desbloqueio de um fictício cartão por seu id
         ****************************************************/
        Long cardId = 123L;
       
        // Teste 1: Bloqueia cartão - Resultado esperado: Deve pemitir
        try {
            cardLock(cardId);
        } catch (IOException e) {
            System.err.println("Teste 1: " + e.getMessage());
        }

        // Teste 2: Bloqueia cartão - Resultado esperado: Não deve pemitir
        try {
            cardLock(cardId);
        } catch (IOException e) {
            System.err.println("Teste 2: " + e.getMessage());
        }

        // Teste 3: Desbloqueia cartão - Resultado esperado: Deve pemitir
        // Se não desbloquear até 120 segundos, desbloqueia automaticamente
        // Leia a constante LOCKTIMEOUT_SECS
        try {
            cardUnlock(cardId);
        } catch (IOException e) {
            System.err.println("Teste 3: " + e.getMessage());
        }
       
        // Teste 4: Bloqueia cartão - Resultado esperado: Deve pemitir
        try {
            cardLock(cardId);
        } catch (IOException e) {
            System.err.println("Teste 4: " + e.getMessage());
        }

        /****************************************************
         * Testar bloqueio/desbloqueio de uma fictícia transação por seu id
         ****************************************************/
        Long transactionId = 1002L;
       
        // Teste 5: Bloqueia transação - Resultado esperado: Deve pemitir
        try {
            transactionLock(transactionId);
        } catch (IOException e) {
            System.err.println("Teste 5: " + e.getMessage());
        }

        // Teste 6: Bloqueia transação - Resultado esperado: Não deve pemitir
        try {
            transactionLock(transactionId);
        } catch (IOException e) {
            System.err.println("Teste 6: " + e.getMessage());
        }

        // Teste 7: Desbloqueia transação - Resultado esperado: Deve pemitir
        // Se não desbloquear até 120 segundos, desbloqueia automaticamente
        // Leia a constante LOCKTIMEOUT_SECS
        try {
            transactionUnlock(transactionId);
        } catch (IOException e) {
            System.err.println("Teste 7: " + e.getMessage());
        }
       
        // Teste 8: Bloqueia transação - Resultado esperado: Deve pemitir
        try {
            transactionLock(transactionId);
        } catch (IOException e) {
            System.err.println("Teste 8: " + e.getMessage());
        }
       
    }

}


A classe MutexControl contém como principais funções lock e unlock para bloquear um recurso pelo seu identificador. Para facilitar o entendimento, na classe ainda foram adicionadas funções de bloqueio e desbloqueio mais concretas, são os casos das funções cardLock, cardUnlock, transactionLock e transactionUnlock. Basicamente você pode criar funções de bloqueio e desbloqueio de outros recursos diretos ao utilizar a mesma técnica de criar as funções baseadas num prefixo para o identificador para não conflitar com controles de outros recursos.

Para evitar incidentes sérios caso você se esqueça de desbloquear um recurso após a operação ou mesmo que seu controle de exceção deixe o recurso bloqueado por erro, foi determinado um limite de tempo de bloqueio em 120 segundos na constante LOCKTIMEOUT_SECS da classe MutexControl. O parâmetro pode ser alterado a seu critério de tolerância para desbloquear um recurso esquecido no Mutex.

Teste da controladora Mutex

O teste está na mesma classe controladora no método main. Execute a classe em modo de debug preferencialmente e acompanhe os exemplos de controle de operação de um cartão de id 123 e em seguida, de uma transação de id 1002.

Resultado

Na tentativas de bloqueios redundantes, devem ocorrer as seguintes exceções:

Teste 2: A chave de operação (_CARD123) simultânea está em uso.
Teste 6: A chave de operação (_TRANSACTION1002) simultânea está em uso.


Conclusão

Análogo a um controle de semáforo onde se passa apenas um carro por vez numa via, o Mutex é uma técnica simples e segura para a exclusão mútua de processamento redundante provocado por falhas de requisições redundantes;

Até o próximo artigo.

quarta-feira, 18 de dezembro de 2013

Banco de dados - Big Data - Análise concreta

Tenho pesquisado nos vários artigos da Internet e com profissionais do campo da TI o que vem a ser o Big Data.

O Big Data segundo análise não é uma ferramenta concreta e nem mesmo uma metodologia concreta, mas é um conceito de processamento de dados de mercados públicos.

Para entender melhor, é preciso fazer um retrospecto das evoluções no campo de banco de dados:

1) Arquivo

Este fenômeno trouxe ao processamento de dados o primeiro poder de armazenamento em pequena escala para agregar a sigla EPS (Entrada->Processamento->Saída). Em outras palavras com o desenvolvimento dos processadores, também foram desenvolvidos meios de armazenamento cada vez mais seguros, velozes e maiores.

2) Banco de dados simples

Após a descoberta de tecnologias físicas para persistir os dados processados, o campo da lógica desenvolveu o catálogo de arquivos para possibilitar a um processo organizar todos seus contextos em arquivos distintos. Vide o sucesso do DBASE nas plataformas de menor porte e do VSAM em plataformas altas com grande capacidade de processamento.

3) Banco de dados relacional

Após transformar arquivos em catálogos, ainda o campo da lógica percebera a necessidade de poupar espaços ao denominar valores repetidos de grandes tamanhos em tabelas (arquivos físicos). Para isso, criou adereço de relacionamento menor para representar o valor muito grande (em bytes) e muito repetido. O adereço é a chave utilizada para relacionar o grande valor não mais repetido ao seu registro original quando este fosse requisitado.

Aqui ocorreram grandes transformações no campo do banco de dados, pois para maior velocidade na recomposição do registro original, tabelas de registros precisavam ser ligadas com tabelas redutoras de volumes de dados, conhecidas hoje como tabelas de cadastros ou de domínios, mas de maneira veloz e não se podia para cada registro armazenado em fragmentos buscar sua composição varrendo completamente as tabelas de domínio.

Para resolver o problema, inventaram e evoluíram bastante as técnicas de índices. Os índices começaram com um clone da tabela a ser varrida, porém organizada pela chave de busca (o adereço de relacionamento) e estas tabelas eram denominadas de arquivos lógicos (logical file) e a tabela de registros era chamada de arquivo físico (physical file). Cada índice gerava um arquivo lógico não explícito normalmente por ser unicamente de interesse do gerenciamento do banco de dados. Porém, no início a atualização destes arquivos físicos perdia a integridade com facilidade e rotinas de reindexação eram entregues juntas com o banco de dados para serem executadas manualmente. Algo bastante recorrente.

Para resumir, as buscas mesmo com os índices eram morosas de serem programadas e por isso foi inventada a linguagem SQL para elevar a manipulação unitária de registros para a manipulação em escala.

Este fenômeno teve um impacto real na capacidade de produção de softwares no mundo inteiro. Aqui é importante destacar, a comunidade do Big Data busca algum feito equivalente, mas ao invés de atender uma escala corporativa, pretende impactar a forma de processamento de dados em uma escala maior ainda a utilizar a Internet como meio condutor.

4) Sistema Gerenciador de Banco de Dados (SGBDs)

Logo após o banco de dados relacional SQL e ainda com a contribuição dos gurus da época, as empresas de softwares passaram a desenvolver, sob a tutela do órgão regulamentador ANSI, bancos de dados profissionais capazes de armazenamentos e recuperação totalmente sofisticados a ressaltar o SYBASE, o seu herdeiro SQL Server comprado e renomeado pela Microsoft, o DB2 da IBM, o Oracle Database Enterprise da Oracle, o Ingress da CA, Informix hoje da IBM, o MySQL hoje da Oracle, o PostGresql ainda comunitário e outros de menor evidência no mercado, mas de grande importância para alguns ramos peculiares do processamento de dados como o geoprocessamento e o sócio-processamento demandados por setores normalmente governamentais ou militares.

Os SGBDs ainda são predominantes no mercado por causa da maturidade, garantias, desempenho, integridade, fácil desenvolvimento e manutenção alcançados em paralelo com a evolução das máquinas, meios de armazenamento e superação de muitos paradigmas computacionais a ressaltar o último, a própria Internet.

5) Banco de dados multi dimensional

No início deste milênio, muito se propagou a respeito deste tipo de banco de dados, porém ele emprestava como escravo os convencionais SGBDs e cuidava apenas de transformar dados operacionais em dados gerenciais a partir da ordem multi dimensional. Todos os SGBDs passaram a permitir a configuração em modo operacional (OLTP) em modo analítico (OLAP) porque a distinção entre estes modos determina consideravelmente a lógica de processamento de dados e armazenamento a ser realizada pelo SGBD.

O conceito do banco de dados multi dimensional foi pautado em reprocessar o banco de dados Entidade-Relacionamento (entenda por SGBD ao pé da letra) para a organização de Fatos, Dimensões e Tempo. Os Fatos na terminologia multi dimensional é uma ocorrência relevante financeiramente e histórica, ou seja, o fato é o registro transacional. As Dimensões são conhecidas como as entidades substantivas e por isso equivalem as tabelas de cadastro ou domínio do SGBD. Já o tempo foi externado como um entidade cronológica e escalonada em unidades de acordo com a necessidade do cliente final.

Em suma, o Fato é a tabela operacional ponderada ao patamar de granularidade (detalhada ao extremo , resumida ao extremo ou graduada entre estes dois últimos) desejada pelo analista e atribuída das chaves de ligação as Dimensões e Tempos encontradas em uma espécie de Fato.

A partir desse bastidor, ferramentas permitem ao usuário analista montar suas análises operacionais, táticas e estratégicas com arrastar de soltar de fatos, dimensões e tempo. Algo semelhante a geração de uma cross table em Excel, se você já fez isso alguma vez vai entender melhor este último passo.

O banco de dados organizado para fim gerencial (OLAP) é chamado de Data Warehouse. Simplesmente um nome simples para armazém de dados para o contexto analítico e não operacional.

6) Banco de dados orientado à objetos

Esta empreita foi um grande fiasco, pois muitos entusiastas e desconhecedores da história dos SGBDs pensaram em banir com o modelo Entidade-Relacionamento e no lugar de entidades pensavam em gravar o Objeto conceituado da Orientação à Objetos.

A ideia não era nada mal em primeira avaliação, porém isso acabaria com a capacidade de economia de recursos de armazenamento, desempenho e a flexibilidade da rastreabilidade relacional, atributos estes totalmente maduros nos SGBDs.

Este banco de dados orientado à objetos não vingou no mercado e se ainda existe, é em porção pífia.

7) Big Data

O futuro normalmente recorre ao passado, isso é uma verdade a ser considerada.

O Big Data ainda não tem nenhum consórcio e nem órgão normatizador determinados para desenvolvê-lo sem os vícios tendenciosos de empresas gigantes como a IBM ou Oracle somente por ilustração.

Mas sua ideia é clara quando se fala na maneira de armazenamento, algo parecido com o banco de dados multi dimensional ou grandes catálogos de arquivos sem normalização da Entidade-Relacionamento justamente para imprimir grande desempenho ao processamento. É daqui a primeira frase "O futuro normalmente recorre ao passado".

Se as informações são guardadas sem fatoração ou denominações de adereços para redução de espaço, sua recomposição torna-se muito mais veloz e esta é a proposta essencial do Big Data. Basta relembrar da flex table muito representada pelo VSAM e outros arquivos indispensáveis para o processamento em larga escala encontrado em programas sobre processadores RISC.

Note, o Big Data é o campo da lógica correlacionado com a evolução dos processadores, estes hoje atendem com maturidade a computação distribuída e a computação paralela. Ainda vale destacar um feito importante do campo dos processadores, o uso da preempção para priorizar racionalmente as demandas computacionais e de uma maneira federativa e organizada imprimir grande capacidade de processamento com menor custo. Se você tem um tablet ou um smartphone mais recentes, certamente esta evolução dos processadores está em suas mãos e você provavelmente não sabe.

No entanto, o Big Data sabe onde pretende chegar, porém ainda deve tratar de três obstáculos:
  • onde armazenar tantos dados? 
  • como acessar estes dados reaproveitando todas as técnicas de busca desenvolvidas em outras gerações bancos de dados?
  • como coordenar os computadores em unidades computacionais para obtenção de informações do Big Data tendo como meio condutor a Internet?
O armazenamento certamente será dividido por profissionais do ramo de grandes empreendimentos para adquirirem Data Centers inicialmente mais aplicados em Big Datas para compilar dados de alguns mercados e; ainda por estudantes e cientistas porque estes já estão em busca de novos paradigmas de armazenamento redundante cujo objetivo é a confiabilidade na integridade da informação. Talvez nada seja capaz de levar o Big Data a este patamar nos próximos anos porque os meios de armazenamento ainda são escassos e caros para todos, por isso uma solução híbrida que recompõe uma parcela dos dados perdida a partir de rotinas mais inteligentes de manutenção cuide desta escassez tida como obstáculo. Menciono indiretamente um armazenamento distribuído, porém em meios seguros e autorizados sem tentar roubar espaços dos bilhões de usuários leigos na Internet com a instalação forçada de aplicações escravizadoras de seus computadores pessoais. Esta ideia é por si insegura e ilegal.

O acesso as informações depende é claro de índices não vetoriais como a maior parte dos índices usados em SGBDs hoje. Aqui caberá como desafio a junção de índices com relacionamentos, ligações menores, mas registradas em metadados para responder em tempo hábil consultas sobre o Big Data.

Por último obstáculo, a coordenação das unidades computacionais é um desafio cuja computação nas nuvens já tem respostas porque esta se pauta em sistemas operacionais não exclusivo de uma máquina, é uma expansão gritante dos tímidos investimentos em clusters de processamento e das bem-sucedidas evoluções das máquinas virtuais. É opção de um Big Data utilizar do benefício da computação nas nuvens ou tentar uma solução melhor, apesar de aparentemente não existir. Se a computação é nas nuvens, há um receio do mercado de uma chuva de dados incontrolável, mas este receio já está sendo mitigado por cientistas e empresários da área porque a computação nas nuvens é um futuro esperado por muitos anos quando se falava ainda em ter apenas um terminal simples para processar os dados armazenados na Internet.

Empresas podem até dizer que superaram todos os desafios, mas ainda é cedo e os obstáculos ainda não foram transpostos ou contornados em fórum mundialmente organizado como foi o caso dos SGBDs com a ANSI.

Espero ter contribuído e se você tiver informações para agregar, entra em contato.

Boa sorte.

terça-feira, 17 de dezembro de 2013

Java - Sincronizar referência entre threads

Quando se trata de operar um objeto entre threads, seja escrita e leitura posterior, existe a ocorrência de três situações distintas: processamento paralelo, geração de referências do objeto de origem e a atualização tardia da alteração do objeto porque a JVM não garante imediates nesta questão.

Estas três situações mencionadas, quando combinadas, terminam normalmente num problema de sincronismo que pode interferir em muito a integridade do processamento concorrente (não paralelo apenas) de objetos e deixar qualquer programador ou projetista do campo em questão com bastante dor de cabeça costumeiramente.

O problema

A bateria de classes a seguir compõem uma simulação de um problema de atraso no sincronismo prejudicial para a operação concorrente de objetos. O valor operado é outData do tipo ValueObject, pois a operação final copiar os parâmetros de inData, também do tipo ValueObject, para outdata:

A classe ValueObject é o objeto da operação

public class ValueObject {

private long id;
private String name;

public ValueObject() {
this.id = 0L;
this.name = null;
}

public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override

public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("ValueObject [id=");
builder.append(id);
builder.append(", name=");
builder.append(name);
builder.append("]");
return builder.toString();
}

}

A classe AbstractExecutor implementa Runnable para apoiar a concorrência

public abstract class AbstractExecutor implements Runnable {

private ValueObject inData;
private ValueObject outData;

abstract void execute(ValueObject inData, ValueObject outData);

@Override
public void run() {

this.execute(inData, outData);

this.setOutData(outData);

}

public ValueObject getInData() {
return inData;
}

public void setInData(ValueObject inData) {
this.inData = inData;
}

public ValueObject getOutData() {
return outData;
}

public void setOutData(ValueObject outData) {
this.outData = outData;
}

}

A classe FinalExecutor herda AbstractExecutor para realizar a operação concorrente

public class FinalExecutor extends AbstractExecutor {

@Override
protected void execute(ValueObject inData, ValueObject outData) {

outData.setId(inData.getId());
outData.setName(inData.getName());

}

}

A classe ThreadPoolExecution gera a execução paralela com falha no sincronismo 

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ThreadPoolExecution <E extends AbstractExecutor> {
private static int executions;
static {
executions = 0;
}

private Class<E> clazz;
private ExecutorService threadPool;
public ThreadPoolExecution(Class<E> clazz) {
this.clazz = clazz;
this.threadPool = Executors.newFixedThreadPool(2);
}

public void execute(ValueObject inData, ValueObject  outData) {
try {
E executor = (E) this.clazz.newInstance();
executor.setInData(inData);
executor.setOutData(outData);
executions++;
threadPool.execute(executor);
if (outData.getId() == 0L) {
System.out.println(String.format("Não alterado o objeto da execução %d: %s", executions, outData.toString()));
} else {
System.out.println("ok");
}

} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

}

A classe MainTest executa em série, mas o resultado é o processamento paralelo porque tem como executor de FinalExecutor o ThreadPoolExecution 

public class MainTest {

public static void main(String[] args) {
ThreadPoolExecution<FinalExecutor> tpe = new ThreadPoolExecution<FinalExecutor>(FinalExecutor.class);
for (long count = 1L; count <= 1000; count++) {
ValueObject inData = new ValueObject();
ValueObject outData = new ValueObject();
inData.setId(count);
inData.setName(String.format("Named %d", count));
tpe.execute(inData, outData);

}
}
}

Resultado com erro

Não alterado o objeto da execução 1: ValueObject [id=1, name=Named 1]
Não alterado o objeto da execução 2: ValueObject [id=0, name=null]
...
Não alterado o objeto da execução 997: ValueObject [id=0, name=null]
Não alterado o objeto da execução 998: ValueObject [id=0, name=null]
Não alterado o objeto da execução 999: ValueObject [id=0, name=null]
Não alterado o objeto da execução 1000: ValueObject [id=0, name=null]

A solução

A execução em ThreadPoolExecution sempre ocorre em paralelo e na maior velocidade possível para garantir produção porque como o próprio nome diz, é um pool de threads com duas threads executoras. Observe o construtor de ThreadPoolExecution.

Por causa disso, não é obrigação da ThreadPoolExecution garantir a atualização em tempo real de qualquer objeto alterado, pois isso cabe a JVM realizar espontaneamente o sincronismo. No caso "O problema" foi um caso de estudo forçado para a execução em paralelo nunca ser superada pela atualização da referência de outData em todas as classes que a referencia.

Para corrigir o problema, onde se inicia a alteração em paralelo das referência, basta fazer um controle de sincronismo e antes disso, garantir que o objeto a ser operado jamais estará nulo porque o sincronismo só funciona com objetos e não com nulo.

Conforme dito, a correção inicia onde a operação é bifurcada para processamento paralelo e na operação fim. Portanto:

A classe FinalExecutor está corrigida no destaque em amarelo

public class FinalExecutor extends AbstractExecutor {

@Override
protected void execute(ValueObject inData, ValueObject outData) {

synchronized (outData) {

outData.setId(inData.getId());
outData.setName(inData.getName());
outData.notify();
}

}



A classe ThreadPoolExecution também foi corrigida conforme destaque em amarelo

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ThreadPoolExecution <E extends AbstractExecutor> {
private static int executions;
static {
executions = 0;
}

private Class<E> clazz;
private ExecutorService threadPool;
public ThreadPoolExecution(Class<E> clazz) {
this.clazz = clazz;
this.threadPool = Executors.newFixedThreadPool(2);
}

public void execute(ValueObject inData, ValueObject  outData) {
try {
E executor = (E) this.clazz.newInstance();
executor.setInData(inData);
executor.setOutData(outData);
executions++;
threadPool.execute(executor);
synchronized(outData) {

try {
outData.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (outData.getId() == 0L) {
System.out.println(String.format("Não alterado o objeto da execução %d: %s", executions, outData.toString()));
} else {
System.out.println("ok");
}

}

} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

}

}

Resultado

1: ok
2: ok
...
997: ok
998: ok
999: ok
1000: ok

Espero com este artigo polpar os desenvolvedores e projetistas de softwares terem de gastar horas para analisar a origem deste problema simples de compreensão, mas altamente complexo de ser percebido no dia-a-dia.

Boa sorte.

domingo, 1 de dezembro de 2013

Banco de dados - Principais erros no desenvolvimento de software

Hoje vamos tratar de um assunto pouco levado em conta por empresas desenvolvedoras de softwares sem competência profissional para desenvolver software com banco de dados.

Origem do problema e soluções

É comum o empresário não enxergar a importância do banco de dados sobre como este deve ser implementado e os impactos futuros em seus investimentos. Se você é este empresário, o problema pode ser resolvido através de três alternativas bases:

  1. contratar um profissional especialista a partir de critérios de seleção adequados para identificar um especialista comprometido e focado. Este especialista deve conhecer de modelagens de bancos de dados relacionais, multidimensionais e não relacionais com experiência comprovada no exercício de seus trabalhos em projetos de variada complexidade e finalidade. Sua formação deve ser comprovada no campo teórico e prático, para isso, é importante compreender se o especialista tem experiência nos bancos de dados predominantes no mercado, não é recomendável contratá-lo somente baseado na tecnologia do banco de dados utilizado por sua empresa;
  2. se sua empresa não tem demanda o suficiente para contratar um especialista, então procure ponderar as características de um especialista em banco de dados para uma das competências de um analista de seu quadro profissional, é possível identificar no mercado profissionais focados em análise de projetos com excelente competência desenvolvida profissionalmente e academicamente em banco de dados;
  3. a outra maneira de sanar o problema é identificar em sua equipe de projetistas um profissional alinhado com banco de dados e então investir em cursos de boa procedência e até mesmo adicionar na atividade do profissional o aprendizado formal sobre o assunto, mas neste caso, não transfira a responsabilidade do pagamento do curso ou compra de livros para o profissional porque isso é má fé, e o profissional mais cedo ou mais tarde pode perder sua motivação ao se sentir lesado.


Mitos e verdades acadêmicas

No final de 1990, ocorreu uma crescente busca pela Análise Orientada à Objetos (A.O.O.), pois a sua antecessora, a Análise Essencial (A.E.) já não sustentava as demandas por projetos de sistemas porque seus documentos não eram de fácil compreensão para os menos envolvidos no projeto do sistema e principalmente, o cliente final, mesmo sendo estes do campo da ciência ou tecnologia.

Nota: Embora a Análise Essencial não comunicasse claramente com todos os envolvidos, é importante resgatar, ela simplificou em muito as técnicas de desenvolvimento de softwares, pois tratava de amparar a projeção de um software detalhadamente sem considerar a forma de implementação, desta maneira a Análise Essencial tinha como principais contribuições o foco no serviço a ser entregue ao cliente e melhor controle das estruturas (funções), porém, numa visão de quem implementa o projeto.

A Análise Essencial evoluiu da Análise Estruturada, esta é praticamente o primórdio da análise para projeto e desenvolvimento de sistemas ao alcance de pessoas comuns, sem dotes de gênios, e a maior parte da compreensão da maneira de conceber um novo sistema ainda é um legado dessa análise. A Análise Estruturada se pauta na seguinte ordem elementar para projetar um sistema: DFD (Definição Fluxo de Dados), DER (Definição de Entidade-Relacionamento) e MER (Modelo de Entidade-Relacionamento). O DFD é o estudo lógico dos dados de entradas, processamentos e dados de resultados após os processamentos. Após elucidada esta etapa, o analista partia para a definição das entidades do sistema e seus relacionamentos. Já ao final destas etapas, o especialista em banco de dados cuidava de tratar do modelo de armazenamento dos dados a considerar o melhor desempenho, menor consumo de recursos computacionais e a fácil manutenção.

De volta a crescente busca pela Análise Orientada à Objetos, nas escolas e nas empresas, tornou-se um modismo dar total ênfase a A.O.O. porque ela comunicava bem com o cliente final a partir dos documentos exigidos por essa análise, mas toda contribuição das suas análises antecessoras foram subestimadas radicalmente e passamos a ver excelentes diagramas lógicos com uma clareza quanto o seu fluxo de processamento do sistema, identificação dos objetos operados pelo sistema e quase todos os estados possíveis de um processamento eram elucidados de maneira bastante simples. O principal estopim do sucesso da A.O.O. foram os esforços no início por parte das empresas em entregarem diagramas mais claros para os seus clientes validarem seus pedidos e terem real capacidade crítica a respeito do proposto sistema.

Assim como dizem que a arte imita a vida, a programação imita a análise. Quer dizer,  na última década, emergiram ferramentas de alta produtividade e estas ferramentas privadas ou desenvolvidas por comunidades de códigos livres, passaram a potencializar a Orientação à Objetos, mas uma nova anomalia surgiu no mercado de desenvolvimento, os Objetos da Programação Orientada à Objetos (P.O.O.) passaram a ser confundidos com as Entidades do Modelo Entidade-Relacionamento. Aqui é importante destacar, os Objetos são estruturas geradas durante o ciclo de vida de um sistema com uma conotação dos objetos do mundo real para facilitar ao programador não perder o foco no serviço esperado. Quando o sistema se encerra, os Objetos normalmente precisam ser armazenados em banco de dados. Já as Entidades não tem relação direta com os Objetos, pois Entidades estão relacionadas a forma de armazenar os resultados de uma operação do sistema, seja esta um cadastro ou uma transação financeira por exemplo.

Normalmente os profissionais de TI possuem este discernimento teórico, mas na prática, as demandas os exigem e os encantaram demais a concentrarem suas cresças em apenas a A.O.O. e a P.O.O.. O problema deste deslocamento de conhecimento para apenas uma geração de análise é deixar para trás técnicas de conhecimentos importantes para o suprimento de falhas da A.O.O..

Agora temos no mercado um excesso de programadores sendo responsabilizados pelo modelo do banco de dados sem o devido conhecimento. Este problema é agravado porque na entrega do sistema, o banco de dados está vazio e as omissões ou banalizações do Modelo Entidade-Relacionamento, só passam a apresentar seus efeitos quando o banco de dados cresce e atinge um grande volume de dados.

Nesta etapa, os contratos já foram concluídos e o cliente passa a arcar com o ônus das omissões de uma geração cobrada apenas para produzir dentro da última moda do campo da análise e não podem pensar demais porque é um geração pressionada por resultados para cumprir pequenos prazos, realizarem custos baixos e entregar uma falsa qualidade.

O cliente também é corresponsável por isso quando pressiona seu fornecedor de software a menores prazos e preços todavia.

Concluí-se portanto este problema sendo mais mercadológico do que de uma parte ou de outra. Projeto de software ainda é visto por muitos como algo simples e rápido, qualquer pessoa consciente ao tentar dizer o contrário sofrerá retaliações, não pessoal, mas é porque projeto de software é commodity pelo volume de ofertas atual.

Principais erros no desenvolvimento de software com banco de dados

Vamos a verificação dos principais erros, alvos deste artigo.

1) Confundir Objeto com Entidade

A confusão do Objeto com a Entidade é um erro normalmente ocorrido na etapa de concepção de um sistema, pois pensa-se no Objeto como sendo um tabela nos casos mais crônicos.

2) Não se releva no projeto de software a importância do MER

A falta de competência em Modelo Entidade-Relacionamento está ligado ao mal investimento de uma empresa fabricante de software, porque pensa-se no hoje somente, a lógica do consumo rápido faz todos esquecerem dos efeitos desta omissão. Na prática, o banco de dados é um sistema e como qualquer sistema, tem seus pré-requisitos para funcionar corretamente, manter o desempenho ao longo de seu crescimento, atender as necessidades de relatórios sem impactar o sistema que o abastece, conhecido como sistema operacional (não tem nada a ver com Windows, Linux e outros, trata-se do sistema com as operações desenvolvidas e ligado ao banco de dados).

A presença do profissional especialista em banco de dados ainda é a melhor maneira de projetar um sistema capaz de manter o mesmo desempenho em seus primeiros dias de vida e após meses de funcionamento porque ele vai saber como organizar os dados em entidades, gerar os relacionamentos, identificar as indexações vitais para o desempenho das operações principais, relatórios, determinará as políticas de manutenção dos dados como é o caso do controle transacional quando muitas entidades estão envolvidas em uma operação, escalonamento para o sistema comportar novos módulos ou funcionalidades sem sofrer deformações impactantes para o sistema operacional e muito mais.

Em resumo, somente um profissional competente é capaz de prever com muito mais facilidade do que um programador as melhores práticas de organização e manutenção dos dados operacionais e ainda saberá resolver as novas demandas por processamentos gerenciais sobre o banco de dados sem impactar o sistema principal.

3) Erros principais em relatórios

Não é anormal se você for investigar seus relatórios, identificar problemas críticos que impactam na integridade das informações esperadas por você e você nem saber destes problemas. Aqui falo do programador pressionado a gerar relatório, dentro do seu conhecimento ele tende a ignorar as normas de relacionamentos, filtros constantes e variáveis a serem aplicadas na consulta do relatório. Na prática ele pode, por exemplo, apresentar os resultados financeiros parcialmente porque fez uma relação "inner join" (deve estar contido nos dois conjuntos para mostrar a informação) entre a tabela de resultados com cadastros. Se o cadastro for facultativo, simplesmente as transações ocorridas para o cadastro não realizado não serão mostradas e é comum este erro, somente os usuários mais críticos conseguem perceber o problema mesmo sem entender a causa e reclamar a empresa fabricante do software.

Outro problema é a maneira de construir a consulta do relatório, pois o programador desconhece na maior parte das vezes as corretas práticas para interagir com um banco de dados, por isso ele costumeiramente ignora a necessidade de criar índices adequados a consulta ou quando cria os índices, não possui propriedade para criar o índice dentro da ordem necessária requerida pelo banco de dados oferecer o real bom desempenho. Um índice criado com falha ou desnecessário, pode repercutir em lentidão nas operações principais de um sistema.

Por fim, quando um programador receber a responsabilidade de modelar o banco, por coerção na visão geral do mercado, normalmente ele desconhece o que é entidade forte, entidade fraca, relacionamentos, chaves primárias, chaves estrangeiras, cardinalidade, espécies de índices e por isso, pode arbitrar durante a construção de uma consulta e violar muitos dos pré-requisitos de um banco de dados. O impacto disso? Relatórios simples graficamente, porém demorados, são sem integridade ou impossíveis de serem executados a partir do aumento do volume de dados.

4) Computação financeira ou contábil

Normalmente este erro vem do erro de relacionar pessoas que trabalham com computador, pessoas que dominam a matemática financeira ou contábil.

Dificilmente se vê um processamento deste detalhado claramente em um documento, pois o programador receber toda a responsabilidade em atender esta demanda computacional sem que este trabalho seja previamente especificado ou posteriormente conferido com o rigor necessário.

O impacto neste caso depende de quem utiliza os dados computados para fins financeiros ou contábeis. Caso a informação esteja incorreta, o cliente pode pagar alguma tributação para mais ou para menos porque mal saberá se existe falha porque o cliente geralmente confia em seus sistemas.

Conclusão

O problema abordado aqui está relacionado de fato a banalização do MER pelas empresas desenvolvedoras.

A saída do problema depende de cada empresa fabricante de software impor condições melhores para a entrega de um produto, mesmo se para isso ela tiver que abrir mão de novos atendimentos, pois estes na verdade estão ligados a retrabalho e não a desenvolvimento.

sábado, 23 de novembro de 2013

Omissão em campanhas eleitorais fora de hora

Nesta semana trabalhei ouvindo notícias ao mesmo tempo de alguns canais.

Fico impressionado com a articulação pré-eleitoral e mais uma vez o PT (Partido da Perda Total) conseguiu silenciar o STE, pois em eleições estaduais ou municipais, a campanha antecipada é violação de leis eleitorais e a mesma lei é neutralizada pelo soberano governo?

O teatro do Mensalão novamente é um reavivamento de uma história já apagada para prender Dirceu, Genoino, Delúbio, Marcos Valério e toda a patota da alegria. Mostram um jato de luxo escrito polícia federal, mesmo se não tivesse bancos de luxo tal jato será de uso de poucos neste mundo.

O Genoino é o típico político cara-de-pau responsável por fazer frente a história toda, dar mais ofuscamento mesmo e consequentemente tentar causar um real ataque cardíaco, mas não nele, porém no genuíno Joaquim Barbosa, este único lúcido justiceiro no sentido não pejorativo da palavra.

Desta vez o chefe do bonde da alegria só faltou pedir para a postiça presidente dizer "vamos cortar da própria carne" dez anos após a última encenação pré-campanha da dobradinha premiada da nossa sorte.

O mais lamentável é ver o SBT e Globo com seus telejornais sintonizados em discretamente apoiar o PT, certamente porque terão algum tipo de presente e já atacam todos os personagens conhecedores desta artimanha petista como é o caso de tentar associar o Alkmin a conluio na aquisição de composições para as linhas do metrô da cidade de São Paulo, atacam Marina Silva, Eduardo Campos e no aniversário da morte provocada ao presidente John F. Kennedy, o SBT faz uma matéria relacionando o Obama ao falecido presidente na questão de criar uma ideia de ambos falarem demais e nada fazerem, porém convenhamos, não se trata dos defeitos dos presidentes, isso ainda é uma reação petista ao governo do Obama por causa das espionagens dos EUA sobre o percurso do trem da alegria.

Foi dolorido ouvir a jornalista replicando em voz as palavras do tele-prompt "o governo anti privatização reconhece na privatização o mal necessário, pois muitos setores da economia não podem ser geridos diretamente pelo setor público". Privatizar não é vender e nem significa corrupção, aliás toda corrupção em demandas públicas privatizadas são oriundas de partidos formados por lideranças infestadas de bandidos sem contar os organismos públicos já consolidados nesta prática há muitos anos, basta ser um empresário bem informado e formado para saber disso. A privatização nunca beneficia empresário via de regra, pois as demandas são leiloadas pelo governo e o lucro interessante vai para o vazado cofre público por quê? Simples, porque não há retorno algum para quem quiser ver.

De volta ao assunto principal, campanha para presidência fora de hora é crime, o PT já comemora vitória com todos seus paramentos e todas suas táticas para reeleição de mais um presidente postiço, Dilma no caso.

A sociedade está dividida em três grupos, o maior e ainda predominante deles acredita na mídia, nos falsos números e propagandas positivas a respeito de entregas de benefícios sociais irrelevantes comparado a escravização do nosso povo com tanta tributação e omissão nos cuidados principais: educação, segurança e saúde. Faltam criar a taxa do respirar em grande metrópoles, a destacar São Paulo, a real fonte de renda nacional sem querer ofender as demais metrópoles, porém sendo honesto em relação a metrópole mais tributada e explorada propositalmente, até seu trânsito é um fortíssimo sistema de arrecadação para os governantes de maior escalão.

Foi recente a unanime tentativa de todos os personagens públicos, vergonhosamente dos vereadores, de aumentarem o IPTU de São Paulo justamente após escândalos de furo na arrecadação porque fiscais da Receita Federal aliviavam  ISS para algumas construtoras. A reação do PT foi retomar este valor perdido em impostos do povo de São Paulo e prove ao contrário quem puder, pois estes imperadores não se fartam nunca. A máfia do ISS nem prejudicou o povo, mas mexeu na arrecadação do governo, portanto, "crime hediondo", "cana" e conclusão de causa rápida para justiça do cangaço. Não quero relacionar a palavra ao nordeste porque nesta região existem muitas pessoas de boa fé e são responsáveis pelos melhores serviços no país, falo cangaço em seu significado de terrorismo aplicado por Lampião num tempo sem lei ou ordem no sertão de Pernambuco.

É possível existir algum partido de verdade neste país capaz de lidar com tudo isso? Ou em todos eles existem infiltrados sujeitos a prejudicarem idealistas partidários por conta de alguns trocados do grupo informal predominante?

Se o Che-guevara, Napoleão Bonaparte, Abraham-lincoln e, os ainda vivos, Rudolph William Louis Giuliani, Paulo Maluf e Antonio Palocci, sem julgar caráter de cada um porque isso sim é relativo demais, se todos estes estivessem sinergicamente reunidos, seriam todos capazes de fazerem algo?

A equação é grande o bastante para duvidarmos disso.

Vivas ao verdadeiro Lampião e vivas à verdadeira Maria Bonita porque após tantos anos nos acostumamos tanto com isso que pouco faremos, é melhor aceitar o conforto da omissão as mazelas da atitude.

A pátria é amada e gentil mesmo, quem escreveu nosso hino ou fez com boas intenções, porém mal influenciado, ou foi sarcástico mesmo.

Para retomar uma saída, os demais partidos se enfraqueceram porque são formados por humanos e a maior parte de nossa geração é imediatista, porque prioriza o maior lucro no menor prazo para si. Com esta mentalidade, nem sociedade e nem partidos crerão no estado de ordem para o bem social.

Poucos se dispõem a gastarem muito tempo para pensarem na importância da ordem social e já cansados, sentem-se feridos ao ouvir a palavra política. A política só não é uma ciência de ordem porque foi roubada dos idealistas a partir de nossa compassividade com os imperialistas.

Em tempos do pragmatismo ninguém pode parar para pensar senão a roda da fortuna perde velocidade e ameaça nossos sonhos de consumo como viagens para comprar tecnologias nos EUA, aquisição de carros mais bonitos do que os dos nossos vizinhos, podemos perder a próxima versão do iPhone produzido no Brasil e tributado como produto importado, ainda nossas TVs de maiores polegadas podem faltar, talvez a educação particular (é mais uma babá terceirizada) paga aos nossos filhos não seja possível, ou o seguro do carro coloque este bem de alta prioridade em risco e o próximo campeonato talvez nós não o assistamos porque uma leve desaceleração da roda da fortuna nos impeça de pagar PFC ou cativar lugares em restaurantes ou bares para ver os jogos favoritos aprisionados por nossos king empresários, mas com uma fiança você vê seu jogo.

A saúde é somente um grito dos necessitados, porque os economicamente ativos possuem saúde não param para pensar, a saúde não é gerada do parcelamento de um plano médico, ela é consequência de um estilo de vida onde é possível ter tempo para pensar, organizar a vida no estilo menos danoso e em lugares com menos taxas de Oxido de Nitrogênio (NOx), Dióxido de Enxofre (SO2), Monóxido de Carbono (CO2) e outros poluentes de alta periculosidade para a saúde tão presentes nas grandes urbes.

Esta pressa para girar a roda da fortuna nos deixa vulneráveis e ainda nos deixará por muitos anos a sermos escravizados e alienados ouvindo a palavra democracia como se ela fosse real ou justa socialmente. Talvez seja sim, pois se todos decidimos girar a roda da fortuna as custas da própria vida, isso é tecnicamente democrático no mau sentido.

Não precisamos de pressa nem de novas versões de bens de consumo para vivermos, isso é sobrevivência e não é viver.

As necessidades básicas como a manutenção da saúde, alimentação, educação e tempo para gerar conhecimentos para promoção da saúde social, a destacar famílias e comunidades, são nossas principais necessidades das quais somos privados porque devemos bater o ponto todos os dias para não sermos castigados pelas entidades carcereiras "econômicas".

segunda-feira, 28 de outubro de 2013

Java - Obter caminho da aplicação

Obter o caminho completo de uma aplicação algumas vezes é necessário para o programador poder criar, alterar, apagar ou simplesmente acessar subpastas ou arquivos em um sistema de arquivos nativo do sistema operacional. Enfatizo o sistema de arquivos do sistema operacional porque ocorre algumas vezes também a necessidade de se obter acessos de pastas ou arquivos de um JAR, porém não é alvo deste artigo isso.

A classe ApplicationPath

Esta classe contém o método estático para retornar o caminho absoluto de execução da aplicação e tem um simples método main para testar a obtenção do caminho da aplicação.

import java.io.File;
import java.io.IOException;

public class ApplicationPath {

public static String getAppPath() throws IOException  {

String result = null;

File f = new File("");

result = f.getCanonicalPath();

return result;

}

public static void main(String[] args) {

System.out.println("Caminho desta aplicação:");

try {
System.out.println(getAppPath());
} catch (IOException e) {
System.err.println("#Erro#");
}

}

}

Resultado

Caminho desta aplicação:
C:\Users\admin\workspace\Test

sexta-feira, 27 de setembro de 2013

Controlar para enfraquecer

A célebre frase "dividir para conquistar" de Júlio Cesar foi assimilada nos últimos tempos como o ato de pegar um problema, reparti-lo em menores fragmentos e então resolvê-lo por estas partes fragmentadas.

O Henry Ford e suas referências liam a frase de Júlio Cesar pela óptica da organização produtiva e desde então vivenciamos até a década de 80 um período extremamente industrial e construtivo para o cenário mundial.

Naquele tempo existia a carreira profissional para dentro de uma empresa porque suas organizações tinham tamanho em escala de desafios para permitirem isso para profissional ao longo de seu ciclo produtivo.

Porém, com a onda de competições ocorrida nos anos 90 a partir da integração dos mercados internacional, fenômeno chamado de globalização, as organizações se reorganizaram para competição por preços menores, uma espécie de pregão mundial gerado pela abertura de fronteiras internacionais e agravantes como vantagens cambiais que exigiu muitas habilidades das empresas nacionais a desenvolverem uma administração baseada em redução de custo enquanto o governo tentava equilibrar a balança comercial para evitar desvantagens cambiais com algum sucesso todavia.

Me lembro ainda de presenciar reuniões onde algum grande gênio recebia promoções quando achava algum processo passível numa visão leviana de redução de custos e assim tornava-se uma espécie de herói da administração financeira da empresa sem relevar os efeitos sistêmicos de sua solução bitolada e assinada pela empresa.

Este hábito foi tão repetido e massageava tanto o ego dos administradores que viam como forma de competição somente a redução de custos até isso deformar, na década de 2000, o sentido das organizações.

Entramos naquela década e as  empresas ali já reduziam o quadro profissional e acumulavam papéis adicionais aos menos providos de qualificação ainda prematuros sob um discurso de que o profissional era diferenciado, capaz e estava sendo reconhecido com mais papéis e um pouco de aumento. Uma estratégia um tanto quanto promissora para a empresa de fato e para o profissional somente no âmbito utópico, porque apesar de um pequeno aumento, o colocava numa situação de mal estar ou perplexidade quando passava semanas com vários papéis sendo exercidos e acatados como o mínimo a ser feito para permanecer empregado.

A partir dos anos 2000 foi dada a largada para o Você S.A. e empresas, consultores, palestrantes e cientistas pessoais ensinavam-nos a sermos como uma mala de viagem internacional, ou seja, cheios de selos, conhecimentos culturais, do noticiário mundial do último ano para ser relevado como cidadão, habilidades inúmeras e atitude de um tapado garrido convicto numa promoção na escala organizacional.

Bom, mais de 10 anos se passou e as organizações sólidas e verdadeiras foram enterradas na utopia de espaços virtuais e a máxima do você é o guerreiro letrado na arte da guerra e tudo pode naquele que lhe enfraquece. A empresa tornou-se o deserto de muitos profissionais altamente capacitados mas sem perspectiva real dentro de organizações já enxutas e ao mesmo tempo este fenômeno deu aval, em estágio ainda prematuro, para profissionais aceitarem desafios aquém de seus limites porque uma organização reduzida transfere até a responsabilidade de acerto para o profissional não importando se está atitude incompetente da empresa será uma tocha incendiária da motivação do profissional.

O que vivenciamos hoje pode ser por praxe verdadeira o abandono do planejamento social por parte dos nossos governantes, mas as empresas poderiam mudar isso dentro de "casa" se reconhecem sua capacidade de blindar organizações saudáveis em momentos de crise nacional ou competitividade baseada em reduzir custos com demissões em massa ou a transferência de todas responsabilidade ao pequeno quadro profissional sem oferecê-los recursos, não me admira o povo brasileiro ser envaidecido como povo criativo, mas e dai se não conseguimos competir de fato ou fortalecer a nação com soberania?

Só sairemos deste ciclo vicioso quando cada figura chave reconhecer em seu leque de responsabilidades não a produção de bens para consumo, mas o dever de formar pessoas e investir em pessoas para obter no relativo longo prazo resultados em espécie de fortalecimento nacional de mão-de-obras capacitadas e educadas para contribuírem como famílias a exercerem junto com empresas e outras organizações não governamentais uma força regulatória deste governo que aproveita de uma década de decadência para realizar negociações de patrimônios e conquistas do povo brasileiro pela óptica de violarem o povo a fim de um enriquecimento financeiro astronômico até que as empresas e o povo acordem desta letargia.

País soberano depende de mais esforço do que vaidade e cresças em indicadores isolados de análise propositalmente para se criar uma ilusão de economia saudável.

Enquanto isso, o povo nesta sonolência mórbida e cega, alguns aproveitam deste estado para o exercício do controle e zelo pelo inexistente poder a sufocar o estado colaborativo e coletivo pautado da velha máxima de que a união faz sim a força para dividirmos o problema calamitoso o qual passamos para conquistar efetivamente.

Todavia, com a transferência crônica de responsabilidades as empresas sequer reconhecem o pedido sufocado de seu quadro profissional de aliança colaborativa e promovem o exercício reflexivo do mestre e o escravo.