Softwares escritos no estilo “Rube Goldberg Machine”

20/02/2009 01:09

Sempre achei fascinante a engenhosidade das Rube Goldberg Machines, a idéia de realizar operações extremamente simples através de uma engenharia complexa de eventos e ações é fabulosa (como entretenimento, claro). Pra quem não sabia, Rube Goldberg Machines foram originalmente criadas por Reuben Garret Lucius Goldberg numa série de cartoons que ficaram conhecidos internacionalmente. Hoje em dia existem até campeonatos incríveis de inventores que produzem esses aparatos, uma rápida busca no YouTube dá uma boa dimensão da coisa.

Abaixo coloquei um exemplo de uma máquina que tira creme dental do tubo. Repare que uma das ações consiste em fazer um pássaro mover um pino que sustenta um peso sobre o creme dental. Fantástico! Fala sério?

rube-goldberg

O fato é que, apesar de pitorescas, temos como certo que essas máquinas absurdas nunca seriam construídas na vida real, correto? Bem, infelizmente no desenvolvimento de software não é raro encontrarmos códigos ou soluções técnicas no melhor estilo Rube Goldberg. E a ocorrência deste tipo de problema se estende para analistas de sistema, arquitetos, e por aí vai.

Um desenvolvedor consciente deve desconfiar quando uma atividade simples requer uma grande cadeia de eventos e mecanismos para funcionar, e sempre se questionar se não existe um caminho mais curto e conciso para executar essa tarefa. Soluções muito rebuscadas só servem para dificultar a manutenção e o entendimento do código, ou seja, perda de esforço e investimento.

Se você fizer um retrospecto e chegar a conclusão que participou da construção de “Rube Goldberg Softwares” (com todo respeito aos geniais cartoons de Goldberg), sugiro que estude o quanto antes Design Patterns, técnicas de refactoring, boas práticas das tecnologias e metodologias que utiliza e convença os demais profissionais envolvidos a adotarem a mesma postura. Pode acreditar que vale a pena!

 

Um pássaro tirando um pino que sustenta um peso… Magnífico! :)

Reverberando



SQL Server 2008 (parte 5) - Hierarchyid Data Type

18/02/2009 23:53

No último post da série sobre as novidades do SQL Server 2008 abordei os aprimoramentos para os data types de data e hora. Hoje veremos o novo tipo Hierarchyid e sua aplicação.


HIERARCHYID

O novo data type Hierarchyid permite armazenamento estruturado como uma hierarquia de relacionamento entre os dados.

Existem duas formas de pensar sobre o armazenamento da sua hierarquia, conforme as ilustrações a seguir:

hierarchyidProfundidade

Profundidade

Na chamada indexação por profundidade linhas são armazenadas em uma subárvore próximas umas das outras. Um bom exemplo para imaginarmos esse cenário é a relação entre gerentes e funcionários de uma empresa onde o armazenamento será próximo já que os funcionários se reportarão diretamente a algum gerente, da mesma forma que os gerentes a um diretor e assim por diante.

 

hierarchyidAmplitude

Amplitude

Neste tipo de estratégia as linhas de cada nível da hierarquia são armazenadas juntas, revendo o exemplo acima os funcionários que se reportam para um mesmo gerente são armazenados próximos uns dos outros.

 

 

 

Vejamos agora um exemplo com uma tabela simples para ilustrar os conceitos apresentados. A seguir temos o código para criação do exemplo:

CREATE TABLE Equipe
   (
    Lider hierarchyid,
    ReportaPara as Lider.GetLevel(), 
    ColaboradorId int UNIQUE NOT NULL,
    NomeColaborador nvarchar(50) NOT NULL
   ) ;
GO

Vamos inserir alguns registros utilizando o código descrito a seguir:

INSERT Equipe (Lider, ColaboradorId, NomeColaborador)
VALUES (hierarchyid::GetRoot(), 1, 'Lider A');
GO

INSERT Equipe (Lider, ColaboradorId, NomeColaborador)
VALUES (hierarchyid::GetRoot().GetDescendant(null, null), 2, 'Desenv A1');
GO

