Terça-feira, Abril 29, 2008

Projeto Orientado a Componentes, parte III

Agora, uma pausa para reflexão. Esta dicotomia interface versus implementação é difícil de definir. Por baixo dos panos nós temos memória de onde nós lemos e para onde nós escrevemos. O que caracteriza uma interface e o que a distingue de uma implementação?

Essa pergunta só pode ser respondida em um determinado contexto. Um bom sistema escrito em assembler talvez tenha interfaces mais bem definidas que um mau sistema escrito em Java. Porém, está claro para a indústria que certos mecanismos de linguagem favorecem o estabelecimento de boas interfaces no sistema implementado.

Além disso, a noção de interface surge diante de um problema de substituição. É interface aquilo que, mantendo-se estável, permite a substituição daquilo que é implementação. Porém, o que é este permite? Este permite, quando caracterizado, por conseguinte caracteriza o que é interface.

Suponha um sistema escrito em C++ por uma equipe que considera irrisório o tempo de recompilação do código-fonte. Neste contexto, podemos seguramente aceitar que a seguinte substituição mantém estável uma interface.

antes


class Foo {
public:

Foo ();

void
mutate_stuff ();

int
observe_stuff () const;

private:
Bar* m_bar;
};

depois

class Foo {
public:

Foo ();

void
mutate_stuff ();

int
observe_stuff () const;

private:
int m_cache;
shared_ptr<bar> m_bar;
};

Após a alteração acima e uma recompilação o sistema continua a funcionar normalmente. [1] Dizendo de forma mais extensa: neste contexto, a substituição realizada não altera propriedades observáveis externamente da classe, de modo que do ponto de vista de um observador, a classe mantém estável sua interface. (Apenas membros privados foram alterados.)

Agora vamos alterar as nossas premissas. O tempo de recompilação desse sistema é enorme e o ciclo de testes não pode esperar, de modo que a estrutura de classes do sistema foi particionada e esta classe mora dentro de um objeto compartilhado, uma biblioteca dinâmica.

A equipe realiza a substituição, recompila o objeto compartilhado e o entrega a uma equipe de testes.
E os testes falham miseravelmente.

Isto acontece porque, neste novo contexto, há mais propriedades observáveis a considerar, que devem se manter estáveis -- que fazem parte da interface da classe.
Neste caso, o layout de um objeto da classe Foo é uma propriedade observável; um programa compilado criando objetos da definição antes criará objetos com um layout diferente daquele esperado pelo objeto compartilhado que espera objetos dada a definição depois.
A definição depois tem um int no offset onde a definição antes tinha um ponteiro, ela ocupa mais memória etc.

Podemos dizer que o primeiro caso é o caso de um projeto orientado a objetos, onde a alteração de elementos privados da classe não altera a interface; e podemos dizer que o segundo caso é o caso de um projeto orientado a componentes, onde a alteração do layout na memória de uma classe altera sua interface.

Como no segundo caso nós estamos violando a interface do componente, nós não podemos substituir o componente de antes pelo componente de depois impunemente. Dito de trás para a frente, pelo fato de não podermos substituir o componente de antes pelo componente de depois, por definição estamos violando sua interface.

Imagine então o que acontece em um sistema spaghetti, onde todas as classes mantém referência a todas as outras classes; uma violação de interface em um "componente" perturbará implacavelmente todos os outros "componentes".

Quando projetamos um sistema pensando em componentes, ou quando desejamos aplicar a idéia forte de interface para melhorar o nosso projeto diminuindo o acoplamento entre as coisas que são distintas, é útil usar das ferramentas à disposição para dar forma ao que é uma interface.

Linguagens que se propõe a facilitar o desenvolvimento de componentes, como Java e C#, possuem como parte integrante do seu vocabulário e mecanismo nativo uma interface em contraste com as classes. Normalmente algo do tipo:

interface IFoo {

void
mutate_stuff ();

int
observe_stuff () const;

};

Em C++ não existe uma construção análoga mas é possível emulá-la integralmente usando classes, da seguinte maneira:

class IFoo {

virtual
void
mutate_stuff () = 0;

virtual
int
observe_stuff () const = 0;

};

(O leitor astuto observará que esta construção-interface não possui atributos.)

O propósito de usar construções como estas é evidenciar a natureza destes elementos como interfaces -- aquilo que se deseja manter estável -- e diminuir a chance disto que é interface ser inadvertidamente alterado -- causando o desastre. A construção-interface é a melhor amiga do projetista de componentes, permitindo a representação de um conceito de projeto diretamente na linguagem do código-fonte, restringindo as possibilidades de violação durante o processo de implementação, ou ao menos tornando a (necessidade de) violação claramente evidente.

