Pesquisar

Vagas de TI sobrando?

Como é engraçado a visão dos empregados sobre o funcionário. Neste post da Info sobre carreira e porque as vagas estão sobrando alguns entrevistados entram em divergencia sobre o real motivo.

http://info.abril.com.br/noticias/carreira/vagas-de-emprego-em-ti-encalham.-saiba-por-que-04042011-0.shl

Segundo a GVT “a dificuldade de contratar profissionais de TI no Brasil pode ser minimizada não só com a oferta de melhores salários, mas também com outros atrativos para o crescimento do profissional”, agora para outras empresas a dificuldade em contratar está no alto salário dos profissionais, pois eles estão se auto valorizando, pedindo 20% a mais do que valem, e ainda não estão preparados. O engraçado que uma das principais formas de contratação da empresa é por meio do processo de Trainee, com certeza é mais fácil contratar estagiários do que profissionais qualificados.

Outro ponto que as empresas estão reclamando bastante é a falta de qualificação. Porém quanto custa ao profissional realizar uma pós-graduação? Estudar para uma certificação? E quanto ele ganha realmente?

Aqui onde eu trabalho acho que o salário médio das empresas para um programador gira em torno de 2000 reais, se ele estiver fazendo ainda faculdade vai gastar em torno de 500 reais, só com a faculdade sem contar transporte. Agora ele também necessita aprender inglês, colocamos nessa conta mais 150 reais mês. Agora ele precisa também de uma certificação, pois o mercado valoriza isso. Então ele vai precisar comprar alguns livros, mais 100 reais por um livro.

Agora vem os gastos com moradia, aqui em torno de 600 reais mês, comida mensal em torno de 300 reais(não pode comer muita porcaria). Vamos fazer as contas para a sobrevivencia: 1650 reais por mês. Sobrando exatamente 350 reais por mês para transporte, roupas, algum lazer. Como essa pessoa vai pensar em comprar algum bem? Como eu vou comprar um carro? Isso faz as pessoas deixarem de investir o dinheiro em cursos, e certificações para poderem ter um pouco de conforto.

Porém grande parte dos profissionais hoje que começam em TI começam no suporte, ou como estagiários e nunca chegam a ganhar isso, e sem receber incentivos das empresas, como esses profissionais recém-formados vão conseguir ter essa experiência? Aqui vai um texto que saiu no twitter.

CFO asks CEO "What happens if we invest in developing our people & then they leave us?" CEO: 'What happens if we don't, and they stay?”

Traduzindo: O que acontece se nós investirmos em desenvolver nossos funcionários e eles forem embora? Então o gerente responde: O que acontece se não fizermos e eles ficarem?

Todos os gerentes deveriam ser assim. Na verdade esses são os gerentes de verdade, os outros que estão lá entraram por causa do dinheiro.

Fluent NNhibernate e Auto Mapping

Com o Fluent Nhibernate é possivel utilizar-se do padrão “Convention over Configuration”, Convençao sobre Configuração, quem é programador Java, ou de outras linguagens de script já usam bastante deste padrão, mas para .Net isto não é tão comum assim. Este padrão permite que não precisamos configurar nosso mapeamento, pois ele está implicito na declaração de nossas classes, possibilitado pela convençao. Por exemplo quando criamos um campo Id em nossa classe não necessitamos mapear essa propriedade, pois a convenção nos diz q ele vai ser uma chave primaria de nossa tabela.
O Fluent Nhibernate permite que seja mapeado as classe através dessa convenção, devemos apenas dizer quais as nossas classes devem ser mapeadas.
var mapeamento = AutoMap.AssemblyOf<Dominio.Entidades.Core.Usuario>(convencoes); //Qual assembly deve ser mapeado

var cfgFluent = FluentNHibernate.Cfg.Fluently.Configure(cfg).Mappings(x =>
x.AutoMappings.Add(mapeamento));

cfg = cfgFluent.BuildConfiguration();
this.FabricaSessao = BuildSessionFactory(cfg);

No caso acima passamos o assembly da classe Usuario, fazendo com que todas as outras classes sejam mapeadas.

public class Usuario : IEntidade
{
public virtual long Id { get; set; }

public virtual string Nome { get; set; }
}

A classe Usuário será mapeada para um tabela, onde o Id será a chave primária, e  o campo Nome será um varchar.

Porém necessitamos fazer alguns refinamentos nesses mapeamentos, por exemplo caso queiramos adicionar um prefixo no nome da tabela, ou por exemplo definir o tamanho do campo Nome no banco? Teremos que adicionar os mapeamentos um a um?  Ai entra a possibilidade de extensão do Fluent, todas as convençoes podem ser implementadas manualmente extendendo as convenções padrões.