INSERT Equipe (Lider, ColaboradorId, NomeColaborador)
VALUES (hierarchyid::GetRoot().GetDescendant(null, null), 3, 'Desenv A2');
GO

INSERT Equipe (Lider, ColaboradorId, NomeColaborador)
VALUES (hierarchyid::GetRoot().GetDescendant(null, null), 4, 'Desenv A3');
GO

A sintaxe hierarchyid::GetRoot().GetDescendant(null, null) informa ao SQL Server que queremos obter o descendente derivado de Root, no caso, como temos apenas um registro inserido no Root (linhas 1 e 2 do código acima) as linhas serão relacionadas a esse registro.

Se quiséssemos inserir outro elemento derivado de Root, bastaria utilizar o seguinte código:

INSERT Equipe (Lider, ColaboradorId, NomeColaborador)
VALUES (hierarchyid::GetRoot(), 100, 'Lider B');
GO

Agora utilizaremos outra abordagem para inserimos alguns registros com outro nível de hierarquia.

DECLARE @Lider hierarchyid, @lc hierarchyid

SELECT @Lider = Lider
FROM Equipe
WHERE colaboradorId = 2

INSERT Equipe (Lider, ColaboradorId, NomeColaborador)
VALUES (@Lider.GetDescendant(@lc, NULL), 101, 'Desenv A11');

INSERT Equipe (Lider, ColaboradorId, NomeColaborador)
VALUES (@Lider.GetDescendant(@lc, NULL), 102, 'Desenv A12');
GO

Para visualizarmos o resultados vamos executar a query a seguir:

SELECT Lider.ToString(), * FROM Equipe

Repare que utilizei o método ToString() para fazer a conversão do tipo hierárquico para uma notação mais legível. Para visualizarmos todos os lideres do primeiro nível podemos utilizar a seguinte query:

SELECT Lider.ToString() AS OLider, *
FROM Equipe
WHERE Lider = hierarchyid::GetRoot() ;
GO

A query a seguir retorna todos as linhas derivadas do colaborador com o Id 2: 

DECLARE @Colaborador hierarchyid

SELECT @Colaborador = Lider
FROM Equipe
WHERE ColaboradorId = 2;

SELECT Lider.ToString() AS Colaborador, *
FROM Equipe
WHERE Lider.GetAncestor(1) = @Colaborador

Como vimos o novo data type Hierarchiyd permite um armazenamento inteligente e semântico para dados estruturados hierarquicamente, as aplicações são inúmeras. Espero que tenham gostado. Até o próximo post.

SQL Server



SQL Server 2008 (parte 4) – Datetime Data Type Enhancements

16/02/2009 23:58

Na semana passada publiquei os três primeiros posts da série sobre as novidades do SQL Server 2008, nesta semana darei continuidade falando sobre os novos tipos de dados para armazenamento de data e hora. Para acessar os demais posts desta série clique neste link.


DATA TYPES

A nova versão do SQL Server trouxe novos tipos de dados para facilitar e otimizar o armazenamento de data e hora, a tabela a seguir mostra algumas características destes tipos:

Data Type Formato Range Tamanho em bytes
time hh:mm:ss[.nnnnnnn] 00:00:00.0000000
até
23:59:59.9999999
3 a 5
date YYYY-MM-DD 00001-01-01
até
9999-12-31
3
smalldatetime YYYY-MM-DD hh:mm:ss 1900-01-01
até
2079-06-06
4
datetime YYYY-MM-DD hh:mm:ss[.nnn] 1753-01-01
até
9999-12-31
8
datetime2 YYYY-MM-DD hh:mm:ss[.nnnnnnn] 0001-01-01 00:00:00.0000000
até
9999-12-31 23:59:59.9999999
6 a 8
datetimeoffset YYYY-MM-DD hh:mm:ss[.nnnnnnn] [+|-]hh:mm 00001-01-01 00:00:00.0000000
até
9999-12-31 23:59:59.9999999
(in UTC)
8 a 10