Infelizmente para nós nem tudo que existe na fronteira de um componente pode ser uma interface, já que é preciso comunicar coisas de um componente para outro. E quem pode viver comunicando apenas doubles e bools? Nós queremos comunicar objetos.

Além disso, as construções-interface não são garantia de estabilidade de interfaces, já que há mais sobre o que é publicamente observável em um objeto que sua estrutura: há o seu comportamento.

[1] Estamos, naturalmente, assumindo que o programador não é louco e que a alteração tem algum sentido, exatamente como aparenta ter.

Segunda-feira, Abril 28, 2008

Projeto Orientado a Componentes, parte II

Quando dizemos que componentes são por definição intercambiáveis estamos continuando uma longa tradição de bons projetistas de bons sistemas, cujo conjunto de características sempre integrará, por mais sofisticada a metodologia e/ou a nomenclatura, a aplicação da separação entre interface e implementação. [1]

Se a interface continua a mesma, podemos substituir a implementação sem perturbar o comportamento do sistema. Obviamente que o comportamento do sistema deve mudar de alguma forma, senão trocar a porcaria do componente não teria propósito. Esperamos, portanto, que erros sejam corrigidos (de modo que o sistema de fato funcione como deveria), ou que o desempenho aumente (de modo que o sistema funcione antes que eu caia no sono) ou sei lá.

Aplicávamos esta distinção já na era do projeto estruturado; e no projeto essencial; e no projeto orientado a objetos; e agora no projeto orientado a componentes e aplicaremos no projeto orientado a serviços quando finalmente este troço alcançar a plebe.

Em um sistema orientado a objetos, nós temos tipicamente dois elementos em evidência como detalhe de implementação: a estrutura de um objeto, e as instruções levadas a cabo por seus métodos. Nós queremos liberdade para alterar a estrutura de um objeto e queremos liberdade para alterar a instruções executadas por seus métodos. (Há mais por debaixo do pano, como sempre.)

Em um sistema orientado a componentes, um terceiro elemento surge ofuscando, como se fosse, os outros dois; o componente propriamente dito. Entendemos que um componente possui uma interface e uma implementação; sendo a implementação de um componente composta por inúmeras classes. Além disso, um componente é um artefato componente (heh) de um sistema implantado; é parte da definição de componente que este seja intercambiável por um outro, que implemente a mesma interface, em um sistema implantado -- em contraste com um tipo de substituição que exige recompilação.

Esta última restrição, quando posta no contexto dos sistemas operacionais reais, com seus linkers e loaders reais, nos trás à crux do problema de projeto orientado a componentes: a implementação de uma classe integrante de um componente absolutamente não pode depender de um detalhe de implementação de uma classe integrante de outro componente.

Observe que esta restrição não é exatamente uma novidade, já que bons sistemas isolarão módulos através de interfaces para aumentar a coesão e diminuir o acoplamento; porém, quando componentes entram na jogada, a metodologia exige uma restrição mais forte.

(De fato, esta restrição metodológica se torna uma impossibilidade tecnológica assim que os componentes são levados ao próximo estágio, passam a não mais morar no mesmo espaço de memória virtual, e começam a ser chamados "distribuídos" ou "serviços".) [2]

É por esta razão que os líderes do Projeto Spaghetti falharão em "componentizar" seu sistema; mesmo que, à primeira vista, seja possível seccionar sua estrutura de classes em artefatos binários distintos.

[1] Nós, filhos da cultura européia, nem escrevendo programas nos livramos da dicotomia corpo versus espírito. Nem imagino o que seria uma metodologia de desenvolvimento de sistemas desenvolvida por monges taoístas chineses.

[2] E portanto, domar a restrição metodológica significa poder conviver com a impossibilidade tecnológica e eventualmente programar os sistemas do futuro.

Projeto Orientado a Componentes, parte I

Ano passado fiz um curso de extensão em Projeto Orientado a Componentes com UML; na época, eu estava progredindo na minha capacidade de construir modelos mentais de projetos de software orientados a objeto e já havia lido bastante sobre web services e arquiteturas orientada a serviços.

O mais interessante sobre os Componentes é a maneira como eles dão um nó na sofisticação aparente dos sistemas e obrigam o projetista a voltar aos básicos. Digo isso porque estes sistemas são aparentemente sofisticados; na prática, eles apresentam baixa coesão e alto acoplamento, significando que elementos deste sistema se relacionam diretamente com praticamente todos os outros de maneira ad hoc, fenômeno que, em sua forma mais concreta, denomina-se código spaghetti.