public class TableNameConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Table("tb_" + instance.EntityType.Name);
}
}


Neste exemplo criamos uma convenção para o nome da tabela que será gerado, implementamos o IClassConvention, e setamos o nome da tabela que queremos. Todas as interfaces que podem ser implementadas estão no namespace using FluentNHibernate.Conventions.

Na hora de configurar o Fluent devemos adicionar nossas convenções antes de criar a SessionFactory.

var mapeamento = AutoMap.AssemblyOf<Dominio.Entidades.Core.Usuario>(convencoes); //Qual assembly deve ser mapeado
mapeamento.Conventions.Add<TableNameConvention>();
mapeamento.Conventions.Add<PrimaryKeyNameConvention>();

var cfgFluent = FluentNHibernate.Cfg.Fluently.Configure(cfg).Mappings(x =>
x.AutoMappings.Add(mapeamento));

Desta forma o Fluent saberá que deverá usar nossas classes de configuração.

Essa apenas uma das maneiras que o Fluent permite fazer, temos outras mais em exemplos por ai na internet. Vale a pena dar uma olhada e verificar qual melhor se aplica ao seu projeto. Isso é muito util no caso de você já ter algumas convenções que usa e não quer mudar e para código legado.

Estilos e Grid no WPF

Uma das coisas mais demoradas e chatas no desenvolvimento Windows, depois de escrever Sql (brincadeirinha), é o alinhamento de controles e botões na tela. O Visual Studio nos traz várias ferramentas que alinham os botões, aumenta o espaçamento, etc, mas mesmo assim a vida do desenvolvedor fica um pouco complicado. Com o WPF e estilos ao formato dos estilos css da web, podemos criar telas mais faceis de serem escritas através do xaml.
O WPF nos permite definir Grids em nosso formularios e criar linhas e colunas imaginarias onde nossos controles irão ficar. Vamos usar isso para criar a definição dessas linhas e após adicionarmos nossos controles nessas linhas e definirmos um tamanho. Algo como na figura abaixo.
image
Primeiro criamos um estilo para a nossa aplicação, onde devemos colocar o tamanho das colunas e linhas, e o tamanho dos componentes.
Como vocês pode ve
<Style TargetType="ColumnDefinition">        
<Setter Property="MinWidth" Value="70" />
</Style>
<Style TargetType="RowDefinition">
<Setter Property="Height" Value="50" />
</Style>

<Style x:Key="LabelUm" TargetType="Label">        
<Setter Property="Height" Value="23" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>

<Style x:Key="LabelDois" TargetType="Label" BasedOn="{StaticResource LabelUm}">
<Setter Property="Grid.ColumnSpan" Value="2" />
</Style>

<Style x:Key="LabelTres" TargetType="Label" BasedOn="{StaticResource LabelUm}">
<Setter Property="Grid.ColumnSpan" Value="3" />
</Style>
r, nós criamos o tamanho da coluna e da linha, e adicionamos os tamanhos dos labels, apartir da propriedade Grid.ColumnSpan, que permite que um label ocupe o espaço de duas colunas, ou uma.

E agora o nosso formulário principal, onde chamamos os estilos e adicionamos eles aos labels, e textbox, desta forma eles vão se alinhando automaticamente. A idéia é igual a programação Web, criar um estilo e fazer o alinhamento apartir do estilo. Aqui vai o código do formulario principal.

<Window x:Class="MecanicaWPF.CadastroCliente" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MecanicaWPF"
Title="Cadastro de Clientes">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>                
<ResourceDictionary Source="../EstilosFormulario.xaml" />                
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<TabControl Margin="12,12,12,42" Name="tabControleCliente" Height="507">
<TabItem Name="tabCliente" Header="Dados do Cliente">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>                     
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<Label Grid.Row="0" Content="Nome do Cliente:" Style="{StaticResource LabelSeis}" />
<TextBox Grid.Row="0" Name="txtCliente" Style="{StaticResource TextBoxSeis}" />

<Label Grid.Row="0" Grid.Column="6" Content="CPF/CNPJ:" Style="{StaticResource LabelDois}" />
<TextBox Grid.Row="0" Grid.Column="6" Name="txtCpfCnpj" Style="{StaticResource TextBoxDois}" />

<Label Grid.Row="1" Content="Tipo:"  Style="{StaticResource LabelDois}" />
<TextBox Grid.Row="1" Name="txtTipoPessoa" Style="{StaticResource TextBoxDois}" />