Vejamos agora a criação de uma tabela de exemplo com os novos data types, faremos a inserção de um registro para observarmos o resultado final.

CREATE TABLE [dbo].[ExemploDataType]
(
	[ExemploId] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
	[DataTipo1] [smalldatetime] NULL,
	[DataTipo2] [datetime] NULL,
	[DataTipo3] [date] NULL,
	[DataTipo4] [time](7) NULL,
	[DataTipo5] [datetime2](7) NULL,
	[DataTipo6] [datetimeoffset](7) NULL
)
GO

INSERT INTO ExemploDataType 
	(DataTipo1, DataTipo2, DataTipo3,
	 DataTipo4, DataTipo5, DataTipo6)
VALUES 
 	(GetDate(), GetDate(), GetDate(), 
 	 GetDate(), GetDate(), GetDate())
GO


Os registros terão o seguinte aspecto após a inserção:

DataTipo1 (smalldatetime)  = 2009-02-16 23:44:00
DataTipo2 (datetime)       = 2009-02-16 23:44:07.020
DataTipo3 (date)           = 2009-02-16
DataTipo4 (time)           = 23:44:07.0200000
DataTipo5 (datetime2)      = 2009-02-16 23:44:07.02
DataTipo6 (datetimeoffset) = 2009-02-16 23:44:07.0200000 +00:00


Os tipos Time, Datetime2 e Datetimeoffset podem ainda ser declarados com o valor entre parêntesis variando de 0 a 7, isso indica a precisão no armazenamento.

Os novos data types de data e hora do SQL Server 2008 não foram os únicos incrementos, em posts futuros desta série abordarei outros tipos disponibilizados. Até lá.

SQL Server



SQL Server 2008 (parte 3) - Security Enhancements

11/02/2009 23:44

Hoje abordarei algumas melhorias relacionadas ao uso de criptografia no SQL Server 2008. Seguindo a linha dos posts anteriores, apresentarei os conceitos de uma maneira simples e objetiva já que é possível estudar com profundidade todos os assuntos abordados aqui no SQL Server Books Online.

Para acessar os demais posts desta série clique neste link.


ENCRYPTION

A partir da versão 2008 do SQL Server diversos aprimoramentos foram disponibilizados para trabalhar com criptografia das informações armazenadas, dentre eles o Transparent Data Encryption (TDE).

Basicamente a TDE possibilita encriptação e decriptação de dados e do log do SQL Server em tempo real usando o uma chave simétrica armazenada no banco de dados master ou uma chave assimétrica. Esse mecanismo é acionado no nível da página de dados antes que ocorra a gravação em disco.

A figura abaixo mostra a arquitetura do TDE completa.

security_SQL_2008

Alguns passos são necessários para utilizarmos do TDE são eles:

  • Criação de uma master key
  • Criação de um certificado protegido pela master key
  • Criação de uma chave de criptografia para a database protegida pelo certificado
  • Definir o banco de dados para usar a criptografia


Abaixo segue um exemplo de código do MSDN:

USE master;
GO

CREATE MASTER KEY ENCRYPTION BY PASSWORD = '';
go

CREATE CERTIFICATE MyServerCert WITH SUBJECT = 'My DEK Certificate'
go

USE AdventureWorks
GO

CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_128
ENCRYPTION BY SERVER CERTIFICATE MyServerCert
GO

ALTER DATABASE AdventureWorks
SET ENCRYPTION ON
GO


Este artifício reforça a preocupação do time de desenvolvimento do produto com a segurança da informação. Uma dica interessante para ser usada independente do uso dos mecanismos explicados acima é o Microsoft Baseline Security Analyzer 2.1 (MBSA), uma ferramenta gratuita que avalia problemas de segurança em sistemas operacionais como o Vista ou o Windows Server 2008 entre outros produtos. As versões anteriores do MBSA faziam verificações de segurança no SQL Server 2005, contudo não vi nada igual para o 2008 ainda. Caso alguém saiba de alguma versão que faça isso, por favor, deixe um comentário aqui.

