Alfred's profileHow Things (Should) WorkPhotosBlogListsMore Tools Help

How Things (Should) Work

The truth is in the code
How We Test Software at Microsoft
Professional Software Testing with Visual Studio 2005 Team System: Tools for Software Developers and Test Engineers (Programmer
xUnit Test Patterns: Refactoring Test Code (Addison-Wesley Signature Series)
Code Complete: A Practical Handbook of Software Construction
Inside the Microsoft® Build Engine: Using MSBuild and Team Foundation Build (PRO-Developer)
Professional Team Foundation Server
CLR via C#, Second Edition (Pro Developer)
The C# Programming Language (3rd Edition) (Microsoft .NET Development Series)
Essential Windows Workflow Foundation (Microsoft .NET Development Series)
COM and .NET Interoperability
.NET and COM: The Complete Interoperability Guide Parts A and B
Inside Windows  Communication Foundation (Pro Developer)
Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (2nd Edition) (Microsoft .NET Develop
Windows® Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition (PRO-Developer)
Advanced Windows Debugging (The Addison-Wesley Microsoft Technology Series)
Microsoft Windows Internals (4th Edition): Microsoft Windows Server 2003, Windows XP, and Windows 2000
Windows via C/C++ (Pro - Developer)
Programming WPF
Windows Presentation Foundation Unleashed (WPF) (Unleashed)
Essential Windows Communication Foundation (WCF): For .NET Framework 3.5 (Microsoft .NET Development Series)
MCTS Self-Paced Training Kit (Exam 70-503): Microsoft® .NET Framework 3.5 Windows® Communication Foundation (PRO-Certification)
MCTS Self-Paced Training Kit (Exam 70-502): Microsoft® .NET Framework 3.5 Windows® Presentation Foundation
MCSE Self-Paced Training Kit (Exams 70-290, 70-291, 70-293, 70-294): Microsoft® Windows Server(TM) 2003 Core Requirements, Secon
Debugging Microsoft  .NET 2.0 Applications
Debugging Applications for Microsoft  .NET and Microsoft Windows (Pro-Developer)
Applications = Code + Markup: A Guide to the Microsoft  Windows  Presentation Foundation (Pro - Developer)
Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (Microsoft .NET Development Series)
.NET Framework Standard Library Annotated Reference, Volume 2 :Networking Library, Reflection Library, and XML Library
The Common Language Infrastructure Annotated Standard
6/17/2009

Pau que nasce torto não cresce direito

 

Uma prática bastante comum no desenvolvimento de sistemas é o que eu chamo de CPOP [1]- “Copy & Paste Oriented Programming”.

A prática é bastante utilizada, pois fornece um template inicial a partir da qual o módulo sendo trabalhado é rapidamente reproduzido e adaptado. Com isto economiza-se tempo no desenvolvimento.

Por conta CPOP, é de suma importância que o modelo original tenha a melhor qualidade possível.

Vamos pegar um exemplo: O “Guia do Desenvolvimento” de um determinado projeto em que trabalhei que dava o seguinte modelo para a implementação das classes na camada de acesso a dados.

Friend Class AD_GrupoSerie

 

    Private Sub New()

    End Sub

 

    Public Shared Function Construtor(ByVal reader As IDataRecord) As EN_GrupoSerie

 

        If reader Is Nothing Then

            Throw New ArgumentNullException("reader")

        End If

 

        ' Obtém posição dos campos no data reader

        Dim iGrupoSerieIdx As Integer = reader.GetOrdinal("COD_GRUPO_SERIE")

        Dim iNomGrupoSerieIdx As Integer = reader.GetOrdinal("NOM_GRUPO_SERIE")

 

        ' Cria objeto da entidade de negócio

        Dim objGrupoSerie As EN_GrupoSerie = New EN_GrupoSerie()

 

        ' Alimenta propriedades da entidade de negócio

        objGrupoSerie.Codigo = reader.GetInt32(iGrupoSerieIdx)

 

        ' Para campo que pode ser nulo, é necessário atribuir valor default.

        If Not reader.IsDBNull(iNomGrupoSerieIdx) Then

            objGrupoSerie.Nome = reader.GetString(iNomGrupoSerieIdx)

        Else

            objGrupoSerie.Nome = String.Empty

        End If

 

        ' Retorna objeto que representa a entidade de negócio

        Return objGrupoSerie

 

    End Function

 

End Class

 

O código tem uma coisa legal que é a validação do parâmetro de entrada “reader” (isto é menos comum no código deste projeto do que deveria ser), mas o código tem oportunidades de melhoria tanto quando olhado isoladamente quando olhada no contexto em que o método é usado.

DMTCRI[2]

Primeiro vamos ao problema que considero mais relevante que é o contexto onde o método é usado: Este método é chamado pelo método AD_GrupoSerie_Acao.Selecionar dentro de um loop - uma vez para cada registro retornado do banco de dados.

Public Class AD_GrupoSerie_Acao

    Public Function Selecionar(ByVal strNome As String) As List(Of EN_GrupoSerie)

 

        Dim resultado As List(Of EN_GrupoSerie) = New List(Of EN_GrupoSerie)()

 

        Dim db As Database = DatabaseFactory.CreateDatabase(strDBNome)

 

        If db Is Nothing Then

            Throw New ArgumentNullException("db")

        End If

 

        Dim command As DbCommand = db.GetStoredProcCommand("dbo.SPPJ_SELECIONAR_GRUPOSERIE")

 

        ' Alimenta parâmetros da pesquisa

        db.AddInParameter(command, "P_NOM_GRUPOSERIE", DbType.String, strNome)

 

        Dim rdr As IDataReader = db.ExecuteReader(command)

 

        While rdr.Read()

            resultado.Add(AD_GrupoSerie.Construtor(rdr))

        End While

 

        Return resultado

 

    End Function

 

End Class

 

Acontece que parte das operações realizadas dentro do método Construtor avaliam coisas que são imutáveis durante o tempo de vida do loop.

Uma vez que o código entre no loop, reader nunca será Nothing e a posição das colunas nunca vai mudar. A gente está simplesmente fazendo o código repetir a se mesmo. Podemos evitar isto movendo o código que trata destas duas coisas para fora do loop.

Friend Class AD_GrupoSerie

    Private reader As IDataRecord

    Private iGrupoSerieIdx As Integer

    Private iNomGrupoSerieIdx As Integer

    Private iIndAtivoIdx As Integer

 

    Public Sub New(ByVal reader As IDataRecord)

        If reader Is Nothing Then

            Throw New ArgumentNullException("reader")

        End If

        Me.reader = reader

 

        ' Obtém posição dos campos no data reader

        iGrupoSerieIdx = reader.GetOrdinal("COD_GRUPO_SERIE")

        iNomGrupoSerieIdx = reader.GetOrdinal("NOM_GRUPO_SERIE")

        iIndAtivoIdx = reader.GetOrdinal("IND_ATIVO")

    End Sub

 

    Public Function Construir() As EN_GrupoSerie

        ' Cria objeto da entidade de negócio

        Dim objGrupoSerie As EN_GrupoSerie = New EN_GrupoSerie()

 

        ' Alimenta propriedades da entidade de negócio

        objGrupoSerie.Codigo = reader.GetInt32(iGrupoSerieIdx)

 

        ' Para campo que pode ser nulo, é necessário atribuir valor

        If Not reader.IsDBNull(iNomGrupoSerieIdx) Then

            objGrupoSerie.Nome = reader.GetString(iNomGrupoSerieIdx)

            objGrupoSerie.IndAtivo = reader.GetBoolean(iIndAtivoIdx)

        Else

            objGrupoSerie.Nome = String.Empty

        End If

 

        ' Retorna objeto que representa a entidade de negócio

        Return objGrupoSerie

    End Function

End Class

 

    Public Function Selecionar(ByVal strNome As String, ByVal iAtivo As Integer) As List(Of EN_GrupoSerie)

        Dim db As Database = DatabaseFactory.CreateDatabase(strDBNome)

 

        Using command As DbCommand = db.GetStoredProcCommand("dbo.SPPJ_SEL_GRUPO_SERIE")

            db.AddInParameter(command, "P_NOM_GRUPOSERIE", DbType.String, strNome)

            db.AddInParameter(command, "P_IND_ATIVO", DbType.Int32, iAtivo)

 

            Dim resultado As List(Of EN_GrupoSerie) = New List(Of EN_GrupoSerie)()

            Using reader As IDataReader = db.ExecuteReader(command)

                Dim factory As New AD_GrupoSerie(reader)

                While reader.Read()

                    resultado.Add(factory.Construir())

                End While

            End Using

            Return resultado

        End Using

    End Function

As operações foram movidas para o construtor de AD_GrupoSerie que está fora do loop em AD_GrupoSerie_Acao.Selecionar e com isto não se tem o custo de verificação do parâmetro por nulo e a localização da posição das colunas para cada linha do resultset.

Dado ao fato do pessoal do projeto usar CPOP a torto e a direito, o mesmo erro foi replicado em dezenas de locais diferentes. Sair consertando tudo é inviável financeiramente, então é importante revisar no detalhe qualquer código que possa vir a ser utilizado como original (template) para o CPOP.


[1] Ao procurar o verbete para DRY no Wikipedia, eu acabei encontrando uma entrada para “Copy and paste programing” que trata justamente do que eu vinha chamando de CPOP – Copy & Paste Oriented Programming. Eu ainda acho CPOP mais legal por conta da alusão a OOP.

Por falar em OOP, a idéia não é fazer uma apologia ao CPOP. Se o cenário permitir, DRY nele!

[2] DMTCRI - Don’t Make The Code Repeat Itself é uma alusão a DRY – Don’t Repeat Yourself, uma filosofia de programação que prega a redução da duplicação de código. Aqui a idéia que quero passar é a de se evitar fazer com que o programa execute repetidas vezes operações que sempre trarão os mesmos resultados.

2/18/2009

We need a tool that combines functionality of xsd.exe and sgen.exe

I added a suggestion on Microsoft Connect asking for something with the combined functionality of xsd.exe and sgen.exe.

Given an xml schema file (xsd), you could use xsd.exe to generate a set of classes that could be serialized in conformance with that schema.

Then to perf things up a little bit, you could use sgen.exe to create an assembly containing specialized serializers for the classes generated previously.

You would end up with two assemblies for something that, in my opinion, would be better handled with one. For instance, with only one assembly there would be no risks of mismatching versions of the Serializable and Serializer assemblies.

You can work around having an extra assembly using sgen’s “/k” option which keeps on your project’s folder the temporary files used to create the serializer assembly. Among those files, there’s one with the source code.

There are some caveats though:

First, sgen only generates code in C#. If your project is in Visual Basic, then you have to take some extra steps to integrate the code into your code base.

Second, each time you run sgen, it creates a new file with a random name. You’ll have to rename it to something that’s stable enough to be used in your project. This can be done with some pre or post build events, but things can eventually get wrong.

 

If you feel my pain, please vote on:

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=416020

2/16/2009

TF26212: Team Foundation Server could not save your changes.

I created a new WIT (work item type) to track progress of a set of activities we have here. Let’s call it “Setup”.

I wanted to restrict the users that create a new instance of the work item. The way to do this in TFS is to put a restriction on the state transition from “” to the first state of your workflow: “FirstStep” in our case.

To make things easier, I gave the group the same name of the WIT: “Setup”.

So I ended with something along the following lines:

<?xml version="1.0" encoding="utf-8"?>

<witd:WITD application="Work item type editor" version="1.0" xmlns:witd="http://schemas.microsoft.com/VisualStudio/2005/workitemtracking/typedef">

  <WORKITEMTYPE name="Setup">

    <WORKFLOW>

      <STATES />

      <TRANSITIONS>

        <TRANSITION from="" to="FirstStep" for="[project]\Setup" />

      </TRANSITIONS>

    </WORKFLOW>

  </WORKITEMTYPE>

</witd:WITD>

 

The problem is that when I tried to save a new instance of the work item, I received the following message from TFS:

TF26212: Team Foundation Server could not save your changes. There may be problems with the work item type definition. Try again or contact your Team Foundation Server administrator.

That really doesn’t help…

After some research I found a blog post with a solution to the problem.

The problem is you should not have a WIT with the same name of a TFS group in whatever Team Projects you have.

2/11/2009

You probably shouldn’t be using ReDim Preserve inside a loop

These days I was doing a code review when I went across a method which contained a ReDim Preserve inside a loop.

I can’t show the real code because it is from a customer’s code base, but here’s a simplification of what I found:

    Sub CopyAndPasteOrientedProgramming()

        Dim c As New Customer()

        For i As Integer = 0 To 250000

            ReDim Preserve c.Orders(c.Orders.Length + 1)

            c.Orders(c.Orders.Length - 1) = New Order()

        Next

        Console.WriteLine(c.Orders.Length)

    End Sub

 

I found the developer who checked in the code and went on to tell him to use a List(Of Order) and he replied “Oh, don’t bother with that. It’s just a piece of code that I copied from a similar class and since it doesn’t have a business rule for adding the elements, I took off the If statement.

Wait a minute, I said. You’re telling me there’s more code like this scattered throughout the code base?

Yup, he said.

So to simplify, the business rule I’ll use will be the order being a multiple of 3:

    Sub ShowRedim()

        Dim c As New Customer()

        For i As Integer = 0 To 250000

            If i Mod 3 = 0 Then

                ReDim Preserve c.Orders(c.Orders.Length + 1)

                c.Orders(c.Orders.Length - 1) = New Order()

            End If

        Next

        Console.WriteLine(c.Orders.Length)

    End Sub

 

The problem with the code is that for each iteration of the loop, a new array will be created with one more element than earlier and the previous array will be copied into the new one. Yeap… It’s going to create 250,000 arrays on the first sample and 83,334 on the second. Poor Garbage Collector!

A smarter decision would be to use a generic List. If you don’t initialize its capacity, it’ll default to 16 when you add the first element. Then it will double in size each time it reaches its capacity. I’m too lazy to do the math but I guarantee you that it’s far less than the previous example.

    Sub ShowList()

        Dim c As New Customer()

        Dim o As New List(Of Order)

        For i As Integer = 0 To 250000

            If i Mod 3 = 0 Then

                o.Add(New Order)

            End If

        Next

        c.Orders = o.ToArray()

        Console.WriteLine(c.Orders.Length)

    End Sub

 

This is a very simple alternative. If you really want to be clever and you have an idea of the percentage of orders that will fulfill the criteria, you can initialize the List with a meaningful capacity.

So please stop using ReDim Preserve inside loops!!!

 

 

PS. List(Of T).ToArray() creates a new array, but when compared with the original code that doesn’t hurt, does it?

TS: Visual Studio 2008 Team Foundation Server

I've been working a lot with TFS lately and I knew there was an exam for TFS 2005 (70-510 -> TS: Visual Studio 2005 Team Foundation Server) but I wasn't sure if there was one for TFS 2008.
It looks like there won't be one since there were few changes besides those found in Team Build in 2008.
2/10/2009

Warnings TF26171 and TF26204 during WIT import on TFS 2005

When restricting the users or groups that can transition states of a work item type, there’s a little something you should pay attention to.

Lets say you want to restrict who can create a given type of work item to users of a custom “NewTesters” TFS Group. The docs says you should do something as follows:

<TRANSITION from="Resolved" to="Complete" for="[project]\AllTesters" not="[project]\NewTesters">
</TRANSITION>

On the “for” attribute some people may think that “[project]” is a place holder for the project's name, but it is meant as a literal.

If your Team Project is named TheGreatestProjectEver, you should use "[project]\AllTesters" literally as stated in documentation and not " TheGreatestProjectEver \AllTesters"

Using "TheGreatestProjectEver \AllTesters" will return:

“Warning: TF26171: (User/group {0} is not found.

TF26204: The account you entered is not recognized. Contact your Team Foundation Server administrator to add your account.”

2/9/2009

Book on MSBuild and TF Build

  
 
 
Adding to my wish list at Amazon.
2/7/2009

TeamBuildTypes and Source Control Restructuring Gotcha

As part of implementing branching for the project I’m currently working on, I had to do some restructuring of the source control folder structure.

The structure was generally well organized except for the fact they didn’t take branching into consideration when setting up the folder structure:

$

  • Project
    • AnalysisServices
    • Assemblies
    • DatabaseObjects
    • IntegrationScripts
    • Models
    • OldLabBranch
    • TeamBuildTypes
    • Etc.

I wanted to create a branch in where AnalysisServices, Assemblies, DatabaseObjects and IntegrationScripts could be isolated in conjunction so new feature development could be done in parallel with regular maintenance without one breaking the other.

Using the branching guidelines I’ve talked a couple of posts ago, I managed to structure the folders as below:

$

  • Project
    • OldLabBranch
    • Main
      • Sources
        • AnalysisServices
        • Assemblies
        • DatabaseObjects
        • IntegrationScripts
      • TeamBuildTypes
    • Models
    • Etc.

The problem with this setting is that your Team Build Types won’t show up in Team Explorer 2005 because it has a dependency of TeamBuildTypes being a direct child of your Team Project’s folder. Moving back TeamBuildType to $/Project did the trick and everything worked fine.

$

  • Project
    • OldLabBranch
    • Main
      • Sources
        • AnalysisServices
        • Assemblies
        • DatabaseObjects
        • IntegrationScripts
    • Models
    • TeamBuildTypes
    • Etc.

When we upgrade to TFS 2008, I’ll move back TeamBuildTypes to the place recommended by the guidelines as they really do make sense.

2/5/2009

Some of the properties associated with the solution could not be read

There are times when loading a solution in Visual Studio 2005 you get a “Some of the properties associated with the solution could not be read” but the solution is nonetheless loaded.

There’s a KB about it, but the problem we had here had nothing to do to what’s being described on the article.

The problem lays on the fact that for some reason, the TFS source control section of the solution file got duplicated and there were multiple instances of it:

GlobalSection(TeamFoundationVersionControl) = preSolution

….

EndGlobalSection

 

To fix the problem:

  1. Unbind the solution from source control
  2. Open the .sln with Notepad and make sure you delete all of the “GlobalSection(TeamFoundationVersionControl) = preSolution” sections from the file.
  3. Bind the solution to source control again.

With that, Visual Studio will recreate the section properly and you should stop receiving the message.

1/28/2009

Branching and Merging

This week I’m taking a look into branching and merging strategies in TFS.

VSTS Rangers and MVPs have released guidance for both TFS 2005 and 2008.

Even if you’re using 2005, if you want to dig into a little more details, you should take a look into the 2005 version of the guidance.

Microsoft Team Foundation Server Branching Guidance – Home (for TFS 2005)

TFS Branching Guide 2.0 – Home (for TFS 2008)

And by the way, yesterday I ordered Juan-Luc’s Professional Team Foundation Server from Amazon. It should arrive in two or three weeks.

1/24/2009

TFS Podcast

Recently I’ve been doing some stuff with TFS so I added TFS Radio to the set of podcasts I hear regularly.

http://www.radiotfs.com/

1/15/2009

Running away from Windows Vista

With the launch of Windows 7 beta, a couple of my Messenger buddies have started putting “Running Windows 7” as their quick message. I think I’ll put “Running away from Windows Vista” as mine. :P

Just kidding. Despite all the bad press about Windows Vista, I’ve been using it on a daily basis for almost a year now on a desktop at home and a laptop at work. In both cases, the machines came with Vista pre installed and work fine.

My desktop at the customers site is still XP as is an old desktop that I have at home. I also have a personal laptop with XP whose hard drive crashed last week. I’m thinking on installing the Windows 7 bits on it to take a spin.

Stay tuned.

1/3/2009

Resoluções de 2009

Uma das minhas resoluções de 2009 é praticar mais esportes.

Em 2008 eu já vinha praticando moutain bike e caminhada(mais)/corrida(menos).

Em 2009 espero não passar tanto tempo sem praticar estes dois esportes e quem sabe arrumar alguma outra coisa pra fazer.

No dia 31 eu corri a São Silvestre. Sim eu corri! Corri sem parar os quatro primeiros quilômetros, mas corri.

O resto eu alternei entre caminhada (mais) e corrida (menos), mas completei a prova e senti que tinha energia para ter exigido mais de mim mesmo correndo mais e caminhando menos.

 

 

 

Minha meta atual é conseguir completar 5K correndo direto. Depois disto a meta passa ser baixar os tempos de 5K e começar a tentar completar 10K diretos. Quem sabe no final do ano eu consigo completar a São Silvestre correndo direto?

 

  

12/7/2008

Podcasts on iPod

Recently my 2nd generation iPod Nano got broken and after a little research at Apple’s site I decided to buy an iPod Touch.

I went to a store here in Brazil and bought one only to discover that it was a 1st generation iPod Touch while the one shown on Apple’s site was a 2nd generation one.

The 2nd generation iPod has some features I really wanted so I asked for a friend to bring me one from the US:

  • Built-in sensor for Nike+
  • Hardware buttons for volume
  • Speaker

By the way, it also has a faster ARM processor.

 

 

Before getting the new toy, I used to automatically download audio podcasts via iTunes. I also used to manually download videos from Channel 9 to watch on my desktop. Now I setup iTunes to download automatically all the audio and video podcasts I’m interested in. Here are some of the technical ones:

 

Title

Description

Alt.NET Podcast

Alt.NET Podcast about TDD, BDD, DDD, DI, IoC, and other acronyms

Channel 10

[Channel 10]

Google Developer Podcast

The Google Developer Podcast features interesting news in the developer world from a Google perspective. Listen to interviews with Google Developers and the community as a whole.

Hanselminutes

Hanselminutes is a weekly audio talk show with noted web developer and technologist Scott Hanselman and hosted by Carl Franklin. Scott discusses utilities and tools, gives practical how-to advice, and discusses ASP.NET or Windows issues and workarounds

.NET Rocks!

.NET Rocks! is an Internet Audio Talk Show for Microsoft .NET Developers.

OnMicrosoft (Video)

Conversations & tips from expert IT Pro’s & Developers covering a wide range of programming, systems, & software issues: .NET Framework, WCF, WPF, ASP.NET  AJAX, Silverlight, PowerShell, VSTS, VSTO, LIN, SQL Server, Data-binding, and SharePoint.

OnSoftweare (Audio + Video)

Conversations & tips from the industry’s leading developers across a wide range of programming and development topics: Java, Agile, Software Engineering, Design Patterns, C++, C#, Ruby, Lean, Software Quality, Secure Coding, User-centric Design, and more.

Videos – Channel 9

videos

Descriptions were taken from the feeds themselves. That’s why Channel 9 and 10 aren’t so descriptive.

11/7/2008

Fantastic Four

To celebrate the announcement of .NET Framework 4.0, here are four links to stuff I found interesting enough to share with you guys:

  1. .NET 4.0's game-changing feature? Maybe contracts...
  2. What's New in the BCL in .NET 4.0
  3. Code Contracts - Make Coding Assumptions Explicit and Tool Discoverable in .NET
  4. Microsoft Solver Foundation - Customer Technology Preview

The main point being that it looks like we’re going to gain Design by Contract (pre-conditions, pos-conditions, etc.) features in the next version of the framework.

Although there are people not very happy about it being a feature of the framework library instead of the language, I’d like to remember that it is totally possible that in the future, the language incorporates syntax sugar that beneath uses the library’s features.

LINQ, “using”, “lock” all use .NET Framework class library methods under the covers, so there’s still hope! If today we have “int?” as a shorthand for Nullable<int>, how cool would it be to have something like “Customer!” for a non-nullable Customer parameter, field or variable!

Most of this design by contract stuff is based on ideas from Spec# – a research language developed by Microsoft Research.

11/1/2008

Poster do .NET Framework 4.0

Durante o PDC que rolou lá nos “States” esta semana, a Microsoft liberou a primeira versão preliminar pública do .NET Framework 4.0, Visual Studio 2010 e os planos sobre um monte de outras coisas como o Windows Azure, Windows 7 e por aí vai.

Eu já estou com a minha VM do VSTS 2010 aqui, mas ainda não tive tempo de mexer muito com ele.

A primeira coisa que percebi foi que a Start Page parece ser feita com WPF. Estou bastante curioso para ver o que vem no C# 4.0.

Eles também lançaram um poster sobre as novidades que vieram com a SP1 do Fx 3.5 e o que deve vir no 4.0.

Você encontra uma versão online usando Deep Zoom aqui.

Tem um monte de vídeos a respeito disto tudo lá no Channel 9 .

Bem legal!

9/21/2008

TechEd 2008

O TechEd está chegando aí (14 a 16/10) e contará com a presença de ninguém mais ninguém menos que Steve (Developers! Developers! Developers!) Balmer.

Os preparativos já estão a toda. Este ano estarei ministrando duas palestras:

  1. DEV301 - 300- 14/10/2008 14:00 - 15:15 - Sala 2 Melhores Práticas com a Linguagem C# 3.0
  2. WEB301 - 300 - 15/10/2008 09:15 - 10:30 - Sala 7 Internet Explorer 8 Para Desenvolvedores (junto com Miguel Ferreira)

Na palestra “Melhores Práticas com a Linguagem C# 3.0”, eu vou demonstrar os recursos que a linguagem ganhou na versão 3.0 e a melhor forma de usá-los. Também pretendo abordar os principais erros e gotchas que tenho encontrado por aí ao desenvolver o meu código e revisar código dos outros.

Na palestra “Internet Explorer 8 Para Desenvolvedores” eu e o Miguel Ferreira (PM do Windows) vamos mostrar o que o IE8 está trazendo de novidade para os desenvolvedores.

Além disto, estarei respondendo a perguntas no Ask The Experts. Para quem nunca participou de uma sessão destas, é uma chance de ter as suas dúvidas respondidas ali ao vivo e a cores. Imagina como um Fórum MSDN tête-à-tête. Imperdível!

9/6/2008

Object creation with generics

Last week I was reviewing some code when I came across something that looked like.

class TypeTranslator<TOrigin, TDestination> {
    public TDestination Convert(TOrigin value) {
        Type typeOfTo = typeof(TDestination);
        TDestination to = (TDestination)typeOfTo.InvokeMember(null, BindingFlags.CreateInstance, null, null, null, CultureInfo.CurrentCulture);

        // goes on and copies the contents of each property from the TFrom object instance to the TTo object instance
        return to;
    }
}

 

The idea is to translate entity types to data transfer types. The class receives the origin and destination types upon instantiation and when Convert is called it creates a new instance of the destination type and populates its properties from the origin type enumerating through all its properties via reflection.

We all know that reflection is slow when compared to accessing the types and members directly, but the real problem on this code lays on the fact that it tries to instantiate a new object using a parameterless constructor, but there is no guarantee that the class has one.

It has all been working based on the convention assumed on the project that these types will all have a public parameterless constructor. What happens if a new developer comes in and unaware of the convention decides to create a constructor with parameters? The compiler seeing that there's a constructor will not create the default parameterless constructor anymore. Since there's nothing else checking it, it will only fail at runtime.

A runtime exception would be caught relatively early if they were using unit testing, but they aren't using it, so it depends on trusting the developer to do the proper tests.

Well, I'm a developer, but I trust more on the compiler doing that job than on myself or whoever for that matter, so I proposed some changes:

class TypeTranslator<TOrigin, TDestination> where TDestination : new() {
    public TDestination Convert2(TOrigin value) {
        TDestination to = new TDestination();
        // goes on and copies the contents of each property from the TFrom object instance to the TTo object instance
        return to;
    }
}

This way, the compiler will guarantee that the type used has a parameterless constructor. Finding issues at compile time is much cheaper than at runtime.

Live Search - Se eu pudesse pelo menos experimentar...

Eu sou usuário do Google a vários anos.É realmente uma ferramenta de busca fantástica.

O Live Search deixava muito a desejar quando foi lançado. Eu ouvi dizer que melhorou muito, mas infelizemente já a alguns meses, eu não tinha como experimentar...

Tanto de casa quanto nos diversos projetos que passei nos últimos meses, o acesso à internet era provido pela Speedy. Coincidência ou não, em nenhum destes lugares o browser conseguia abrir a página de resultados de busca (http://search.live.com/results.aspx?q=mulher+pelada&form=QBRE, por exemplo).

Como usuário do Google, eu pensava... Ah.. Deixa pra lá, vou fazer a pesquisa no Google mesmo.

 

Hoje eu resolvi gastar um minutinhos nisso e consultei alguns camaradas daqui de São Paulo e de fora do estado e o resultado foi o seguinte:

Todo mundo que acessava via Speedy, não conseguia abrir o site.

O pessoal de outros estados conseguia.

Eu já desconfiava que fosse "sacanagem" do DNS da Telefônica, mas a experiência deixou isso mais claro.

Fazendo uma busca por "live search speedy telefônica dns" no Google eu acabei encontrando algumas páginas com pessoas descrevendo problemas parecidos finalmente uma relação de servidores DNS em http://www.abusar.org/dns.html

Configurei o meu DNS para o www.opendns.org (208.67.222.222 e 208.67.220.220) e Live Search voltou a funcionar.

Salvei a relação de servidores DNS aqui  na máquina para o caso de precisar novamente.

Tchau DNS da TelefoZica!

8/30/2008

Volta on IEEE magazine.

I haven't played with it for a while but the Volta folks released an article on IEEE magazine.

If you're in to developing distributed applications, you should take a look at it.

Keep it simple (and help to save the planet)

Today I came across a piece of code like the following.

Dim strSQL As New StringBuilder
strSQL.Append("SELECT ")
strSQL.Append(" ProductID, ")
strSQL.Append(" Name ")
strSQL.Append("FROM Production.Product")

Try
    cnnConn.Open()
    Dim cmd As New SqlCommand(strSQL.ToString, cnnConn)

When I encounter code I don't agree with, I try to understand what made the developer code it that way.

Looking at this one I can only presume:

  1. He wanted to make his code more legible by separating the SQL Command to different lines.
  2. In doing that, he wanted to avoid string concatenation, because "string concatenation is performance wise evil"!

My answers to these points are:

  1. In this particular case, the code became harder to read than if it was stated in a single line.

    Dim strSQL As String = "SELECT ProductID, Name FROM Production.Product"


  2. That may be true in a lot of situations, but is not true in this particular one: concatenating small string constants, as the compiler is smart enough to generate one single string constant comprised of what we see in code as being multiple strings being concatenated

    Dim strSQL As String = _
    "SELECT " + _
        " ProductID, " + _
        " Name " + _
        "FROM Production.Product"

    Try
        cnnConn.Open()
        Dim cmd As New SqlCommand(strSQL, cnnConn)


    gets compiled to

    L_001f: ldstr "SELECT  ProductID,  Name FROM Production.Product"
    L_0024: stloc.1
    L_0025: nop
    L_0026: ldloc.2
    L_0027: callvirt instance void [System.Data]System.Data.SqlClient.SqlConnection::Open()
    L_002c: nop
    L_002d: ldloc.1
    L_002e: ldloc.2
    L_002f: newobj instance void [System.Data]System.Data.SqlClient.SqlCommand::.ctor(string, class [System.Data]System.Data.SqlClient.SqlConnection)


 

* Q: So what does this post has to do with saving the planet?

A: Keep it simple -> spend less processor cycles -> spend less energy -> ... -> ... ->.... Oooh... you get it!

8/19/2008

Parlophone @ YouTube

A Parlophone, gravadora de bandas como Radiohead, Cold Play, Blur, The Verve, entre outros firmou parceria com o You Tube.

Já foram disponibilizados mais de 180 vídeo-clipes. Vários deles (se não todos, não fui atrás pra conferir) estão disponíveis em alta-resolução

Simplesmente imperdível!

http://www.youtube.com/parlophone

 

 
8/17/2008

Growing software keeping things simple

Back in year 2000 I was running my own software development company and had a small kind of ERP system targeted at small companies.

Reading about all the advantages of interfaces such as the ability to switch implementations one for another at any time, I thought: "Wow! That's amazing! I gotta do that!". So I went extracting the interfaces out of each class and making the classes refer to the interface. Soon I realized that in order to be really independent, I had also to change the methods and properties to point to the interfaces so I could change the object being passed to them.

Several weeks later I had it all done and working, but those were several weeks not adding new features. Only refactoring code at a time where we had no refactoring tools like today.

One could argue that I should have done interfaces from start and then I wouldn't have had all that work. OK, I agree. The problem is that all that was new for me. Still, all the work would be compensated by the possibility of switching implementations whenever I needed!!!

The problem is that time never came! OK... To be fair, there were a couple of situations where I benefited from using interfaces. And that only became possible because I got a new insight, a new way of seeing the world - through interfaces. But for the most part, it was an overkill. When modifying a class, instead of having one place to change, now I had two!

It has been attributed to Albert Einstein that “Everything should be made as simple as possible, but no simpler

After so many years of developing software I came to appreciate simple designs.

I think about the ways the code might evolve in the future and instead of putting in things that pave the way to this predicted future, I tend to leave out the things that would otherwise make it more difficult to get there.

The reason for this is that the predicted future may never come to realization. So by putting in stuff now, I would eventually be throwing resources away. Resources that may be needed for something else.

It gets even worse when - driven by real needs - you find yourself having to accommodate changes that go in another direction that eventually are incompatible with what was initially predicted.

All of this has already been explained by people much better with words than I am. Take a look at YAGNI, KISS and DRY.

The bottom line is: Grow you software simple. Only add complexity when really needed. Even then, try to keep it as simple as possible, but no simpler. :)

8/2/2008

Download gratuito de música - Legalizado e com remuneração do artista

Na semana passada eu descobri o Álbum Virtual da Trama.

Eles estão com uma idéia bem legal que é a de todo mês eles definem um orçamento e rateam a grana para os artistas que estão no site baseado no número de downloads.

Na semana passada haviam 3 bandas/artistas:

Cansei de Ser Sexy - Bem legalzinho

Tom Zé - Pura viagem. Provavelmente não escutarei novamente

Macaco Bong - Ainda não escutei.

Os álbuns ficam disponíveis por tempo limitado, então é bom estar checando o site de tempos em tempos para ver o que aparece de novo por lá.

Tem um videozinho lá no YouTube falando do projeto:

 
7/23/2008

Preparing for Beta Exam 70-660: TS: Windows® Internals

Microsoft Advanced Windows Debugging and Troubleshooting team disclosed the exam preparation information for 70-660 (71-660 while in beta).

You'll find what you need to know at: http://blogs.msdn.com/ntdebugging/pages/exam-preparation-information-for-exam-71-660.aspx

Since there currently is no prep material, I'll recommend some books that I think will help prepare those who might want to take this exam.

First and foremost is Mark Russinovich's Windows Internals currently in the 4th Edition. The 5th edition should be released later this year.

 

These books will give you the fundamentals of Windows internals.

For get a developer's perspective on Windows internals reach out to Jeffrey Richter's Windows via C/C++.

To get insight into debugging take a loot at John Robbin's Debugging Applications for Microsoft .NET and Microsoft Windows :

  

I've read a few chapters from it - mostly the managed code debugging ones, but there's a lot of information on native debugging.

Although I haven't read Advanced Windows Debugging, is has been highly recommended, so I'll list it here too.

That is a lot of stuff to read and study and it sure is not an exhaustive list. For just one exam! But what did you expected from an exam that caters:

     "Candidates for this exam are typically in the upper echelon of the technical staff at their companies."

So get prepared and good luck!

 
Photo 1 of 56

Certifications

Alfred Myers

Occupation
Interests
MVP Visual Developer - Visual C#, MCT, MCPD Enterprise Applications Developer, MCSD.NET, MCITP Database Developer

MVP Visual C#

Xbox Live

Alfred Myers
Xbox Live GamerCard
Rep:
3/5 stars
Score:
0
Zone:
Recreation