<Label Grid.Row="1" Grid.Column="2" Content="Enquadramento Cliente:"  Style="{StaticResource LabelSeis}" />
<RadioButton Grid.Row="1" Grid.Column="2" Content="Cliente" Name="rdbCliente" Style="{StaticResource Dois}"/>
<RadioButton Grid.Row="1" Grid.Column="4" Content="Fornecedor" Name="rdbFornecedor" Style="{StaticResource Dois}"/>
<RadioButton Grid.Row="1" Grid.Column="6" Content="Ambos" Name="rdbAmbos" Style="{StaticResource Dois}"/>

<Label Grid.Row="2" Content="RG/Inscricao:"  Style="{StaticResource LabelDois}" />
<TextBox Grid.Row="2" Name="txtRgInscricao" Style="{StaticResource TextBoxDois}" />

<Label Grid.Row="2" Grid.Column="2" Content="Telefone 1:"  Style="{StaticResource LabelDois}" />
<TextBox Grid.Row="2" Grid.Column="2" Name="txtTelefoneUm" Style="{StaticResource TextBoxDois}" />

<Label Grid.Row="2" Grid.Column="4" Content="Telefone 2:"  Style="{StaticResource LabelDois}" />
<TextBox Grid.Row="2" Grid.Column="4" Name="txtTelefoneDois" Style="{StaticResource TextBoxDois}" />

<Label Grid.Row="2" Grid.Column="6" Content="Cliente desde:"  Style="{StaticResource LabelDois}" />
<TextBox Grid.Row="2" Grid.Column="6" Name="txtClienteDesde" Style="{StaticResource TextBoxDois}" />

<Label Grid.Row="3" Content="Email:"  Style="{StaticResource LabelQuatro}" />
<TextBox Grid.Row="3" Name="txtEmail" Style="{StaticResource TextBoxQuatro}" />

<Label Grid.Row="3" Grid.Column="4" Content="Contato:"  Style="{StaticResource LabelQuatro}" />
<TextBox Grid.Row="3" Grid.Column="4" Name="txtContato" Style="{StaticResource TextBoxQuatro}" />

<Label Grid.Row="4"  Content="Observacao:"  Style="{StaticResource LabelOito}" />
<TextBox Grid.Row="4" Grid.RowSpan="4" Name="txtObservacao"  Style="{StaticResource TextBoxOito}" AcceptsReturn="True" AutoWordSelection="True" VerticalScrollBarVisibility="Auto" />
</Grid>



Como vocês podem ver, eu apenas adiciono aos controles a linha e o tamanho dele, um, dois, tres, etc. O código fica muito mais limpo, sem posições, ancoras, etc. Este exemplo é redimensionavel conforme a janela.

Código Limpo

Apresentação de slides referente aos capitulos iniciais do livro Código Limpo escrito por Robert Martin, mais conhecido como Uncle Bob.
http://www.slideshare.net/nsitechtalks/cdigo-limpo
Vale a pena compartilhar esse link. Essa leitura é obrigatória a todo programador que quer se tornar um melhor programador.

Convertendo Datas e Números

Hoje vou falar sobre conversão de valores numericos e datas. Vejo muita gente fazendo conversões do tipo:

int valor = Convert.ToInt32(textbox1.Text);

O que acontecerá se o usuario não digitar um número? O que você faz? Coloca um try catch envolvendo tudo e diz para o usuário que aconteceu um erro?


A maioria dos programadores tem preguiça de efetuar isto do modo certo. Devemos sempre verificar se o que a gente está convertendo é um valor verdadeiro.


int valor;
int.TryParse(textbox1.Text, out valor);

Este é um caso onde o valor não é obrigatório, caso o usuário não digite um número verdadeiro a funçaõ TryParse irá setar o valor 0 para o valor. Agora caso precisemos que o usuário digite um número devemos efetuar o seguinte:


            int valor;
if (int.TryParse(textbox1.Text, out valor))
{
//Valor Verdadeiro
}



Isto vale para os outros tipos: double, long, decimal, todos eles possuem o método TryParse() que retorna um booleano, devemos usar sempre que possível esta função. Ela usa as configurações regionais do Windows, então caso seu windows estiver configurado como separador decimal o ponto, e vc digitar o valor “12.00”, ele vai converter para doze, agora caso esteja configurado para virgula o valor resultante será mil e duzentos.Isso é muito util pois respeita as configurações que o usuário está acostumado a usar em seu computador.


Devemos utilizar este método especialmente com datas, pois ele vai fazer a conversão de acordo com as configurações do seu computador. Lembre-se DateTime.TryParse().


O próximo post será sobre datas no banco de dados.

Debugando Serviços do Windows