SQL Server



SQL Server 2008 (parte 2) - Programmability Enhancements

10/02/2009 22:45

Dando continuidade na série de posts sobre as melhorias de desenvolvimento do SQL Server 2008 falarei hoje sobre o Row Constructors. Para quem não leu os posts anteriores, é possível acessar todos os posts desta série clicando aqui.


ROW CONSTRUCTORS

O T-SQL a partir da versão 2008 oferece uma maneira mais concisa para criarmos sentenças com Insert. Nas versões anteriores usávamos o seguinte método para inserimos novos registros numa tabela:

INSERT INTO [dbo].[Atividade] (Descricao, DataConclusao) 
VALUES ('Participar do evento', '01/03/2009')

INSERT INTO [dbo].[Atividade] (Descricao, DataConclusao) 
VALUES ('Iniciar treinamento', '05/03/2009')

INSERT INTO [dbo].[Atividade] (Descricao, DataConclusao) 
VALUES ('Finalizar artigo', '11/03/2009')

A construção nova para o exemplo anterior seria:

INSERT INTO 
	[dbo].[Atividade]
VALUES 
	('Participar do evento', '01/03/2009'), 
	('Iniciar treinamento', '15/03/2009'),
	('Finalizar artigo', '22/03/2009')

Muito prático, não?

SQL Server



SQL Server 2008 (parte 1) - Programmability Enhancements

09/02/2009 00:59

Iniciando a série de posts sobre o SQL Server 2008 mostrarei hoje o conceito de Merge introduzido no T-SQL e que trouxe novas possibilidades não só para o Database Engine do SQL Server mas para outros serviços como o Integration Services (SSIS), incrementando a forma como você pode construir o seu DML.


MERGE

A idéia é que operações de insert, update e delete em uma tabela possam ser baseadas no resultado de um join com outra tabela. Isso significa que você pode realizar múltiplas operações em uma única query.

Digamos que você queira atualizar uma tabela de colaboradores de uma revista para aplicar uma nova regra de bônus levando em consideração o seguinte:

- Todos os colaboradores que escreveram mais de 10 artigos ganharão um bônus de 100 pontos;

- Colaboradores que não escreveram nenhum artigo serão deletados - é só um exemplo pessoal :)

Para realizar a operação será necessário utilizarmos a tabela de artigos, a imagem abaixo ilustra as tabelas envolvidas.

Tables_Merge

Antes de utilizarmos o Merge, vamos considerar o cenário ilustrado abaixo através de duas consultas, uma retornando todos os registros da tabela Colaborador e outra que totaliza a quantidade de artigos por colaborador:

 Merge_Antes01

Além do fato de que o segundo colaborador escreveu uma quantidade imensa de artigos, rapidamente constatamos que, de acordo com as regras que queremos aplicar, teríamos o primeiro e o segundo colaboradores ganhando o bônus de 100 pontos, o terceiro permanecendo com a mesma quantidade e o último sendo deletado da tabela. Vejamos como fica a query usando Merge para executar a operação toda:

MERGE Colaborador AS target
USING 
 (
	SELECT 
		[Colaborador].ColaboradorId, COUNT([Artigo].ArtigoId)
	FROM 
		[Colaborador]
		INNER JOIN [Artigo]
			on [Artigo].ColaboradorId = [Colaborador].ColaboradorId
	GROUP BY
		[Colaborador].ColaboradorId
	HAVING
		COUNT([Artigo].ArtigoId) > 0
 ) AS source (ColaboradorId, QtdeArtigos)
ON 
	(target.ColaboradorId = source.ColaboradorId)
WHEN MATCHED AND source.QtdeArtigos > 10
    THEN UPDATE SET target.Bonus = target.Bonus + 100
WHEN NOT MATCHED BY SOURCE 
	THEN DELETE
OUTPUT Deleted.*, $action, Inserted.*;


Na Linha 1 definimos o nosso target, que no caso é a tabela Colaboradores, que possui o atributo Bonus que queremos atualizar.