É possível construir um sistema orientado a objetos onde todos os objetos conhecem ponteiros para todos os outros, ou praticamente todos os outros, usando truques safados como embrulhar todo mundo em shared_ptr e tornando todas as classes enable_shared_from_this e olerê olará. Isto, é claro, se você tem um mínimo de conhecimento sobre C++ contemporâneo -- e se você está de fato escrevendo seu sistema em C++! -- e se você se importa com a memória. O sistema acima é "orientado a objetos". Muitos deles, embolados entre si.

Quando você se propõe a fazer sistemas orientados a componentes, porém, o buraco se alarga e se torna mais profundo. Os componentes existem com o propósito de serem intercambiáveis. Você não tem componentes se você não pode tirar um deles e colocar outro no lugar impunemente.

Frequentemente, os responsáveis por sistemas spaghetti ou aberrações similares, diante dos problemas insuportáveis causados inevitavelmente pela baixa coesão e pelo alto acoplamento, tentam "componentizar" seus sistemas com o intuito de obter os benefícios maravilhosos oferecidos pelos livros.

Vamos, então, pegar pedaços do sistema e enfiar dentro de DLLs!

Certamente isto não funciona.

Quinta-feira, Abril 24, 2008

Pitty

Pitty.
Eu estou ouvindo Pitty.
A semana inteira.
Obsessivamente.

Eu herdei a máquina de um sujeito no trabalho, tem uma pasta "Música" cheia de tralha.
Tem até o "Canto para Minha Morte", do Raul, que eu nunca consegui achar.

Meu player saiu do "Pink Floyd" e entrou em "Pitty".
É impressionante.
Eu não consigo parar. :-(

A banda é razoável e a música é aquele rockzinho[tm] razoável; mas a minha pira é com o que ela diz nas músicas. Não é nada demais; por outro lado... Não sei que porra de fase é essa em que eu entrei. Deve ser o que as pessoas sentem lendo livros de auto-ajuda.

Sábado, Abril 19, 2008

Televisão Digital

Pra quem ainda não sabe, eu dei uma saidinha da indústria da segurança, e estou agora trabalhando com a televisão digital.
Essa semana cumpri minha primeira meta e construí uma aplicação para o set top box capaz de controlar o playback de vídeo.

As capacidades do set top box são muito legais.
A televisão digital será um brinquedo muito maneiro.
Falta pouco pra chegar ao consumidor.
E todos rodarão meu software em casa. :-)

Domingo, Abril 13, 2008

para Sofia sobre kung fu

2008-03-??

Sofia-chan,

hoje no treino coletivo do mo kwoon tive a oportunidade de ver um si dai treinando com seu próprio si dai.
[Nota: mo kwoon é o local de treino de artes marciais; si dai é um irmão mais novo entre os irmãos kung fu.]

Este si dai si hing, coitado, deu um pouco de pena; atrapalhado com a responsabilidade, parecia mais encenando uma peça de teatro que treinando artes marciais.

A dificuldade que eu observei está na vontade de ensinar uma determinada coisa e então construir uma situação onde isso é possível. Isto é, eu quero falar sobre isso, portanto você deve se posicionar de acordo para que o que eu estou dizendo seja fundamentado.

Há pouco kung fu nessa atitude. Esse constante "faz assin, agora faz assado, agora acontece como eu digo" me parece uso de ba lek nesse contexto. A ferramenta do aprendizado, chi sao, é suficiente para que as questões surjam naturalmente do resultado das ações.
[Nota: ba lek é a força aplicada contra a natureza das circunstâncias; chi sao é o treino de combate simbólico do Ving Tsun, onde os dois braços se põe em contato.]

Eu acho que é desnecessário ensinar qualquer uma coisa em particular, e acho que isso se torna cada vez mais evidente com a progressão dos níveis. Aquilo que é importante para cada um é guia suficiente para a introdução dos elementos do sistema de kung fu. A própria pessoa, diante da dificuldade, bem, terá uma dificuldade; o desejo de transpô-la é suficiente para direcionar a sessão de treino aos elementos necessários.

Esse pensamento pode, de certa forma, contradizer a forma sistêmica de transmitir o kung fu -- ou talvez de desencorajá-la ou diminuir o seu valor.

Eu não entendo as coisas dessa forma; entendo que o próprio sistema é um elemento proposto como solução na discussão que naturalmente segue à aproximação do indivíduo e da família kung fu.

Quando o indivíduo aborda a família kung fu, ele tem um problema, um propósito; que seja obter a capacidade de lutar. Dado isto, é natural que o sistema seja apresentado e que o indivíduo ingresse na família.