Geralmente quando vamos criar um serviço do windows temos um problema ao querer debugar o projeto criado.
Ao invéz de criarmos o projeto, instalarmos ele e após ele rodando irmos em Attach to Process e escolhermos o serviço já rodando podemos fazer de um outro modo, mais simples e fácil:

Colocamos diretivas de compilação para verificarmos quando estamos em modo debug, e criamos uma instãncia de nosso service e chamamos seu método Start(), simples não?

       Public Shared Sub Main()
#If DEBUG Then
Dim servico As New ServicoBuscaDePedidos()
servico.OnStart(New String() {})
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite)
#Else
ServiceBase.Run(New ServiceBase() {New ServicoBuscaDePedidos()})
#End If
End Sub

Até mais, espero que gostem deste post.

Criar Foto Sépia

Aqui está uma função que converte uma imagem ou bitmap em sépia.
Ele utiliza a primeira matriz para deixar a foto em preto e branco, e após ele aplica a matriz sépia sobre a foto.
Com a classe ColorMatrix, e Matrix podemos efetuar qualquer transformação de Cor e geométrica sobre a foto.

Private Function MontarImagemSepia(ByVal fotoUsuario As Bitmap) As Bitmap
Dim novoBitmap As New Bitmap(fotoUsuario.Width, fotoUsuario.Height)

Dim graphics As Graphics = System.Drawing.Graphics.FromImage(novoBitmap)

Dim matrixPB()() As Single = {New Single() {0.33, 0.33, 0.33, 0, 0}, _
New Single() {0.33, 0.33, 0.33, 0, 0}, _
New Single() {0.33, 0.33, 0.33, 0, 0}, _
New Single() {0, 0, 0, 1, 0}, _
New Single() {0, 0, 0, 0, 1}}

Dim matrixSepia()() As Single = {New Single() {0.439, 0.33, 0.33, 0, 0}, _
New Single() {0.33, 0.258, 0.33, 0, 0}, _
New Single() {0.33, 0.33, 0.078, 0, 0}, _
New Single() {0, 0, 0, 1, 0}, _
New Single() {0, 0, 0, 0, 1}}

Dim newColorMatrixPB As System.Drawing.Imaging.ColorMatrix = New System.Drawing.Imaging.ColorMatrix(matrixPB)
Dim newColorMatrixSepia As System.Drawing.Imaging.ColorMatrix = New System.Drawing.Imaging.ColorMatrix(matrixSepia)

Dim Attributes As System.Drawing.Imaging.ImageAttributes = New System.Drawing.Imaging.ImageAttributes()
Attributes.SetColorMatrix(newColorMatrixPB, Imaging.ColorMatrixFlag.Default, Imaging.ColorAdjustType.Bitmap)

graphics.DrawImage(fotoUsuario, New System.Drawing.Rectangle(0, 0, fotoUsuario.Width, fotoUsuario.Height), 0, 0, fotoUsuario.Width, fotoUsuario.Height, System.Drawing.GraphicsUnit.Pixel, Attributes)
graphics.Dispose()

Dim attributesSepia As System.Drawing.Imaging.ImageAttributes = New System.Drawing.Imaging.ImageAttributes()
attributesSepia.SetColorMatrix(newColorMatrixSepia, Imaging.ColorMatrixFlag.Default, Imaging.ColorAdjustType.Bitmap)

Dim newGraphicsSepia As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(novoBitmap)
newGraphicsSepia.DrawImage(novoBitmap, New System.Drawing.Rectangle(0, 0, novoBitmap.Width, novoBitmap.Height), 0, 0, novoBitmap.Width, novoBitmap.Height, System.Drawing.GraphicsUnit.Pixel, attributesSepia)
newGraphicsSepia.Dispose()

Return novoBitmap

End Function

Sql Compact versus DB4O

Hoje vou apresentar alguns testes que fiz com Sql Compact e o banco de dados orientado a objeto DB4O.

1º Teste -> Inserção de 10000 registros no banco de dados em uma tabela ou objeto com 5 campos:
Neste primeiro teste tive uma surpresa, o DB4O surpreendeu.
55597 milisegundos do Sql Compact contra 19976 para o DB4O.

2º Teste -> Inserção de 1000 registros e após pesquisa sequencial dos 1000 registros 1 a 1.
2674 milissegundos para o SqlCompact contra 5130 para o DB4O. Parece que consulta não é o forte do DB4O.

3º Teste -> Inserção de 1000 registros e busca de todos os registros de uma unica vez.
Mais uma vez o SqlCompact ganhou, 2377 milissegundos contra 8855 do DB4O.

