sábado, 17 de maio de 2008

Como iniciar uma thread com múltiplos parâmetros

Ainda hoje surgiu esta questão. Necessito de executar um pedaço de código numa Thread separada mas tenho de lhe passar um conjunto de parâmetros. A solução clássica passa por criar uma classe que expõe as propriedades necessárias e executar a thread numa instância dessa classe. Algo do género:

MyThreadClass myThreadClass1 = new MyThreadClass() { P1 = 1, P2 = "teste" };
ThreadStart threadStart1 = new ThreadStart(myThreadClass1.start);
Thread thread1 = new Thread(threadStart1);
thread1.Start();
class MyThreadClass
{
public int P1 { get; set; }
public string P2 { get; set; }
public void start()
{
//algum código...
}
}

Pode-se também criar uma struct ou classe simples onde se colocam os parâmetros necessários e utilizar o ParameterizedThreadStart, mas a questão mantêm-se: se o código a executar paralelamente é algo muito simples, não deveria haver uma solução mais simples? Claro que há. O construtor da classe Thread pode receber uma ThreadStart ou uma ParameterizedThreadStart. Ambos são delegates. Porque não construir ThreadStart que aponte para um simples delegate que por sua vez chama o método que se pretende paralelo? Como por exemplo:

ThreadStart threadStart1 = delegate { threadWith2Parameters("texto 1", "texto 2"); };
Thread thread1 = new Thread(threadStart1);
thread1.Start();
private void threadWith2Parameters(string i1, string i2)
{
//algum código...
}

Assim é possível executar qualquer método que esteja incluído na mesma classe independentemente dos seus parâmetros. Compactando mais o código fica apenas:

(new Thread((ThreadStart)delegate { threadWith2Parameters("texto 1", "texto 2"); })).Start();

Em ambientes WinForms é quase sempre preferível executar tarefas possivelmente demoradas em Thread's paralelas para evitar o congelamento da janela. Com este tipo de mecanismos evita-se que o código fique demasiado complexo. Imagine-se por exemplo um botão que executa um qualquer serviço remoto:

private void button1_Click(object sender, EventArgs e)
{
(new Thread((ThreadStart)delegate { listClients("sousa", "lisboa"); })).Start();
}
private void listClients(string name, string address)
{
this.BeginInvoke((MethodInvoker)delegate()
{
//método para bloquear controlos...
});
try
{
//algum código...
}
catch (Exception ex)
{
//tratar o erro...
}
finally
{
this.BeginInvoke((MethodInvoker)delegate()
{
//método para desbloquear controlos...
});
}
}

Existem por ai outras abordagens. Fica apenas mais uma.

sexta-feira, 16 de maio de 2008

Desenvolver software ou construir casas?

Diversas vezes que somos confrontados com esta questão:

    Porque razão desenvolver software não é um processo previsível e controlado como outras áreas de engenharia, como construção civil, por exemplo?

A resposta comum a esta questão passa normalmente por tentativas de mecanizar, burocratizar, medir, controlar o processo de desenvolvimento. Passa por adoptar metodologias monstruosas que acrescentam ao desenvolvimento uma quantidade de processos muitas vezes supérfluos e sem qualquer valor acrescentado. Na maior parte dos casos inclusive acabamos por nos esquecer que o principal resultado, aquele pelo qual o cliente paga que é:… código a funcionar. O principal produto num projecto de desenvolvimento de um portal, por exemplo, não é uma lista de casos de uso nem diagramas de sequência nem sequer gráficos de GANT! O principal produto é o portal a FUNCIONAR!

Ora o cenário comum é inundar as equipas de desenvolvimento com processos de qualidade burocráticos, numa tentativa de "controlar" e "tornar previsível" o processo de desenvolvimento. Em diversos casos que assisti até hoje, normalmente o resultado é… nenhum. O desenvolvimento é feito da mesma forma e no final do dia ou da semana (ou mesmo do projecto), os programadores vão consumir tempo e dinheiro a escrever documentação que não vai ter qualquer utilização que não seja mostrar nas auditorias.

Não quero com isto dizer que a construção de uma aplicação deva ser feita sem qualquer controlo, mas sim que a documentação a criar deve ser a necessária para ajudar no desenvolvimento do produto. Consumir tempo a criar diagramas de sequencia depois do software estar desenvolvido é apenas perda de tempo. Ou é feito antes do desenvolvimento no intuito de se perceber o que se vai fazer e encontrar a melhor forma de o fazer ou é simplesmente perda de tempo.

Analisando o outro lado (que conheço muito pouco), quando se desenvolve um projecto de construção, os arquitectos e engenheiros têm um determinado conhecimento sobre os materiais que vão ser utilizados, o seu comportamento, a sua utilização, a sua assemblagem. Agora pergunto: qual é o domínio de um arquitecto de software (quando existe um) ou um chefe de projecto sobre as linguagens, plataformas, componentes ou protocolos que vão ser utilizados? Já para não falar que nas engenharias tradicionais, tanto as matérias primas como produto final é quase sempre algo materializável, palpável. O desenvolvimento de software é um processo criado na totalidade sobre abstracção. Posso ter uma aplicação que tenha algumas funcionalidades, mas não deixa de ser uma abstracção, bem diferente de uma parede, uma janela ou uma casa. Quer queiramos ou não, o desenvolvimento de software é sempre muito mais complexo e dificilmente quem desenha ou planeia tem domínio suficiente sobre a sua construção para que consiga prever o resultado na sua totalidade. O arquitecto pode não saber como se coloca um parapeito numa janela, mas existe um conhecimento adquirido de que isso é possível e além do mais, os materiais são físicos e pouco mutáveis. Em último caso com mais umas pancadas e a coisa vai ao sítio. Do outro lado quando se planeia uma comunicação entre dois sistemas não existe domínio concreto sobre os problemas que vão existir em garantir a comunicação. Vão aparecer problemas de protocolos, autenticações, localização, etc… que podem ser resolvidos em muito pouco tempo ou podem gerar perdas de dias ou semanas. Tal como o arquitecto coloca uma janela algures numa parede, para quem planeia uma aplicação é simples desenhar num diagrama uma seta que significa uma comunicação entre dois sistemas, mas o conhecimento que os ambos têm sobre a implementação concreta, a complexidade ou os problemas que irão surgir a meio não é de todo comparável.

Então em que ficamos? Simplesmente são processos demasiado distintos para que devam ser comparados. Quando me colocam esta questão contraponho:

"Então as obras de engenharia civil nunca falham, nunca excedem orçamentos e estão sempre terminadas na data estipulada?"