Da Linha 2 até a Linha 16 montaremos a nossa query para verificamos a quantidade de artigos por colaborador.

Nas Linhas 17 e 18 dizemos através do argumento WHEN MATCHED  que para cada registro do source que tivemos uma quantidade de artigos maior que 10 aplicaremos uma atualização no target somando mais 100 pontos no atributo Bonus.

As Linhas 19 e 20 e utilizam o argumento WHEN NOT MATCHED BY SOURCE para realizar o delete dos registros que não satisfizeram nem consulta do source quanto as as condições adicionais.

Finalmente a Linha 21 exibe o resultado antes e depois do Merge através do comando OUTPUT, esta última linha é opcional, e nos dará o seguinte resultado:

Merge_Antes

Na imagem acima também está o resultado final da tabela Colaborador. Como vimos realizamos todas as operações propostas de maneira bem simples. Fácil, não?

Embora incrementos como o Merge afaste o T-SQL do padrão ANSI devemos considerar o uso deste recurso quando desejamos realizar tarefas mais complexas de uma maneira rápida e limpa, ainda que apenas em tempo de desenvolvimento. Processos de ETL no Integration Services também podem ser beneficiar com o Merge, uma que vez tarefas de verificação que dependam de resultados de outras consultas podem ser implementadas mais facilmente e de maneira eficiente.

No próximo post da série veremos mais incrementos de desenvolvimento do SQL Server 2008.

SQL Server



Série de posts sobre SQL Server 2008

07/02/2009 21:42

SQLServer2008

Iniciarei aqui no Reverb uma série de posts sobre os aprimoramentos de desenvolvimento no SQL Server 2008 utilizando exemplos práticos.

Utilizo o SQL Server desde a versão 2000, e nesses 8 anos pude trabalhar em projetos interessantes, passando por desenvolvimento no Analysis Services, Reporting Services, muito T-SQL e algumas experiências com o SSIS. Participei de um projeto de migração do SQL Server 2000 para 2005 que trouxe muitas experiências enriquecedoras.

Espero que você, leitor deste blog, acompanhe os posts e principalmente participe deixando os seus comentários. Não perca!

SQL Server



Quer contribuir com a Enterprise Library 5?

04/02/2009 22:34

 pnp_logo

O convite foi realizado há poucos dias por Grigori Melnik, um dos coordenadores do projeto, em seu blog, e mostra a abertura dos responsáveis pela Enterprise Library em receber opiniões e sugestões.

Segue o texto original:

Enterprise Library 5 – what’s on your wish list?

We’ve started our planning of the Enterprise Library 5. This is your chance to send us suggestions, comments, screams... These may include ideas for new blocks, new providers for existing blocks, integration with new .NET Framework 4.0 features, improvements to the design-time experience, performance improvements, support of specific deployment/operations scenarios, documentation/training support etc.

I am going to use the same technique Tom employed several years ago soliciting feature requests for EntLib3. It seemed to work quite well then. So, imagine you have a sum of money that you can invest in developing EntLib 5. Say $100 (or should I index the amount to be more like a stimulus package? :) In any case, when suggesting your features, decide how much of that $100 you want to spend for each feature. You can split $100 any way you want. If there is only one feature you want to spend all your money on, you can do it too. Please stay within the budget. Also, be specific – explain your scenario in detail, provide some context, make your case potentially appealing to other users of EntLib. Do remember, however, that EntLib has been and will be a general purpose library of reusable components that are architecture- and application domain-agnostic.

Once we gather your feedback, we will publish the list of feature requests and invite you to prioritize them.

Feel free to post your suggestions as comments on my blog or simply email me. Look forward to your propositions!

Thanks!

Sem dúvida eu separaria uma parte dos meus $100 para aprimorar a configuração dos arquivos XML, um pouco para melhorias do Unity Application Block, outro tanto para o Validation Application Block permitir maior integração com outras tecnologias de front end, e o restante… o restante eu guardaria. ;)

Enterprise Library