Com os resultados, pode-se concluir que o DB4O ganha com larga vantagem na inserção de registros, em compensação em pesquisas simples o DB4O deixa a desejar.
Não foram efetuados testes com queries mais complexas, segundo algumas fontes o DB4O apresenta um resultado melhor quando a complexidade do objeto fica maior. Chegando a se igualar ao Sql Compact.

Programadores Bons

Segue link de um post muito bom falando sobre a importância de um programador e código bem escrito.
http://imasters.com.br/artigo/20302/carreira/verdades-nao-tao-conhecidas-sobre-programacao
Os gerentes de TI ainda não dão o merecido valor a um bom design e um bom código, pelo menos as pequenas companhias.

Gerando as classe da NFE

Para criar as classes para gerar a Nota Fiscal eletronica temos uma maneira mais facil do que precisar ler todo o manual e escrever as classes manualmente. Podemos usar uma ferramenta que vem junto com o Visual Studio ‘xsd.exe’.

Primeiramente devemos efetuar o download dos schemas da NFE do site http://www.nfe.fazenda.gov.br/PORTAL/schemas.aspx. Feito isto descompactamos todos eles em uma pasta.

Devemos iniciar o Visual Studio Command Prompt, e navegar no prompt de comando até a pasta onde descompactamos nossos arquivos.

image

Após apenas devemos digitar o comando:

‘xsd.exe xmldsig-core-schema_v1.01.xsd nfe_v2.00.xsd /c /l:vb’

Pronto, está gerada o arquivo com todas as classes dentro. Agora precisamos apenas separar as classes em arquivos. Um boa ferramenta para isso é a da DevExpress Code Formatter.

Plugin para o Windows Live Writer

Vamos escrever hoje um plugin para o Windows Live Writer. Para quem não conhecer o Live Writer vem juntamente com o instalador do Messenger, ele é um cliente de blog. Você escreve e publica diretamente através do programa.

Primeiramente você deve adicionar a referencia a dll WindowsLive.Writter.Api.dll que fica dentro da pasta C:\Program Files\Windows Live\Writer ao seu projeto Class Library. Após devemos herdar uma classe de SmartContentSource e sobrescrever 3 de de seus métodos: CreateEditor, CreateContent, e GeneratePublishHtml.

O CreateEditor serve para atualizar o html depois que você insere ele, o CreateContent é o método chamado para Criar o html, então neste método devemos abrir uma janela para poder escrever o nosso conteúdo, e o GeneratePublishHtml é chamado para pegar o código html gerado.

    [WindowsLive.Writer.Api.WriterPlugin("910AE5F6-2BC5-4632-AF01-B53414D45E9F", "InsertCodeWordPress",
Description = "Insere código de programação para utilizar o highlight do WordPress.")]
[WindowsLive.Writer.Api.InsertableContentSource("Inserir Código", SidebarText = "Inserir Código")]
public class CodeFormatter : WindowsLive.Writer.Api.SmartContentSource
{
public override WindowsLive.Writer.Api.SmartContentEditor CreateEditor(WindowsLive.Writer.Api.ISmartContentEditorSite editorSite)
{
return new ContentEditor();
}

public override System.Windows.Forms.DialogResult CreateContent(System.Windows.Forms.IWin32Window dialogOwner, WindowsLive.Writer.Api.ISmartContent newContent)
{
using (InsertCodeFormatted entryform = new InsertCodeFormatted(string.Empty, string.Empty, string.Empty))
{
DialogResult result = entryform.ShowDialog(dialogOwner);
if (result == DialogResult.OK)
{
newContent.Properties.SetString("HtmlGerado", entryform.RetornaHtmlFinal());
newContent.Properties.SetString("CodigoPuro", entryform.RetornaCodigoPuro());
newContent.Properties.SetString("Linguagem", entryform.RetornaLinguagem());
newContent.Properties.SetString("HtmlVisual", entryform.CriarHtmlVisual());
}
return result;
}
}

public override string GeneratePublishHtml(WindowsLive.Writer.Api.ISmartContent content, WindowsLive.Writer.Api.IPublishingContext publishingContext)
{

return content.Properties.GetString("HtmlGerado", "");
}
}


A classe InsertCodeFormatter é um formulario windows onde eu posso colocar um texto e quando eu fecho ele eu seto o resultado para as propriedade do newContent através do método SetString(), e no método GeneratePublishHtml eu retorno o código anteriormente salvo.


Devemos sempre lembrar de inserir o atributo Writerplugin na classe. Após compilar devemos jogar o plugin dentro da pasta Plugins em C:\Program Files\Windows Live Writer