Mas quem irá parar um estranho na rua para dizer que o problema dele se resolve com Ving Tsun? Isso é tolice. Da mesma forma, no chi sao não se deve parar o si dai para discursar sobre um problema que ele ainda não tem -- ou melhor, para um problema que ainda não ocorreu a ele.

Há um contraponto, no meu pensamento, entre a estase e a dinâmica do kung fu em um praticante, no tocante ao seu desenvolvimento. É natural, e indiscutível, que um si hing cuja responsabilidade é de estimular o chi sao do si dai não deve simplesmente aceitar a situação totalmente como é -- da mesma forma como ele busca melhorar o próprio kung fu, ele busca estimular o kung fu do si dai. Mas isso não é contraditório? Estimular é intencionar que o objeto mude. Como você pode permitir que uma pessoa seja como ela é mas estimulá-la a mudar?

Uma forma de resolver este dilema é buscar no indivíduo o que é sua essência e o que é mero comportamento decorrente de uma história de vida -- talvez. Eu acho perigoso fragmentar o indivíduo desta forma e resolvo na prática este dilema agindo de acordo com a intuição. Eu admito que, apesar de tudo, resta no processo de aprendizado uma atitude fundamental do tipo: você é bom como você é em quase sua totalidade exceto... nisto. Acredito que, do ponto de vista de quem transmite o kung fu, o que a pessoa é não importa, ou, é sempre aceitável; como ela se comporta pode melhorar.

Para nossa família kung fu a natureza desse "pode melhorar" é clara: melhorar é expressar a si mesmo com melhor posicionamento, melhor distância, melhor timing, melhor energia. Além disso, melhor não é mais, melhor é justo; o tanto quanto necessário para realizar sua vontade.
[Nota: timing é timing.]

O que é a vontade do indivíduo é algo intocável pela crítica; não faz sentido dizer ao outro que ele não deve querer o que ele quer. Este fato escapa a muitos processos didáticos, infelizmente. O impulso de impor ao outro uma forma para o seu mundo é natural ao homem; ele é inescapável de certa forma, ao bicho que se comunica de forma tão sofisticada como nós.

Quando nós falamos, nós entregamos ao outro a forma da nossa mente, a estrutura do nosso mundo. É natural que, então, a forma da mente do outro, seu mundo, se ponha a perigo de transmutação. Mesmo a mais singela apresentação de um fato isolado -- uma experiência sensorial! -- apresenta um elemento potencialmente desestruturante, reestruturante. Que dirá um contra-ponto, uma contradição.

chi sao é como o debate dos corpos; esta é a minha estrutura, esta é a sua estrutura, o que acontece quando estas coisas são postas em contato? Apenas esta atitude inicial é suficiente para prover todas as condições necessárias ao aprendizado.

O debate, infelizmente, não possui o tipo de ligação com o corpo que o chi sao tem, de modo que muitas "vitórias" em debates são... ilegítimas, para dizer o mínimo. O ba lek, e como lidar com ele, é uma arte que não sei onde aprender, nesse contexto.

Sei que o Ving Tsun me habilitou a construir minha própria arte e só.

Domingo, Abril 06, 2008

Projeto: Eclipse + CppUnit

Estou prestes a apresentar para o ccppbrasil.org um projeto de integração da CppUnit com o Eclipse TPTP.

Será uma oportunidade interessante de aprender a desenvolver sobre a plataforma OSGi e uma maneira de estimular a comunidade a aplicar as técnicas de testes de unidade.

A arquitetura do TPTP Test é assim: para um determinado "tipo de teste" registra-se um adaptador de implantação, um adaptador de ambiente e um adaptador de execução, bem como um runner para este "tipo de teste" no agente remoto.

A tarefa será implementar esses adaptadores para programas executáveis nativos e bibliotecas compartilhadas, resolvendo LD_LIBRARY_PATH e assuntos relacionados, depois implementar uma biblioteca de suporte em C para que programas joguem na saída padrão o histórico de execução da forma correta e por fim implementar com um wrapper Java um runner para suites de teste CppUnit na forma de plug-in.

Na verdade as tarefas ainda estão se abrindo porque não consegui dominar o problema de projeto completamente, o que me aborreceu um pouco, já que vou passar a semana ocupado com outros assuntos.

Quarta-feira, Abril 02, 2008

Encontro de Nerds em São Paulo

Ora, aqui estamos nós!
O Encontro foi muito bom, evoluindo o formato do anterior.
Os nerds são inteligentes e conhecedoras das coisas, e bebem bastante cerveja e são engraçados demais.
Nosso trabalho continua no site ccppbrasil.org.