segunda-feira, 21 de dezembro de 2009

Aplicação FindAndReplace

Devido a problemas de Acessibilidade Web encontrados num projecto recente desenvolvido em tecnologia Sharepoint, decidiu-se construir uma pequena aplicação com o objectivo de automatizar a localização e substituição de tags html obsoletas de acordo com as normas de acessibilidade a cumprir.

Estes atributos são gerados pelo Sharepoint, aquando a inserção/edição de conteúdos em controlos do tipo RichHtmlField.



Com este controlo, o utilizador tem a possibilidade de formatar o conteúdo que insere e, após a publicação da página, o html que é gerado pelo Sharepoint nem sempre cumpre as normas de acessibilidade estabelecidas pelo W3C, entidade que define as directivas para a acessibilidade do conteúdo da Web.

Neste caso específico, poderíamos, por exemplo, pesquisar num site (e nos seus sites “filhos”) de acordo com o URL que o utilizador indicar e substituir os parâmetros indicados em Localizar pelos de Substituir, como é ilustrado na imagem seguinte.




/******************************Abrir o site indicado no campo URL*******************************/

using (SPSite site = new SPSite(tbUrl.Text))
{
SPWeb web = null;
try
{
SPContext context = SPContext.GetContext(site.RootWeb);
SPSecurity.RunWithElevatedPrivileges(delegate()
{
web = context.Site.OpenWeb(tbUrl.Text);
});
Localizar(web);

}
finally
{
if (web != null)
web.Dispose();
}


/***********************Localizar o que está indicado no campo Localizar*********************/
private void Localizar(SPWeb web)
{
try
{
SPQuery query = new SPQuery();
//Pesquisa no Field CorpoArtigoGenerico substituindo os caracteres <> pelo seu valor hexadecimal
query.Query = "<Where><And><Contains><FieldRef Name='CorpoArtigoGenerico' /><Value Type='HTML'>" + tbLocalizar.Text.Replace("<", "&#60;").Replace(">", "&#62;") + @"</Value></Contains><IsNotNull><FieldRef Name='TituloArtigoGenerico'/></IsNotNull></And></Where>";
SPListItemCollection listItem = web.Lists["Páginas"].GetItems(query);
if (listItem.Count != 0)
{
Substituir(listItem, web);
}
//se nao retornar resultados ou não tiver encontrado paginas do tipo artigos genericos
else
{
MessageBox.Show("No site " + web.ToString() + " não foi encontrado o termo pesquisado");
}
}
catch
{
MessageBox.Show("Erro");
}

//para cada site filho vai ser feita a pesquisa e substituiçao
for (int i = 0; i < web.Webs.Count; ++i)
{
Localizar(web.Webs[i]);
}

}


Para essa substituição acontecer, são percorridos os passos normais de uma edição de página em Sharepoint: a saída da página, a entrada da página e a publicação da mesma.

/***Editar a página, substituir pelo termo indicado no campo Substituir e Publicar a página******/

private void Substituir(SPListItemCollection listItem, SPWeb web)
{

foreach (SPListItem li in listItem)
{
if (PublishingPage.IsPublishingPage(li))
{
PublishingPage page = PublishingPage.GetPublishingPage(li);
try
{
page.ListItem.File.CheckOut();
string corpoAntigo = page.ListItem["CorpoArtigoGenerico"].ToString();
string corpoNovo = corpoAntigo.Replace(tbLocalizar.Text, tbSubstituir.Text);
//faz a substituiçao do texto antigo pelo novo
page.ListItem["CorpoArtigoGenerico"] = corpoNovo;
//faz o update, checkin, publish e aprove da pagina
page.Update();
page.ListItem.File.CheckIn("Actualizado pela Aplicacao Find&Replace");
page.ListItem.File.Publish("Publicado pela Aplicacao Find&Replace");
page.ListItem.File.Approve("Aprovado pela Aplicacao Find&Replace");
}
catch
{
MessageBox.Show("Houve um problema na saida do ficheiro");
}

}
}
MessageBox.Show("No site " + web.ToString() + " foram feitas alteraçoes");
}


Mais uma vez, dando como exemplo este caso, estas substituições estavam restritas a campos específicos de determinados esquemas de página. Por exemplo, a pesquisa seria feita para encontrar/substituir os parâmetros em causa apenas no campo Descrição do esquema de página Artigo.

Em suma, esta aplicação está construída com um objectivo muito específico mas pode servir como base para uma ideia com os mesmos propósitos.

segunda-feira, 30 de novembro de 2009

Pesquisa em listas Sharepoint 2007

Ao longo do tempo que fui explorando o desenvolvimento de aplicações em Sharepoint 2007, conheci diversas formas de efectuar pesquisas sobre listas. Neste post faço a comparação entre quatro métodos de pesquisar informação em listas, com o objectivo de podermos tomar decisões informadas no desenvolvimento de soluções em Sharepoint 2007.

Para a elaboração deste post desenvolvi uma pequena aplicação que permite efectuar pedidos a páginas Web e que mede o tempo decorrido entre a execução do pedido e a recepção da resposta. Esta aplicação executa pedidos em paralelo durante um determinado período de tempo.

Para cada método de pesquisa foram feitos dois testes que descrevo de seguida, ambos num conjunto de 350 pedidos distribuídos por 3 minutos:

  • Uma lista de páginas preenchida com 100 itens;
  • Uma lista de páginas preenchida com 400 itens.

Note-se que neste post apenas me foco na pesquisa numa única lista. Numa segunda parte deste post irei comparar as pesquisas com os mesmos métodos em n listas de páginas pertencentes a diferentes sites de publicação.

De seguida apresento os quatro métodos de pesquisa utilizados nos testes, não demonstrarei a implementação destes visto que este assunto se encontra amplamente difundido na blogosfera.

  • Pesquisa com Foreach: pesquisa utilizando um ciclo Foreach percorrendo o object model do Sharepoint 2007.
  • Pesquisa com SPQuery: pesquisa utilizando o objecto SPQuery que permite executar a pesquisa numa lista.
  • Pesquisa com SPSiteDataQuery: pesquisa utilizando o objecto SPSiteDataQuery que permite pesquisar sobre várias listas em simultâneo.
  • Pesquisa com CrossListQueryInfo: pesquisa utilizando o objecto CrossListQueryInfo que permite executar pesquisas em várias listas em simultâneo e tirando partido de um mecanismo de cache de dados denominado de CrossListQueryCache. Este objecto permite ainda fazer aundience target dos resultados das pesquisas.

    Deixo ainda um post que explica o conceito de audience target: SharePoint Audience Targeting vs. Item Level Security

Foreach


Clique para aumentar

O gráfico apresenta os resultados dos testes referentes ao método de Foreach. Da análise destaca-se um considerável aumento do tempo de pesquisa com o aumento de itens na lista. Destaca-se ainda que em ambos os testes existe bastante oscilação de valores entre as diferentes pesquisas o que nos indica que é um método bastante irregular. Parece ainda que com o aumentar do número de itens esta irregularidade é mais acentuada.

SPQuery

Clique para aumentar

Este gráfico apresenta os resultados referentes ao método de pesquisa com o objecto SPQuery. As grandes diferenças que se apresentam em relação ao método anterior são: maior independência quanto ao número de itens da lista e um decréscimo do tempo médio das pesquisas.

SPSiteDataQuery

Clique para aumentar

O gráfico anterior mostra os resultados dos testes efectuados com o objecto SPSiteDataQuery. Na generalidade o resultado é semelhante ao método anterior, apesar de se notar que os tempos de pesquisa são mais constantes.

CrossListQueryInfo

Clique para aumentar

Por último apresento o resultado dos testes com o objecto CrossListQueryInfo. Este teste revela resultados bastante semelhantes aos resultados dos dois testes anteriores.

Comparação

Clique para aumentar

Em cima podemos observar de uma forma mais clara a média dos resultados dos diferentes métodos de pesquisa sob as mesmas condições. Em ambos se nota que o método de Foreach tende a ser o mais demorado e por isso deve ser evitado. Nos restantes casos a diferença de resultados é pouca, o que nos deixa com alguma margem de manobra na escolha do método de pesquisa a utilizar.

Na minha opinião devem-se utilizar os métodos nas circunstâncias para as quais foram desenvolvidos. Assim para uma pesquisa em apenas uma lista e sem contemplar audience targeting utilizaria o método da pesquisa com o objecto SPQuery.

Por último gostaria ainda de observar que também seria interessante de testar a memória e o tempo de processador que utiliza cada um dos métodos. Assunto que, com muita pena minha, não foi contemplado nos testes efectuados.

terça-feira, 22 de setembro de 2009

ExceptionHandling Application Block

Estive com uma equipa da PTSI, em Junho de 2007, a desenvolver serviços de negócio para um projecto interno, gerido e liderado pela Microsoft. Fomos incutidos a usar algumas soluções "state of the art". Uma das soluções usadas foi "ExceptionHandling Application Block".

O Enterprise Library Exception Handling Application Block permite criar uma estratégia coerente para o tratamento de excepções que ocorrem em todas as camadas de uma arquitectura de aplicativos.

Foi projectado para suportar código incluído nas declarações de capturas em componentes de aplicação. Em vez de repetir este código, como o registo de informações de excepção, por todos os blocos de catch idênticos em uma componente de aplicação, o bloco de aplicativo permite aos programadores encapsular esta lógica como manipuladores de excepção reutilizáveis. Manipuladores de excepção são classes .NET que encapsulam lógica de manipulação de excepção e implementam o Exception Handling Application Block interface chamado IExceptionHandler.

O Exception Handling Application Block inclui 4 manipuladores de excepção:
  • Wrap handler - Encapsula uma excepção em torno de outra.
  • Replace handler - substitui uma excepção com outra.
  • Logging handler - formata informação de excepção, tais como a mensagem. Em seguida, o Logging handler dá essa informação para o Enterprise Library Logging Application Block para que seja publicada.
  • Fault Contract Exception Handler - para uso em Windows Communication Foundation (WCF), e gera um novo contrato de falha da excepção.

Exemplo de Código de Aplicação
O código mostra como executar a política chamada "Data Access Policy" quando ocorre uma excepção.
[C #]

try

{

// Run code.

}

catch(Exception ex)

{

bool rethrow = ExceptionPolicy.HandleException(ex, " Data Access Policy");

if (rethrow)

throw;

}


Definições necessárias no Config

Definir uma Exception Policy no web.config

(...)

<exceptionHandling>

<exceptionPolicies>

<add name="Exception Policy">

(...)

Associar um tipo de Excepção para a Exception Policy

(...)

<add name="Exception Policy">

<exceptionTypes>

<add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"postHandlingAction="NotifyRethrow" name="Exception">

(...)

Associar o Exception Handler ao tipo de Excepção da Exception Policy

(...)

<exceptionHandlers>

<add exceptionMessage="Replaced Exception"exceptionMessageResourceType=""replaceExceptionType="System.ApplicationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" name="Replace Handler" />

</exceptionHandlers>

</add>

</exceptionTypes>

</add>

</exceptionPolicies>

</exceptionHandling>

(...)

</configuration>

domingo, 31 de maio de 2009

Tabelas vs Div’s e Css – Em busca do layout perfeito



No início da Internet as páginas eram constituídas, praticamente, apenas por uma amalgama de texto e imagens. A maior parte dessas páginas tinha como objectivo a troca de informação nos mundos académico, militar e de investigação científica, não necessitando de grandes cuidados visuais.
Mas, principalmente com o aparecimento das primeiras possibilidades de negócio online, tornou-se necessário arranjar uma forma de conseguir apresentar a informação de uma forma mais ordenada e agradável ao visitante.

A primeira forma encontrada para este propósito foi a nossa conhecida tabela, que permite apresentar dados de forma tabular e, ao aparecer a propriedade border = 0, tornou-se possível organizar a informação sem que o visitante visse a inestética estrutura da tabela.
Contudo, embora ainda hoje em dia as tabelas sejam de grande utilidade, é certo que trazem também algumas complicações a quem desenvolve qualquer tipo de aplicação web. Os principais problemas ao utilizar tabelas para construir o layout de um site resumem-se, em termos gerais, aos seguintes pontos:
  • mistura dos dados de apresentação (ou seja, a estrutura da tabela, tamanhos, cores, etc) com o conteúdo (texto, imagens, etc), o que leva ao aumento desnecessário do tamanho do ficheiro que representa a página;

  • a largura de banda não é grátis, tanto para o visitante como para o dono do site, e visto que os ficheiros têm um tamanho maior devido aos dados de apresentação, verifica-se um aumento na largura de banda consumida sempre que um visitante visualiza uma página;

  • o acesso a utilizadores de PDA’s e telemóveis torna-se mais complicado devido à necessidade de maior largura de banda e aos browsers existentes para esses dispositivos;

  • embora seja possível definir informação sobre o conteúdo nos cabeçalhos das tabelas, a acessibilidade para utilizadores com dificuldades torna-se complicada caso existam várias tabelas dentro de outras tabelas;

  • torna-se mais complicado de manter constante o aspecto visual em todo o site;

  • o redesign de um site torna-se muito mais complicado e moroso.

Mesmo com tantos pontos negativos as tabelas continuam a ser largamente usadas por toda a Internet, porquê?
Bem, principalmente devido a dois pontos:
  • são simples de usar, o que serve de apoio para muitos utilizadores que pretendem criar uma página web e não têm conhecimentos aprofundados sobre o assunto;

  • devido aos diferentes métodos de renderização ainda existentes entre os diversos browsers, o que pode provocar alguma inconsistência visual num site.

Afinal se utilizar tabelas para criar o layout de um site é assim tão mau, qual é a solução para esse problema?


A solução para o problema passa pela utilização de Cascading Style Sheets (CSS) em conjunto com div’s.

Nota:
CSS representa todas as regras de apresentação que são utilizadas numa página ou site, onde é possível definir desde a cor da letra até à largura de um div.
div representa uma divisão numa página, podendo esta ser apresentada de diversas formas na página: ocupar um bloco que a toda a largura da página, flutuar à esquerda, flutuar à direita, ocupar apenas o espaço necessário para apresentar a informação contida, etc.

Como os browsers modernos são muito melhores a fazer a renderização de páginas web do que os existentes na altura em que se começaram a utilizar tabelas, podemos recorrer a esta solução tendo em especial atenção a criação de um ficheiro CSS geral para todo o site e a atribuição de nomes (identificadores) sugestivos para os diferentes div’s que irão fornecer o pretendido aspecto "tabular” da página.

A solução CSS + div dá-nos então alguns aspectos superiores à solução com tabelas:
  • devido à separação dos dados de apresentação (presentes no ficheiro CSS) do conteúdo da página, a largura de banda consumida será menor, sendo apenas necessário carregar os dados de apresentação na primeira visualização de uma página do site. Como esses dados serão utilizados ao longo de todo o site, e devido ao sistema de cache do browser, não será necessário fazer o download de todos os dados de apresentação sempre que se visualiza uma nova página;

  • o ficheiro CSS único oferece-nos a possibilidade de realizar um redesign de forma muito mais rápida e automaticamente extensível a todas as zonas do site que utilizem as regras alteradas, não sendo necessário editar página a página;

  • o aspecto visual em todo o site torna-se constante, desde que os dados de apresentação presentes no ficheiro CSS sejam utilizados correctamente;

  • os nomes sugestivos dos div’s oferecem-nos não só a possibilidade de criar uma regra de estilo específica para esse div, como também uma maior facilidade em perceber que dados serão apresentados no seu interior, melhorando assim a acessibilidade do site para utilizadores com dificuldades;

  • embora nem todos os browsers apresentem os div’s, da mesma maneira, é possível minimizar as inconsistências visuais através da utilização de um div extra que realiza um "reset" às formatações no sítio onde este se encontra.

Parece-me bem, mas soa a algo complicado de fazer...


Parece complicado, mas na realidade não o é. Após algumas edições este processo torna-se algo natural de fazer.
É natural também que existam ainda algumas situações em que seja necessário recorrer a uma tabela para apresentar alguns dados, mas estas deverão ser usadas apenas para o seu propósito - apresentação de dados de maneira tabular - e não para criação de layouts completos.
Caso existam algumas dúvidas sobre como começar, não há nada como uma boa pesquisa na Internet para as desfazer. Existem vários sites que referem métodos para se construir um layout com um aspecto sólido utilizando apenas CSS e div’s, merecendo o artigo de Matthew James Taylor um destaque especial.

terça-feira, 26 de maio de 2009

Application Compatibility Toolkit 5.5



Esta aplicação tem como finalidade ajudar a perceber quais as possíveis incompatibilidades que possam ocorrer aquando a instalação de um novo sistema operativo, ou uma actualização do mesmo ou até mesmo na instalação de uma nova actualização do Internet Explorer. É produzido um relatório com as anomalias encontradas que permite, após devida análise, conceber um plano com possíveis soluções para as resolver e posteriormente criar pacotes de mitigação que, ao serem aplicados e quando possível, resolvem os problemas encontrados.
Este processo é executado por três fases utilizando a arquitectura resultante da instalação do ACT:

Fase 1 – Inventariar informação

Antes da análise dos potenciais problemas de compatibilidade, primeiro tem de ser coleccionar a informação de toda a organização. Para tal utiliza-se a ferramenta Application Compatibility Manager (ACM) que permite que se configure, coleccione, organize e analise a compatibilidade dos dados. A forma de comunicação de toda a organização para recolha e armazenamento da informação relevante a problemas de compatibilidade é uma pasta partilhada que funciona como um registo (Log Processing Service – LPS), colocando depois esta informação numa base de dados, criada no processo de configuração do ACM, especialmente para esta aplicação. É a esta base de dados que o ACM acede e que tem toda a informação de toda a organização.


Fase 2 – Analisar problemas

Depois de inventariados os dados da organização é altura de analisá-los. Isto inclui categorizá-los e organizá-los de forma a proporcionar uma leitura mais fácil de toda a informação que está disponibilizada no ACM após colecção dos dados. Além desta opção, existe também hipótese de utilização de três ferramentas mais específicas para pesquisa de incompatibilidades:

Internet Explorer Compatibility Test Tool (IECT) – Permite que se coleccione as incompatibilidades em Web Sites e Aplicações Web e mostra os resultados em tempo real no Internet Explorer 7.

Setup Analysis Tool (SAT) – Permite que se detecte problemas que possam ocorrer durante uma instalação e configuração de uma aplicação.

Standard User Analyzer (SUA) – Permite que se detecte problemas que possam ocorrer em aplicações a funcionar em ambientes de Standard User, ou seja, quando os utilizadores comuns não são administradores.

Fase 3 – Testes e Mitigações

Por último, depois de testados todos os problemas encontrados, existe a possibilidade de se criarem pacotes de mitigação que posteriormente serão instalados para resolução das incompatibilidades. Para tal, utilizam-se as opções que existem em cada ferramenta de análise (IECT, SAT ou SUA) ou utiliza-se o Compatibility Administrator que nos dá a possibilidade de criar um pacote de mitigação personalizado, escolhendo que tipo de problema queremos resolver e como.

Ex. Se houver uma aplicação que não funcione devidamente se o utilizador não for administrador podemos criar um pacote de mitigação que aplique uma regra de que sejam elevadas as permissões deste utilizador naquela aplicação.



This application helps you to understand which could be your compatibility issues during an installation of a new operating system, an operating system update, or even an Internet Explorer update. It creates a report with the issues found and then, after analyze it, design a plan with possible solutions to posteriorly create mitigation packages to fix this compatibility issues.

There are three steps to execute this process using the resulting architecture from the ACT installation:

Phase 1 – Collecting Data

Before analyse potencialy compatibility problems, first collect your organization's inventory and the associated compatibility issues. For that, use the tool Application Compatibility Manager (ACM) that enables you to configure, to collect, and to analyze your data so you can fix any issues. The way that all organization communicates and share information about compatibility data is a shared folder that works like a log file (Log Processing Service – LPS), placing then this information inside a database, created during the ACM’s configuration process exclusively for this application. That is the database that ACM’s access in order to have all information about all organization.

Phase 2 – Analyzing Issues

After collecting your inventory and associated compatibility data, you can organize and analyze your issues. Besides this option, you can also use three tools more specific to search for incompatibilities:

Internet Explorer Compatibility Test Tool (IECT) – Enables you to collect, in real-time, the potential Web site and Web application issues that might occur due to running Web sites and Web applications in Internet Explorer 7

Setup Analysis Tool (SAT) – Enables you to detect problems that might occur during an application’s installation and configuration.

Standard User Analyzer (SUA) – Enables you to detect problems that might occur in applications running on standard user environments, i.e., when the common user it’s not an administrator.

Phase 3 – Testing and Mitigating Issues

After analyzing your compatibility issue reports you can create mitigation packages to fix the issues. For that you can use Compatibility Administrator or the other tools, provided with ACT, including the IECT, the SAT, and the SUA tool, to determine additional issues and possible mitigation strategies.

Ex. If there is an application that doesn’t work correctly because the user must be an administrator you can create a mitigation package that applies a rule that elevates permission to this user in that application.

sexta-feira, 22 de maio de 2009

httpModules e httpHandlers (ashx)

Na última semana o ISEL esteve nas instalações da Simple Solutions a dar uma formação avançada em desenvolvimento Asp.Net. Um dos objectivos era perceber a sequência de geração de eventos no HTTP Pipeline, para a construção de páginas aspx. Identificámos os eventos que mais se adequam a cada situação e a forma correcta de os utilizar, diminuindo por exemplo, o efeito do ViewState.

Dois dos assuntos de que falámos foram os httpModules e httpHandlers. Deixo aqui uma pequena descrição da sua implementação e em que situações devem ser utilizados.

httpModules

A utilizar em situações que queiramos um controlo de entrada ou saída sobre todos os pedidos na aplicação. Exemplos: cifrar a query string, verificar permissões de acessos a recursos (pode entrar na página?).

Implementação:

Registar no Web.config
<system.web>
<httpModules>
<add type="Isel.Handler.RequestTimeModule" name="RequestTimeModule"/>
</httpModules>
</system.web>
Criar uma classe que implementa a interface IHttpModule
namespace Empresa.Aplicacao {
public class RequestTimeModule: IHttpModule {
No evento Init registar os eventos que querem utilizar
public void Init(HttpApplication context) {
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
Implementar o código nos eventos registados
void context_BeginRequest(object sender, EventArgs e) {
HttpContext.Current.Items["start"] = DateTime.Now;
}

void context_EndRequest(object sender, EventArgs e) {
if (HttpContext.Current.Response.ContentType == "text/html") {
HttpContext.Current.Response.Write("<p>" + (DateTime.Now -Convert.ToDateTime(HttpContext.Current.Items["start"])) + "</p>");
}
}

httpHandlers (ashx)

A utilizar sempre que quisermos gerar informação a partir da aplicação sem passar por todo o processamento de uma página. Exemplos: gerar imagens a partir da BD, exportação de informação para ficheiros Excel ou XML.

Implementação:

Não é necessário registar nada no Web.config porque o handler ashx já vem de raiz com a plataforma.

Criar uma classe que implementa a interface IHttpModule. No caso de ser necessário acesso à Session, implementar também IRequiresSessionState.
namespace Empresa.Aplicacao.Handler {
public class Exportar : IHttpHandler, IRequiresSessionState {
Definir o evento IsReusable
public bool IsReusable {
get { return true; }
}
Implementar o código no evento ProcessRequest
public void ProcessRequest(HttpContext context) {
try {
string userName = context.User.Identity.Name;
if (userName != null && userName != "") {

string titulo = "";
if (context.Session["ExportarTitulo"] != null && context.Session["ExportarTitulo"].ToString() != "")
titulo = context.Session["ExportarTitulo"].ToString();

if (context.Session["ExportarParametros"] != null & context.Session["ExportarSP"] != null && context.Session["ExportarSP"].ToString() != "") {

context.Response.ContentType = "application/vnd.ms-excel";
context.Response.AddHeader("content-disposition", "attachment;filename=" + titulo + ".xls");
context.Response.Charset = "utf-8";

Regras.Entidade obj = new Regras.Entidade(null, origemErro, userName);
DataSet dSet = obj.Selecciona(context.Session["ExportarSP"].ToString(),
(Regras.Parametro[])context.Session["ExportarParametros"]);

GridView gridLista = new GridView();
gridLista.DataSource = dSet.Tables[0];
gridLista.DataBind();

System.Web.UI.HtmlTextWriter html = new System.Web.UI.HtmlTextWriter(context.Response.Output);

gridLista.RenderControl(html);
}
}
}
catch (Exception ex) {
context.Response.Redirect(ConfigurationManager.AppSettings["NomeApp"] + "Erro.aspx?erro=" + ex.Message);
}
}
Podemos inclusive fazer o override ao comportamento de qualquer tipo de recurso numa aplicação Web.
<httpHandlers>
<add verb="*" path="*.jpg" type="Empresa.Aplicacao.Imagem"/>
</httpHandlers>
Neste caso todos os ficheiros JPEG pedidos à aplicação passam pelo ProcessRequest do tipo “Empresa.Aplicacao.Imagem”.

quarta-feira, 22 de abril de 2009

Scrum ? O prazer de planear, gerir e executar …

Scrum é um processo interactivo e incremental para o desenvolvimento de produtos ou para a gestão de tarefas. A agilidade que suporta esta metodologia de gestão e planeamento, traz uma nova dimensão na capacidade de resposta, adequabilidade, eficácia e eficiência na gestão actual dos processos.” – by http://scrumpt.com/

Quando leio esta definição, questiono-me “ - Como é que eu poderia pensar o quão bom e inovador era abrir o Visio, fazer uns desenhos… Abrir o Project, definir umas tarefas, atribui-las… e fazer umas reuniões mensais?”. Hoje vejo, que tal pensamento se enquadra fora da realidade do que pode e deve ser uma gestão completa e eficiente de um projecto de software.
Mas comecemos do início. Longe vão os tempos em que me sentava numa cadeira na faculdade para ouvir os professores falarem (e quando o assunto era análise de sistemas) do UML, que primeiro era preciso analisar e só depois desenvolver. Sempre fui dessa opinião também, e ainda hoje acredito que é preferível gastar ¾ do tempo a planear e o resto a desenvolver. Isto porque, nunca é demais conhecer o sistema que estamos a desenvolver, conhecer o problema que temos entre mãos. Até aqui a teoria encaixava na perfeição, o pior estava para vir com a prática.

Com o entrar na vida profissional, constato que as coisas nem sempre acontecem como se espera, ou melhor, quase nunca. E hoje que escrevo este artigo, vem-me á memória o último projecto de grandes dimensões em que entrei. Um projecto grande no inicio que se transformou em megalómano. Um cliente exigente, que coloca vários desafios, propõe várias funcionalidades a cada reunião realizada e o sistema dispara. Cada vez que achávamos que tínhamos os requisitos prontos, vinha o cliente e dizia “ – Falta isto. - Era bom que o sistema fizesse isto. “ Chegámos a uma fase que estávamos a desenvolver em velocidade cruzeiro e o levantamento de requisitos ainda não tinha terminado. Situação impensável, cria-se um desgaste na relação cliente/equipa de desenvolvimento, sucedem-se reuniões atrás de reuniões, a maior parte delas inconclusivas e improdutivas. Conclusão, o sistema vai atrasando.

- Para onde caminhar?”, é esta a questão que se coloca perante este cenário. Após algum tempo investido da minha parte em alguns produtos e soluções, há um que se destaca… Scrum. “- Será a solução? “. O Scrum é um processo que nos ajuda a gerir projectos de uma forma hábil. Os seus primórdios tiveram origem no sector automóvel, onde equipas pequenas e multidisciplinares conseguiam melhores resultados. Em 1995, um senhor chamado Ken Schwaber implementa e adapta este mecanismo em desenvolvimento de software. A indústria de software aceita muito bem esta metodologia. “- E porquê?”. Digamos que, de entre os vários interesses que a plataforma despertou, destaco o facto de podermos estimular e intensificar o contacto cliente/equipa de desenvolvimento, através da interrupção do projecto em períodos regulares de tempo. A estas acções dá-se o nome de Sprint. No fim de cada acção o cliente recebe as funcionalidades desenvolvidas, comprometendo-se a utilizá-las, a testá-las, apontando as qualidades assim como os defeitos.

A participação activa por parte do cliente torna-o não um mero comprador de software, mas sim um elo importante no desenvolvimento de todo o sistema, na criação do produto, contribuindo na pesquisa de requisitos, na análise, na formalização de tempos, na execução, nos testes, etc, responsabilizando-o durante todo o processo.

Alguns motivos que justificam a implementação desta prática:

· As mudanças são bem vindas e não alteram a produtividade;
· O cliente participa nas reuniões e vê o produto (sistema) a ser construído;
· A equipa produz o que foi previsto e pode ir acompanhando os resultados diariamente;
· A equipa determina a complexidade da “funcionalidade” e a mesma é debatida até que todos tenham “entendido”, com a participação do cliente;
· Todos os envolvidos conhecem o que deve ser feito e todos contribuem;
· A equipa trabalha em colaboração;
· Maior comprometimento da equipa;
· Mais tempo para o Scrum Master (Gestor de Projecto) concentrar sua atenção no que realmente interessa e não apenas em relatórios;
· A equipa consegue trabalhar e concentrar esforços no que é realmente importante no momento;

Enumeremos alguns conceitos úteis:

Entidades

· Cliente ou PO (product owner)- define as funcionalidades do produto, datas de lançamento e conteúdo, faz ajustes de funcionalidade e prioridade e aceita ou rejeita resultados obtidos;
· ScrumMaster ou Gestor de Projecto – representa a entidade responsável para o projecto, responsável pela aplicação dos valores e pelas práticas do Scrum, garante produtividade e funcionalidade da equipa e serve como filtro de interferências externas;
· Equipa de Desenvolvimento – trabalha de maneira auto-organizável, em grupos de 5 a 9 pessoas, é multifuncional (programadores, testers, designers, etc.) e só pode trocar de equipa no próximo Sprint;

Itens

· Product backlog – é o que deseja desenvolver-se no projecto, é uma lista que estabelece as actividades de acordo com a vontade do cliente;
· Sprint backlog – é o que será desenvolvido, conjunto de tarefas organizado temporariamente, com cronograma e tempo de execução;
· Burndown charts – é o gráfico de andamento do Sprint, relacionando horas e data em relação ao restante de tempo hábil para o término do ciclo;

Metodologia

· Planeamento – a equipa selecciona os itens do Product Backlog que irá comprometidamente executar; cria-se o Sprint Backlog, tarefas são identificadas e o tempo é estimado (1 a 16 horas);
· Revisão – a equipa demonstra o que foi realizado durante o Sprint. Geralmente, trata-se de uma reunião informal para abordar novas funcionalidades e estrutura do projecto;
· Retrospectiva – é realizada após cada Sprint e tem como objectivo ver o que funciona e o que não funciona. Toda a equipa participa na retrospectiva, inclusive o cliente;
· Reunião diária – são tipicamente rápidas, realizadas em pé e duram cerca de 15 ou 30 minutos. Assim, mantém-se o foco no que está a ser desenvolvido.

sexta-feira, 20 de março de 2009

Microsoft Commerce Server 2007

Aproveitando a experiência adquirida no projecto que tenho estado a desenvolver e numa formação, gostaria de falar um pouco sobre o Microsoft Commerce Server 2007 (CS). Um pouco em jeito de apresentação, trata-se de uma ferramenta para construir um negócio on-line e poderá ser uma solução a levar em conta ao avaliar os pedidos dos nossos clientes.
O CS disponibiliza uma boa base para criarmos o nosso código através de uma vasta API, mas destaca-se no aspecto de colocar nas mãos do cliente a gestão de produtos, encomendas, inventário, perfis de utilizadores e campanhas de marketing no site.
A instalação do CS inclui 4 aplicações de backoffice para gestão das várias componentes do negócio: Catalog Manager, Catalog and Inventory Schema Manager, Customer and Orders Manager e Marketing Manager.

Catálogo
O cliente pode criar e manter o seu catálogo de produtos. O catálogo é constituído por categorias de produtos e produtos. As categorias e produtos têm as suas propriedades base (nome, descrição, preço, etc), mas facilmente podem ser acrescentadas novas propriedades do tipo texto, númerico, opcional, etc. Por exemplo, criar um campo para as várias cores disponíveis de um produto. Também é possível relacionar categorias ou produtos entre si, facilitando a implementação daquilo que se vê em sites de vendas em que podemos ver os produtos parecidos ou do mesmo tipo do produto que estamos a ver. O catálogo facilita o uso de diferentes línguas e moedas.

Perfis
Podemos criar perfis de utilizadores e tornar a experiência de navegação mais personalizada. Com base no padrão de navegação e de cliques, poderá ser dirigida a atenção do user para uma campanha promocional ou fazer aparecer um determinado banner. Por exemplo, se o user é do sexo masculino então poderá aplicar-se um desconto nos casacos para homens.

Inventário
Permite gerir os stocks dos produtos, estabelecer quantidades disponíveis, pesquisar os itens esgotados, definir se um produto pode ser reservado, para dar alguns exemplos.

Marketing
Permite criar banners, campanhas e descontos. Por exemplo, definir em que situações um banner deverá aparecer quer seja com base no horário, perfil ou categorias de produtos. Ou então criar códigos de desconto para ser aplicado na compra de um produto ou aplicado ao total de uma compra. O código poderá ter algumas regras como um tempo de expiração ao fim do qual deixará de ter validade. O CS dispõe também de um Direct Mailer para envio de mails para campanhas publicitárias aos clientes registados da loja.

Encomendas
Esta componente faz a gestão dos vários carrinhos de compras, os que foram criados, abandonados ou que se traduziram em compras feitas. O CS está preparado para disponibilizar vários tipos de pagamento e apresenta algumas soluções de segurança para gerir números de cartões de crédito. Apresenta também soluções para vários cenários. Por exemplo, numa loja um cliente adiciona ao seu basket canetas e papel. Quando faz checkout, internamente é criado um novo basket com o pedido de papel para ser processado por uma outra loja que vende o papel. Também são usados pipelines, que são uma espécie de filtragem de produtos, ao qual é possível introduzirmos algumas regras. Por exemplo, podemos através dos pipelines prevenir que o user adicione mais que 10 produtos só de uma vez. Essa limitação é imediatamente aplicada ao site sem qualquer alteração ao code-behind da página.

No projecto em que estive a trabalhar não foi possível explorar todas as capacidades do CS, nem parece razoável que uma só aplicação venha a usar todas elas. Mas é bastante abrangente para poder apresentar várias soluções no âmbito do comércio on-line. Mesmo no caso de tratar-se de um pequeno negócio o CS poderá ser uma ajuda no seu crescimento.
A instalação do CS é bastante morosa pois implica a criação de vários web services, cada um para as várias componentes. Além disso, por motivos de segurança a Microsoft recomenda a criação de um user diferente para cada ws. Acrescentado a isso, temos de criar as permissões desses users em vários ficheiros, pastas e base de dados. Para integrar com o Sharepoint são precisas mais algumas configurações.
Estão disponíveis as seguintes edições: Standard, Enterprise e Developer. A diferença está no número de sites e servidores que são suportados.

Alguns sites que usam o CS2007:
http://www.nike.com
www.roxy-europe.com
http://www.booksdirect.co.uk
http://www.quiksilver-store.com/
www.harrods.com

quinta-feira, 29 de janeiro de 2009

Ergonomia

Criar um site para a Web ou desenvolver qualquer outro tipo de aplicação envolve, acima de tudo, uma boa organização dentro da equipa de concepção. Este conceito aplica-se de duas formas: do programador para o utilizador e do programador para a sua equipa.

Como utilizadores regulares da Internet, todos sabemos como é fácil existir redundância de informação, pouca clareza na navegação, longos tempos de espera, inconsistência do ponto de vista gráfico, entre outras contrariedades que, com o pouco tempo do dia-a-dia, nos faz fechar a janela e procurar outra alternativa, tendo em conta que existem actualmente mais de mil milhões de páginas na internet.

Visto isto, é essencial tirar partido do nosso próprio usufruto da Web e pensar no utilizador final e na forma como este vai interagir com o produto. Há que ter em consideração:

Usabilidade – A utilização da aplicação deve ser o mais amigável possível de forma a entender-se rapidamente como usá-la.
Navegabilidade – A partir de uma boa estrutura hierárquica da aplicação deve pensar-se na navegação na tentativa de ser lógica, intuitiva, clara e não redundante.
Simplicidade – Manter a aplicação simples. Demasiada informação ou informação repetida torna-se inconsistente para o utilizador e desvia a sua atenção do que é essencial reter.
Consistência – Criar uma aparência consistente, sem utilizar muitos tipos de fontes, muitas cores que não se conjuguem nem se relacionem com a informação a ser passada.

Como programadores, acontece regularmente haver a necessidade de se modificar linhas de código realizadas por outro programador. Quando estamos a falar em grandes projectos, é fácil perdermo-nos naquela que será a organização de outra pessoa.

Como tal, o ideal é estandardizar o mais possível o desenvolvimento de um projecto elaborado em equipa. Para isso é essencial ter em conta algumas situações:

Nomenclatura – É conveniente ter alguma atenção aos nomes de variáveis, métodos, classes, funções, etc. Devem ser coerentes e facilmente identificáveis com a informação que disponibilizam. É também importante que a escrita seja igual em toda a aplicação, como por exemplo utilizar só letras minúsculas ou o identificador de um controlo começar pelo diminutivo do tipo de controlo (Ex: btnClicar, em que o controlo é um botão)
Formatação – Para uma mais fácil formatação de tabelas ou controlos utilizam-se folhas de estilo em cascata, CSS. Estas permitem controlar tamanhos, espaçamentos, cores entre outras propriedades. A utilização de CSS leva a uma diminuição de propriedades atribuídas directamente aos controlos e abre a possibilidade da reutilização do mesmo estilo em todo o site tornando-o assim mais consistente.
Comentário – Nas situações de menor evidência do resultado de uma parte do código é fundamental colocar comentários que permitam uma maior clareza do funcionamento do mesmo.
Funcionalidade – Para existir funcionalidade é indispensável reduzir a redundância. Se um excerto de código vai ser reutilizado mais vezes ao longo do projecto então será mais fácil desenvolver um método ou uma função que depois seja chamada ao longo do projecto ao invés de repetir as mesmas instruções várias vezes.

Nem sempre se consegue cumprir todas estas regras, e tantas outras, à risca. Mas se no desenvolvimento de software tivermos em conta que também poderemos ser nós utilizadores da aplicação ou programadores da equipa que está sujeita a proceder a alterações no projecto torna-se mais fácil entender o quão essencial é cumpri-las.

quinta-feira, 1 de janeiro de 2009

Videos de formação para Aspx, Ajax e MOSS

Quem já não sentiu que é cada vez menor o tempo disponível, para acompanhar os novos produtos e soluções que emergem no mercado, inclusive os directamente relacionados com o nosso negócio. O que na maior das vezes leva-nos a tomar decisões erradas relativas à sua correcta utilização.

Quantas vezes, demos por nós sem tempo para podermos apoiar da melhor forma, os novos elementos da equipa. Algo que a médio prazo pode trazer problemas sérios, sem contar com a produtividade, que nunca consegue atingir o nível ideal.

Existe sempre a solução de formações pós-laborais, mas para além de serem dispendiosas, trazem uma sobrecarga adicional aos colaboradores. Sendo que muitas delas, principalmente as baseadas em tecnologias recentes no mercado Português, não passam de um debitar de informação do manual, sem nenhuma mais valia em termos de experiências do formador.

Como o nosso país ainda tem um pequeno gap (e ainda bem) na adopção das últimas tecnologias, existe uma solução que temos adoptado com cada vez maior frequência – Vídeos de formação – apresentados por alguém com experiência comprovada nos produtos que está a apresentar. Acabam por ser sessões explicativas relativamente curtas mas que focam os pontos essenciais.

Deixo aqui uma referência para um site que tem alguns excelentes vídeos de formação em tecnologia Microsoft, www.traincert.net. Tem inclusive alguns vídeos de oferta muito interessantes. Se quiser fazer o download de todos os restantes vídeos, o custo é de 19 dólares.

Deixo aqui uma lista resumida dos vídeos (existe também uma enorme lista para os interessados em DotNetNuke):

SharePoint 2007 Developer Vídeos
SharePoint #1 : Developing WebParts (24:15)
SharePoint #2 : Developing Features (29:55)
SharePoint #3 : Application Pages (13:47)
SharePoint #4 : Feature Receivers (10:55)
SharePoint #5 : Ajaxified WebParts with Gaia (33:13)

Various New TrainCert.NET Videos
Ajax : Getting Started with Ajax on ASP.NET (30:37)
Ajax : Intro to Gaia Ajax Widgets for ASP.NET (27:40)
Ajax : SharePoint 2007 Ajax WebParts (33:13)

ASP.NET 2.0
ASP.NET 2.0: Data Access (30:18)
ASP.NET 2.0: Data Access (25:49)
ASP.NET 2.0: Master Pages (7:46)
ASP.NET 2.0: Skins and Themes (5:13)
ASP.NET 2.0: Profiles (6:44)
ASP.NET 2.0: Localization (11:6)
ASP.NET 2.0: Site Navigation (11:29)

C# 2.0 Language Enhancements
C# 2.0 : Generics (21:0)
C# 2.0 : Anonymous methods (9:45)
C# 2.0 : Partial Types (9:48)
C# 2.0 : Iterators (9:47)
C# 2.0 : Minor enhancements (12:43)

Visual Studio 2005 IDE enhancements
VS.NET 2005 : Class Designer (16:44)
VS.NET 2005 : Snippets & Intellisense (15:10)
VS.NET 2005 : New debugger features (11:3)
VS.NET 2005 : Refactoring (13:58)

VB.NET 2.0 Enhancements
VB.NET 2005 : IDE Enhancements (12:40)
VB.NET 2005 : Language Enhancements (12:5)
VB.NET 2005 : My Namespace (10:48)

Microsoft Search Server 2008

Um produto muito interessante que tem passado um pouco ao lado do mercado português. Este Search Server 2008 tem tudo para resultar nos projectos que vamos implementando.

Quem não se lembra de usar soluções CMS com Sharepoint 2003, apenas porque tinha necessidade de criar uma pesquisa sobre os conteúdos criados. Este novo produto vem resolver isso mesmo, ou seja, reutilizaram a funcionalidade de pesquisa do Sharepoint numa solução bastante light. Ainda por cima a versão base não tem quaisquer custos associados.

Este software funciona com uma série de fontes:
• Partilha de ficheiros
• Bases de dados Lotus Notes
• Motores de pesquisa como a Wikipedia
• Existem conectores para FileNET
• E claro, tudo o que criares nos teus sites. Inclusive conteúdos de ficheiros

Ainda tem que ser submetido à prova mas parece que a Microsoft acertou mais uma vez no caminho certo!

Deixo aqui alguns links onde podem retirar mais informação:
http://www.microsoft.com/EnterpriseSearch/
http://www.microsoft.com/enterprisesearch/flash/MSSX.html

Alguns cuidados a ter com a performance de websites

Um assunto já amplamente discutido tem a ver com a optimização da performance das aplicações ASP.Net. Ninguém pode descurar a definição de regras básicas tendo em vista o melhor funcionamento das suas aplicações.

Principalmente na fase inicial de cada projecto, devem ser adoptadas soluções adequadas aos seus requisitos, de modo a que não hajam desagradáveis surpresas numa fase mais avançada, o que na maior parte dos casos vai acarretar a custos não previstos e elevados.

Um dos grandes objectivos deste blog é dar conhecimento de algumas formas e soluções para optimizar a performance das aplicações Web. Começo por deixar aqui alguns conselhos, já antigos, mas que nunca devem ser esquecidos.

1. Evitar idas desnecessárias ao servidor
Sempre que possível utilizar Javascript para controlar o aspecto e funcionalidade das páginas. É impressionante o número de aplicações que fazem uma ida ao servidor apenas para mostrar um controlo, ou fazer pequenas validações, obrigando a reconstruir toda a página.

Utilizar o “Page.IsPostBack” no load das páginas para evitar processamento desnecessário.

Se ainda não usas metodologia Ajax, deves começar o mais rápido possível. Além do melhor aspecto funcional das aplicações, evita em muito, a sobrecarga de trabalho e informação que é gerada para cada construção integral da página.

2. Usar o viewstate apenas quando necessário
Apesar de muito simpático, facilmente podemos perder o controlo do viewstate. Basta olhar para o html gerado daquelas páginas mais pesadas, principalmente as que fazem uso de datagrids ou repeaters, para ver aumentar exponencialmente o tamanho da nossa página.

Por defeito está activo, mas caso não precisemos dele, podemos sempre desactivá-lo das seguintes formas:
• Ao nível do controlo – colocar a propriedade EnableViewState=”false”
• Ao nível da página – colocar a directiva de página EnableViewState=”false”
• Ao nível da aplicação – colocar no Web.config a chave

3. Não usar excepções para fazer validações
Este tipo de código pode trazer complicações ao servidor, basta fazer um pequeno debug e ver o tempo que ele demora a gerar a excepção.

public bool IsNumeric(string val) {
  try {
    int number = int.Parse(val);
    return true;
  }
  catch {
    return false;
  }
}

4. E antes de colocar em produtivo…
Tirar o trace e o debug. Por incrível que pareça, é tão fácil de esquecer que já vi bastantes aplicações em produtivo com estas chaves activas.

No Web.config coloca:
<configuration>
<system.web>
<trace enabled="false" pageOutput="false" />
<compilation debug="false" />
</system.web>
</configuration>

Javascript: Activar o Debug no lado do cliente

Não sei porquê, mas continua a passar ao lado de muitos programadores a possibilidade que têm de fazer debug em javascript, no Visual Studio.

Muito simples a configuração:
• No IE, em propriedades avançadas, desmarcar a opção “Disable Script Debugging (Internet Explorer)”.

Depois basta colocar “debugger” onde quiser na sua função de javascript e está pronto. Da próxima vez que esta função for evocada irá despoletar o debug.

Javascript: Mostrar um alerta sempre que abandona um formulário sem gravar

Uma das grandes limitações que as aplicações Web sempre tiveram, foi a facilidade com que um utilizador pode perder informações introduzidas num formulário (apenas por seleccionar um link que não era suposto).

Se bem que este problema já começou a ser um pouco ultrapassado com a nova moda de colocar um “div de fundo”, dando a impressão que está a usar um formulário modal, em muitas situações esta limitação continua a ser bem real.

Há alguns anos atrás participei num projecto em que um dos requisitos era alertar o utilizador sempre que carregava num link, sem antes ter guardado a informação alterada. Depois da equipa muito pesquisar na Net sobre a melhor forma de implementar este requisito em Javascript, encontrámos uma propriedade muito interessante – defaultValue – disponível para qualquer elemento de um Form.

Baseámo-nos num script do Bob Mattler (infelizmente perdi a referência) com alguma modificações nossas.

Para implementar basta:
• Colocar uma referência na Master Page para o JS.
• Em cada link da vossa aplicação, nomeadamente nos menus, colocar a instrução onclick="formAlterado=true;" e já está.


/*********************************
** Verifica Alterações em Form **
*********************************/

window.onbeforeunload=verificaAlteracoes; //regista o evento para correr no unload de qualquer página

var formAlterado = false;
var msgAlterado = 'Colocar aqui a mensagem de erro';

function verificaAlteracoes() {
if (formAlterado){
//só queremos validação nos forms que são para gravar
if (document.getElementById('lnkGravar') && isFormChanged()) {
event.returnValue = msgAlterado;
}
formAlterado = false;
}
}

function isFormChanged() {
var rtnVal = false;
var frm = document.forms[0];
var ele = frm.elements;

//Percorre todos os elementos do Form
for ( i=0; i < ele.length; i++ ) {
if ( ele[i].type.length > 0 ) {
if ( isElementChanged( ele, i ) ) {
rtnVal = true;
break;
}
}
}
return rtnVal;
}

function isElementChanged( ele, i ) {
switch ( ele[i].type ) {
case "text" :
if ( ele[i].value != ele[i].defaultValue )
return true;
break;
case "textarea" :
if ( ele[i].value != ele[i].defaultValue )
return true;
break;
case "radio" :
if ( ele[i].checked != ele[i].defaultChecked )
return true;
break;
case "select-one" :
if (ele[i].options.selectedIndex != -1 &&
ele[i].options[ele[i].options.selectedIndex].selected !=
ele[i].options[ele[i].options.selectedIndex].defaultSelected){

if (ele[i].options.selectedIndex == 0 && ele[i].options[0].value == ''){
for ( var x =0 ; x < ele[i].length; x++ ) {
//verifica se existia algum default selected
if ( ele[i].options[x].defaultSelected )
return true;
}
}
else
return true;
}
break;
case "select-multiple" :
if (ele[i].options.selectedIndex != -1 &&
ele[i].options[ele[i].options.selectedIndex].selected !=
ele[i].options[ele[i].options.selectedIndex].defaultSelected){

if (ele[i].options.selectedIndex == 0 && ele[i].options[0].value == ''){
for ( var x =0 ; x < ele[i].length; x++ ) {
//verifica se existia algum default selected
if ( ele[i].options[x].defaultSelected )
return true;
}
}
else
return true;
}
break;
case "checkbox" :
if ( ele[i].checked != ele[i].defaultChecked )
return true;
break;
}
return false;
}



Bem vindo ao blogue da Simple Solutions

Ano novo, vida nova!

Ao iniciar um novo ano, olho com saudades para 2008, um ano em que estivemos envolvidos em vários projectos de relevo, com especial destaque para o MOSS 2007. Fortalecemos a nossa equipa com três novos elementos jovens de grande valia técnica e conseguimos construir as bases para que 2009 seja um ano ainda de maior sucesso para a Simple Solutions.

Um dos grandes objectivos que tenho desde que criámos a nossa empresa é demonstrar a qualidade técnica dos nossos elementos. E que melhor forma de confirmar essa qualidade do que a criação de um blog!

Iremos falar sobre os mais variados assuntos ligados ao desenvolvimento de software em Portugal. Desde novos produtos, formas de facilitar a resolução de problemas que nos surgem no dia-a-dia, performance, trabalho em equipa... No fundo, tudo aquilo que achamos interessante e que gostaríamos de partilhar com os nossos parceiros, fará parte deste blog.

Espero que gostem!

Um excelente ano de 2009.
Carlos Teixeira