Outlook Error. Could not open Outlook Window

Today, I suddenly started receiving the above error. Among the many fixes for this situations depicted here, what worked for me was Method 3: Resetting the Navigation pane.

To do so, just select Start->Run and then type “outlook /RESETNAVPANE”. It worked for me.

Read the instructions on the above link about what side effects can have resetting the navigation pane.

Cheers!

Enabling DivX/MKV video playback from USB device in Samsung LED B6000

Since last year, I´m one of the happy owners of this magnificent 46” LED TV:

Samsung UE40B7000

There is just one thing that I was missing: DivX/MKV video playback from USB devices.

Last week, a friend bought a Samsung Series 6 too, but the LCD version. I was shocked when I saw this TV included the option to play videos from USB devices, so I decided to investigate a bit if it was possible to activate that option to mine, via a firmware upgrade or so. AND IT WAS!

The best part is you don´t need even to upgrade your firmware, it´s just a matter of changed several values in the service menu of the TV.

DISCLAIMER you enter the service menu at your own risk, altering the wrong settings in the service menu could result in your TV not functioning as it should
Note: This operation might work on some firmware versions only. Google a bit around to find more information about this. With mine, it worked fine.

1.- Enter service menu

With the TV in StandBy mode (off), press the following remote control buttons, one by one: Info, Menu, Mute and then switch the TV on by pressing Power. When the TV turns on, you will see some menus like the following:

The navigation in this menu is done by pressing up/down only. Keep in mind that pressing right means enter the selected option. Be very careful to not change any value accidentally. That can be catastrophic for your TV.

2.- Make the following changes in the Service Menu

First, change the model number of your screen, from B6000 to B7000. This will enable the WiseLink Movie option: Enter the “Option” submenu, navigate to “Model”, press right, and then press right several times until you change from B6000 to B7000.

In Control->Sub Option menu, turn ON the following values:

  • WISELINK MOVIE
  • WISELINK WRITE
  • HIGH DEVI

3.- Results

Done. Now you have video playback support from USB devices. I have tried several movies and not all of them have been correctly played, but must of them yes.

What you will have:

It supports DivX, XVid, and MKV. I also tried several movies in HD (both 720 and 1080), and they worked well. Also AC3 audio seems to work.

What you won´t have:

Subtitles, dual audio, picture size formats, navigation (only 2x forward)

However… ¡¡¡¡¡¡ IT´S A GREAT IMPROVEMENT !!!!!!

Cheers

Simax en el Microsoft Innovation Day

María Garaña, en BilbaoEl pasado Martes, 1 de Junio, Microsoft celebró en Bilbao el primer Innovation Day, donde nos mostró las tendencias en innovación que la corporación está investigando, así como los nuevos productos que llegan al mercado en los próximos meses. Hablaron de Natal, el cual se espera en el mercado para finales de año, hablaron de Mavis, un sistema de indexación de contenidos de video impresionante, de Photosynth, un sistema bastante impresionante que genera fake cubemaps 3D a partir de fotos normales geo-posicionadas, por supuesto de Azure, Windows Phone, Zune HD, de las nuevas tendencias en educación, en sanidad, en el hogar del futuro. En fin una gozada.

Simax estuvo invitada a una de las ponencias como “caso de éxito”, según Microsoft, junto con la directora de Indisys, otra gran empresa con una tecnología que aplica la inteligencia artificial para aplicativos del lenguaje natural, realmente impresionante.

Directivos de Intel dejaron ver ordenadores portátiles especialmente diseñados para niños, que resisten incluso caídas desde 60 cm de altura (impresionante ver al ponente dándole patadas). Me gustó mucho un gráfico que mostraron de la tendencia en disipación de calor que seguían los procesadores de tecnología Pentium. De no haber cambiado de tecnología, ahora mismo un procesador disiparía por cm2 el mismo calor que la tobera de una lanzadera espacial. Gracias a la evolución tecnológica, la reducción del tamaño de los transistores, y a la paralelización, se ha conseguido reducir el consumo de forma dramática. Por cierto, Intel tiene un prototipo de procesador (por el momento para estaciones de computación), con ¡¡¡80 núcleos en un solo chip !!!

También me gustó mucho la ponencia de César Gaicoya, reputado arquitecto, y uno de los artífices del museo Guggenheim de Bilbao, junto a Frank Gehry. Mostró el proceso de diseño y fabricación que siguieron en el museo, haciendo hincapié en los puntos donde más se innovo (que no fueron pocos). Se me caía la baba, la verdad…

En fin, un gusto.

Strange physics or math results since August 2009 release of SlimDX

Logo

If you use the magnificent SlimDX (something that you should definitely do), and have been experiencing strange issues with maths or physics, keep reading.

Quaternion Multiplication Issue

As you probably know, Quaternion multiplication is not commutative. This means that “a*b” is not the same than “b*a”.

It seems that XNA and D3DX implement this algorithm in exactly the opposite way, so for the operation: Multiply(Quaternion left, Quaternion right), one does left*right and the other does right*left.

Since the August 2009 release of SlimDX, they changed the way this operation was being done, as they thought they were previously doing it wrong. That’s why you might be getting strange maths or physical results if you install any version newer than March 2009.

I write this post because, believe me, this kind of errors are pretty difficult to trace (if you don’t pay the needed attention to Release Notes, as we did). In our case, we were suddenly getting erratic Rigid Body behavior, but everything else seemed to be working fine.

Of course, the first reaction was to think that some change in our code was to blame. It was obviously something related to maths, vector operations or matrices maybe, but after checking everything for some time, we saw no change related to that.

Then we realized it had something to do with the SlimDX update, so we started checking all the changes done to the library since March 2009, looking for changes in Math code. et voilá: revision 1199: Quaternion multiply was backwards. That was making our rigid bodies go crazy…

We should definitely read the Release Notes of each new version better next time.

Warning

According to this issue, the SlimDX team is changing the method again (back to the old way) in the next June release. So pay attention to the change.

Cheers!

XNArkanoid for Windows Phone 7

A few weeks ago I started a Windows Phone 7 port of my old XNArkanoid.

02 

It’s a C#-XNA remake of the classic Taito’s Arkanoid. This version is written in XNA 4.0 for Windows Phone. It’s not finished yet, but you can find all the information and source code at CodePlex:

arkanoidlogo original  http://xnarkanoid.codeplex.com

Targeting C++/CLI Projects to .Net Framework 3.X in Visual Studio 2010

If you work with C++/CLI projects, and recently jumped to Visual Studio 2010, you have probably noticed that Visual Studio re-targeted your project to .Net Framework 4. This is the default behavior when converting C++/CLI projects to VS2010, as some of its C++ compiler tools are only compatible with .Net Framework 4.

The problem is that sometimes you cannot jump to .Net 4 yet. Maybe because customer’s restrictions, maybe because compatibility problems with 3rd party tools, whatever… If that’s your case, you need to target to .Net Framework 3.0 or 3.5, and still want to use VS2010, you can do the following:

(Source: here and here and even better here)

1.- Change the target Framework of your project

On a C# project, you can select the target Framework by simply changing a value in a combo box. On a C++/CLI project, you will find this in the project properties page:

It´s just a read-only value, that you cannot change directly. To change it, you must edit the project´s file (.vcxproj). To do so, open it in the notepad, or better, use the new feature included in VS2010: Edit project file by right-clicking in the project and selecting the following menu entry:

image

You will end up with an xml view of the file. Search for a node called PropertyGroup. As a child node of this one, you should create another one with the form:

<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>

It might already be there or not. If it’s not, create it. If it is, just edit its value, setting the target framework version you want: v3.0, v3.5, etc, ending with something like this:

image After the change, the project properties page will reflect the new target framework

2.- Reload the project

After any change in project’s file, you will need to reload it, by closing and re-opening the solution, or by selecting “Reload Project” in the context menu of VS.

3.- Install Visual Studio 2008 SP1

If you remember, we said that the VS2010 C++ compiler tools were not compatible with any Framework other than 4.0. That’s why as soon you change the target Framework and recompile, VS2010 will try to use the C++ compiler tools of Visual Studio 2008. If they are not present, it will stop the compilation with an error, requesting you to install VS2008.

Just a quick note: you need to install also the Service Pack 1 to VS2008.

4.- Issues

In my case, and with my specific project, the Microsoft C++/CLI Optimizing Compiler crashed if I targeted the project to .Net Framework 3.5. I really didn’t investigate why, as I really wanted to target v3.0 and didn’t have much time. Targeting v3.0 worked just fine.

So if you find the same error and find the reason or a solution, please comment!

Cheers!

Dependency error on Visual Studio 2010 Setup project

Since I moved to Visual Studio 2010, I have had several issues with Setup Projects. They convert from 2008 just fine, but I have detected some misbehaviors, specially related to DLL dependencies.

This morning, I came to a situation where Visual Studio always detected a DLL dependency which should not exist anymore. I tried marking the dependency as non-vital, excluding it. Nothing worked. My EXE file no longer depends on that DLL, but it was still there, and as it was an automatically detected dependency, I could not delete it. I tried even to set the DLL in the proper location (where Visual Studio was supposedly searching for it), but it didn’t work either. Visual Studio was still complaining about DLL not found.

The only thing that seemed to work momentarily was re-adding the EXE file that supposedly was dependant on that DLL. That fixed the DLL not found errors, but then appeared another one: “Unable to update the dependencies of the project”.

Searching a bit about this last message, I’ve found this post talking about garbage in project’s dependencies. Clayton James explains how to get rid of that error, cleaning the project by yourself in notepad. I found that information very useful.

However, in my specific case, it was not necessary to wipe all the Hierarchy and Files nodes (what wipes your solution too, making you to re-add all your files to your setup project). In my case it was enough with removing the references to the conflicting DLL from the Files section. That made the trick.

Hope it helps.

Getting audio from your computer to your TV Speakers… a usual headache…

Taking the audio signal from your computer to your LCD/LED screen speakers is sometimes very easy, and sometimes quite tricky, depending on the model and builder of your graphics card. If you want to do so, there are several things you should be aware of:

First, you should know that nowadays this operation is possible both through HDMI and DVI ports, as today's graphics cards can take audio out from DVI ports too (using a DVI-HDMI cable or an adaptor).

Second, remember that you have two options to take audio from your computer to the LCD screen:

1.- Use external analog audio through a Jack-Jack or Jack-RCA cable (depending on the analog audio input of your screen)

2.- Use digital audio through the HDMI cable (available on every screen)

If you want to use the first option, you will need to configure your computer to use the Speakers as the default audio device. If you select the second option, you will want to set your Digital HDMI audio device as default.

Where to do so? In Start->Control Panel->Sound:

image

The good thing about second option is that it uses just one cable for both audio and video, but in Both options you will have to deal with other configuration issues to make them work with the TV Speakers:

Different audio behaviors depending on HDMI input port

TV Screens usually include several HDMI input ports, and they behave differently regarding audio input. The typical options are:

  • HDMI port only: The TV will try to get audio from HDMI cable only
  • HDMI/DVI port: This kind of HDMI input usually has a external Jack or RCA audio input just by it. The thing is that some TVs will always take audio from that external jack, and some will decide when to get audio from HDMI or from those external Jack/RCAs automatically, and this is the most usual cause of problems.

In those that make this decision automatically, when they decide one option or the other? If the computer is “telling” the TV that the HDMI cable has audio, the screen will take audio from there. If not, it will take audio from the external Jack/RCA.

So, if you want audio to go through an external analog jack-jack cable, HDMI should carry NO AUDIO (so the screens takes audio from the external cable).

Now, next step is: how to control when the computer sends audio through HDMI or not?

Controlling the presence of audio in the HDMI cable

This task is to be managed by the graphics card, as it’s the graphics card who put signal on the HDMI cable. So, you will need to go to the nVidia Control Panel to adjust this option (under the Change Resolution tab). If the graphics card detects the presence of a HDMI or DVI cable, it will offer the possibility to enable or disable Audio on the wire (see next picture):

image

This is what tells the TV if the cable carries audio or not. It sometimes happens that you change this option, click apply and the screen doesn’t detect the change. If that’s your case, force the screen to notice by switching to a different resolution, and then switching back to the original one, with the selected audio option. You normally can tell if the screen noticed the change by a small blink or by the screen going black for a moment.

I don’t want two wires… HDMI audio rocks!

So, you want audio to go through HDMI? Good option…. Let’s see how to do it:

We already know the basic steps:

  • Set your HDMI (not the speakers) as default audio device (Start->Control Panel->Sound)
  • Set your graphics card to enable audio on HDMI (nVidia control panel)
  • Connect your HDMI cable to a HDMI input port of your screen (if you want to avoid problems, better select a normal HDMI input, not the HDMI / DVI).

There is an additional step needed for this:

Connecting the S/PDIF cable

Didn’t you ask yourself how is it possible that graphics cards take audio out through the HDMI cable? The S/PDIF cable (Sony/Philips Digital Interconnect Format) is the answer. It will take digital audio from your motherboard (taken from a standard interface with the sound card) to the graphics card, and the graphics card will output it to the HDMI cable. This cable is usually a very small, two pin cable, supplied with your graphics card:

See your motherboard and graphics card’s manuals to locate the two pins where to connect the cable. They are also usually marked in the board with labels like: SPDIF or AUDIO. The following are some examples:

image

A unusual case: The Point Of View GeForce GTX 260

This last week, we acquired a Point Of View GeForce GTX 260, just like this one:

P1000197

We had to invest quite some time in order to make audio work with this card:

1.- The card came with a SPDIF cable, and although the manual mentions the possibility to use it, it didn’t specify where to connect it. There are two free pins in the card but it doesn’t say SPDIF or AUDIO anywhere. Initially, they seem to be some kind of jumpers, as they are marked as JP0 and JP1.

2.- So, we tried using external analog jack-jack, but the nVidia latest driver (197.45) seemed to fail disabling HDMI audio on this card, so our Samsung LCD screen always selected HDMI audio as source. No luck…

3.- As nothing worked, we decided to take the risk and to connect the SPDIF cable to those JP0 and JP1… et voilá! That did the trick. Now we have digital audio running on HDMI.

No manual, specs or information we could found on Point Of View will tell you where to connect the SPDIF cable, so for your reference, here is how you should connect it (white on the right, red on the left, from this perspective and with this connection on the motherboard):

P1000196

Hope it helps.

Take Care!

Integrate CopySourceAsHTML into release version of VisualStudio 2010

CopySourceAsHTML is one of the most useful tools for developers who blog or post code in any form. Now that Visual Studio 2010 is out, it’s time to integrate both tools.

They released a patch and a new version which technically supports 2010, but it was released for the beta version (I guess), and now it doesn´t integrate well with the release version. As Sean mentions in his blog, all you need to do is:

1.- Download CopySourceAsHTML from here

2.- Install it normally, selecting VS 2010 support (it won´t register well in the program though).

3.- Go to the CopySourceAsHTML installation directory, typically:

C:\Program Files (x86)\J.T. Leigh & Associates\CopySourceAsHtml

4.- Copy the contents of the folder

5.- Find what folder is VStudio using for storing the AddIns (there is more than one), in Tools->Options->Add in/Macros Security. Typically (you might have to create this folder):

C:\ProgramData\Microsoft Visual Studio\Addins

6.- Paste the addin file there, re-launch VStudio, and make sure it’s enabled:

Add-in Dialog

7.- Open the file "CopySourceAsHtml.2010.AddIn” and open it with a text editor (it´s an XML file). In every entry <version>9.0</version>, replace the “9.0” with a “10.0”.

And that´s it!

Best video player for Windows Mobile PocketPC

After testing CorePlayer and some others, I have to say that I moved back to TCPMP again. CorePlayer is great, and it´s greatly optimized for handheld devices, but lacks AC3 audio support.

TCPMP on the other hand, although it has been deprecated, perfectly supports AC3 and many other formats, and is still the best player for WM devices.

There is a recomp version specifically compiled for Windows Mobile 6.1 that works flawlessly, and includes most of the plugins available.

You can download from here:

http://www.htcmania.com/showthread.php?t=51241

Don´t worry, it´s free.

Videogame history in a short. Revenge of the pixels!!!

One of the best animation videos I’ve seen in a long long time. It’s not just the story, which is great and remind me of great great videogame moments (watching the frog jumping across the street is priceless…), but it’s also very well done. Be sure to watch it!

 

Cheers!

Oriented Button in Windows Forms

imageThe following class is a button which can be oriented both horizontally and vertically (like in the picture of your left). Text and image react properly to this orientation and so do their Alignments. The control also includes customizable margins for the text and image inside the button and a SizePercent property for the Image. Please keep in mind that if Orientation is set to “Horizontal”, the normal Draw methods from the base class are called, so all of this properties are ignored. However, you can change this behavior or add any other property very easily if you need it.
The whole thing has been designed to use as less resources as possible (accept suggestions on this of course ;), but you can very easily add other features, like a PictureBox for the image rendering (re-using all the PictureBox features as: BorderStyle, SizeMode, etc).
You can just copy-paste the following parts of code into a class which inherits from Button, and you´ll have it. Something like this:
public class OrientedButton : Button
Hope it helps:

Declaration of variables and props

        private Orientation mOrientation = Orientation.Horizontal;
        private int mTextMargin = 5;
        private int mImageMargin = 5;
        private int mImageScalingPercent = 100;
        private System.Windows.Forms.VisualStyles.PushButtonState mState = System.Windows.Forms.VisualStyles.PushButtonState.Normal;
 
        #region Props
        [Category("Appearance")]
        [DefaultValue(5)]
        public int TextMargin
        {
            get { return mTextMargin; }
            set { mTextMargin = value; }
        }
        [Category("Appearance")]
        [DefaultValue(5)]
        public int ImageMargin
        {
            get { return mImageMargin; }
            set { mImageMargin = value; }
        }    
        [Category("Appearance")]
        [DefaultValue(Orientation.Horizontal)]
        public Orientation Orientation
        {
            get { return mOrientation; }
            set { mOrientation = value; }
        }
        [Category("Appearance")]
        [DefaultValue(100)]      
        public int ImageScalingPercent
        {
            get { return mImageScalingPercent; }
            set { mImageScalingPercent = value; }
        }
        #endregion

Mouse Events Handling

       #region Mouse Events
        /// <summary>
        ///
        /// </summary>
        /// <param name="mevent"></param>
        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            base.OnMouseDown(mevent);
            mState = System.Windows.Forms.VisualStyles.PushButtonState.Pressed;
            Invalidate();
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="mevent"></param>
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            base.OnMouseUp(mevent);
            mState = System.Windows.Forms.VisualStyles.PushButtonState.Hot;
            Invalidate();
        }       
        /// <summary>
        ///
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            mState = System.Windows.Forms.VisualStyles.PushButtonState.Normal;
            Invalidate();
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            mState = System.Windows.Forms.VisualStyles.PushButtonState.Hot;
            Invalidate();
        }
        #endregion

OnPaint Method

        /// <summary>
        /// Some code parts were taken from here: http://msdn.microsoft.com/es-es/library/f0ys5025.aspx
        /// </summary>
        /// <param name="pevent"></param>
        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);
 
            if (mOrientation == Orientation.Horizontal)
                return;
 
            // Base Button Draw
            if (mState == System.Windows.Forms.VisualStyles.PushButtonState.Pressed)
            {
                // Set the background color to the parent if visual styles 
                // are disabled, because DrawParentBackground will only paint 
                // over the control background if visual styles are enabled.
                this.BackColor = Application.RenderWithVisualStyles ?
                    Color.Azure : this.Parent.BackColor;
 
                // If you comment out the call to DrawParentBackground,
                // the background of the control will still be visible
                // outside the pressed button, if visual styles are enabled.
                ButtonRenderer.DrawParentBackground(pevent.Graphics,
                    ClientRectangle, this);
                ButtonRenderer.DrawButton(pevent.Graphics, this.ClientRectangle,
                    "", this.Font, true, mState);
            }
            else
            {
                // Draw the bigger unpressed button image.
                ButtonRenderer.DrawButton(pevent.Graphics, ClientRectangle,
                    "", this.Font, false, mState);
            }
 
            // Draw Text
            if (this.Text != "")
                this.DrawText(pevent.Graphics);
 
            // Draw Image
            if (this.Image != null)
                this.DrawImage(pevent.Graphics);
        }

The DrawText method

        /// <summary>
        ///
        /// </summary>
        private void DrawText(System.Drawing.Graphics pGraphics)
        {
            // Calc size of text (la func devuelve el size horizontal)
            SizeF sizeOfText = pGraphics.MeasureString(this.Text, this.Font);
            float temp = sizeOfText.Width;
            sizeOfText.Width = sizeOfText.Height;
            sizeOfText.Height = temp;
 
            // Calc X coord of Text           
            float x = mTextMargin;
            switch (this.TextAlign)
            {
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.TopCenter:
                case ContentAlignment.BottomCenter:
                    x = (this.Width / 2) - (sizeOfText.Width / 2);
                    break;
                case ContentAlignment.MiddleRight:
                case ContentAlignment.BottomRight:
                case ContentAlignment.TopRight:
                    x = this.Width - mTextMargin - sizeOfText.Width;
                    break;
            }
 
            // Calc Y coord of Text
            float y = mTextMargin;
            switch (this.TextAlign)
            {
                case ContentAlignment.BottomCenter:
                case ContentAlignment.BottomLeft:
                case ContentAlignment.BottomRight:
                    y = this.Height - mTextMargin - sizeOfText.Height;
                    break;
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.MiddleRight:
                    y = (this.Height / 2) - (sizeOfText.Height / 2);
                    break;
            }
 
            // Draw text
            System.Drawing.SolidBrush drawBrush = new System.Drawing.SolidBrush(this.ForeColor);
            System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat();
            drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;
            pGraphics.DrawString(this.Text, this.Font, drawBrush, x, y, drawFormat);
            drawBrush.Dispose();
        }

The DrawImage Method

        /// <summary>
        ///
        /// </summary>
        /// <param name="pGraphics"></param>
        private void DrawImage(System.Drawing.Graphics pGraphics)
        {
            float imageScaling = (float)mImageScalingPercent / 100f;
            float finalWidth = (float)this.Image.Width * imageScaling;
            float finalHeight = (float)this.Image.Height * imageScaling;
            float halfFinalWidth = finalWidth / 2f;
            float halfFinalHeight = finalHeight / 2f;
 
            float x = mImageMargin;
            float y = mImageMargin;
            switch (this.ImageAlign)
            {
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.TopCenter:
                case ContentAlignment.BottomCenter:
                    x = (this.Width / 2f) - halfFinalWidth;
                    break;
                case ContentAlignment.MiddleRight:
                case ContentAlignment.BottomRight:
                case ContentAlignment.TopRight:
                    x = this.Width - mImageMargin - finalWidth;
                    break;
            }
            switch (this.ImageAlign)
            {
                case ContentAlignment.BottomCenter:
                case ContentAlignment.BottomLeft:
                case ContentAlignment.BottomRight:
                    y = this.Height - mImageMargin - finalHeight;
                    break;
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.MiddleRight:
                    y = (this.Height / 2f) - halfFinalHeight;
                    break;
            }
            System.Drawing.Drawing2D.Matrix rotMat = new System.Drawing.Drawing2D.Matrix();
            PointF rotationCenter = new PointF(x + halfFinalWidth, y + halfFinalHeight);           
            rotMat.RotateAt(90, rotationCenter);
            pGraphics.Transform = rotMat;
 
            System.Drawing.Rectangle destRect = new Rectangle((int)x, (int)y, (int)finalWidth, (int)finalHeight);
            System.Drawing.Rectangle srcRect = new Rectangle(0, 0, this.Image.Width, this.Image.Height);
            pGraphics.DrawImage(this.Image, destRect, srcRect, GraphicsUnit.Pixel);
        }

References

http://msdn.microsoft.com/es-es/library/f0ys5025.aspx

You duplicating? You wrong…

This is not the best example for the issue, but here we go: imagine your are going to sweep your house, and that you have one of those modern brooms that can be disassembled to fit into small broom cupboards. When you start, let’s say in the kitchen, you take the broom from the cupboard, assemble it, and start sweeping. When you are done with the kitchen, you don’t disassemble it and place it into the cupboard, because you have other rooms left, do you? You would feel stupid assembling and disassembling the broom for each room, wouldn’t you?
Then why you do that when you write software?

First, some misprints of the writer

Thanks to M. Barnett for pointing out the “mounting and dismounting broom” issue. It seems that I wrote this post too fast (or too late), and I didn’t notice that “mounting a broom”, in English is more something like this:

So I changed it to “assemble” and “disassemble” which is what I meant to write the first time, I promise… ;)

Intro

This post is about some very basic thoughts, about engineering behaviors students tend to forget… It might sound obvious for experienced people, so if you are one of them, better go get a beer with friends instead of reading it. So, back to what students forget. Among others, one of the most important things to keep in mind, one that will always guide you through the right path is:
DUPLICATION IS THE SOURCE OF ALL EVIL IN THE WORLD
And this applies not only to software development, but also to content management, organization and engineering in general. Damn! it even applies when you tiny up a wardrobe or clean the kitchen, as we saw in the preface.

Why is this misbehavior so usual in software?

Easy. Assembling a broom and taking it to the cupboard takes time, and therefore it is trivial for any dumb-ass to see that’s a waste of time. In software, many times it takes less time duplicating things than thinking how to avoid the duplication. It’s just a matter of Copy-Paste, when avoiding duplication can take weeks of work. That’s why duplication appears all around in bad software.

The student counter part

At this point, it’s when students tend to say:
- <<Weeks! then it is indeed better to duplicate code than loosing weeks>>
And then you play the role of the old, wise grandpa, telling them:
- <<Believe me, it’s better this way. You will thank it, when you grow older…>>

Example 1: Duplication of work - Duplication of decisions

Chronicles of a bad developer

  • Company “A”
  • Project “B”
  • You are the “Bad developer #1”
  • A simple operation: obtain the concatenated name of a user, composed as: “Name” + “Second Name” + “Last Name”
It’s just one line of code, so you come to the conclusion that it’s not worthy to think much about it. So, you leave it like that and copy-paste the line when you need it.
Some months later, project “B” has grown, becoming “big”, with let’s say 150 sub-projects. Your famous name composition operation is scattered all around, in more than 1500 places. Now imagine that the worst happens (the worst always happens), and that your boss demands a change in the way you are concatenating names. Let’s say, he wants it in the form: “Last Name, First Name”, instead of the previous. You are screwed, easy as that.
As you are a bad bad developer, first thing you say is:
- <<Boss, are you sure we need that change? I like names in the way they are right now>>
- <<Our clients don’t>> He replies…
No prob, you are a bad, but clever developer, so you think:
- <<Visual Studio will fix this, I heard somewhere that there’s a thing for these cases called Refactoring>>
Then you try to Refactor a whole sentence, and of course, it doesn’t work.
- <<Damn Visual Studio! Damn Microsoft! For things like these is why I prefer Linux! Sure that Linux knows how to Refactor a whole sentence>>
And then, you end up making massive text replacements, investing one week trying to find all the instances of the operation, and in fixing the resulting compilation errors. Of course, you forget to change 3 or 4 instances of it. That’s when you go to your boss again and say:
- <<Hey, not that bad. 3 out of 1500, that’s a 99% of success!>> 
- <<You are a 99% of an idiot>>… He replies…

Diary of the good developer

<<Monday, 36 of October of year 2124
Today, I slept well. I had breakfast and went to the office. My job for today was changing the way names are concatenated in our software. As I was clever enough a couple of months ago, and I isolated this task inside a method, all my job for today has been done in 10 secs. The rest of the day I was in the beach, getting some sun… No phone calls from my boss. No phone calls from clients… No news is good news. Life is wonderful…>>
You learned the lecture?

What lecture?

Pay attention Padawan to the following line of code:
FullName = Name + SecondName + LastName;
It doesn’t only make a name composition. It also decides how this concatenation will be done, and this is the key point. That’s what you need to understand and learn. Because duplicating work is bad, but duplicating decisions is one of the worst things you can ever do in software. I´ll put that in big so you remember it:
Remember: Duplicating work is bad, but duplicating decisions is one of the worst things you can ever do in software

Example 2: Duplication of Contents

As we mentioned, duplication is not only a software development issue.
Copy-pasting files is slower than copy-pasting code, but for sure it’s still faster than assembling and disassembling the broom ;)
That’s why many dumb-asses still don’t get it, making duplication of contents to be pretty frequent too. It’s the same stuff. You make a texture, you use it in hundreds of 3D models, and then one day you need to change it. You are screwed again man!
How to avoid duplication in this cases?
You should think about having global repositories for contents that are shared between many entities: texts, textures, sounds, xml files, whatever. Remember, duplication is the source of all evil in the world. If you find yourself doing a Copy-Paste, ask yourself if it is really necessary or if there’s a way to avoid it.

Example 3: Other, not so obvious, forms of Duplications

Imagine we have a game with the class Player, and with a property which holds his status. You know, things like “Dead”, “Alive”, “Running”, etc. At design time, we need to choose how to store that status:
  • The core C++ kings that want his player to be dead and alive at the same time (may be a zombies game?), will want his status to be an Hexadecimal Flag
  • Those who want their game to be fast and “cross-platform with their toaster”, will want his status to be an Int, you know: 0, 1, 2, etc
  • A Visual Basic developer will probably want it to be a String, actually writing the value “Dead”, “Alive”, etc.
Anyone is right? Nope (unless special circumstances). Let’s debate

Speed vs Comprehensiveness

- << Who said to use strings? Oh yes, the VisualBasic people… Come on man, do you know how slow is to compare two strings? Player is a core class, that is used all along the game, even in performance critical parts. You cannot be serious… strings… The solution is to use an Int, or an Hex flag.>>
- <<Who said to use an Int or an Hex Flag? Of course! The native people. Why not we all just turn back into binary, you prehistoric monkeys? Will we need to check what “State = 0” is every time we need to use it?  Man you cannot be serious… ints… The solution is to use strings…>>
As you probably already notice, one can stay like that forever, when there’s a much better solution… Yes, you clever boy, we will use Enumerations. But, do you know why? And what is more important, are you aware of all the benefits (and cons) of an Enumeration? Will talk more on this later, by now lets get deeper in the cons of the other alternatives.

Anyone said duplication again?

We have seen duplication of work (bad), and duplication of decisions (very bad). What none of the contenders in the previous discussion have seen is that both solutions imply a new, hidden form of duplication. It’s what I call: duplication of abilities.

Duplication of Abilities (also very bad)

When you choose to store the status of your player as an Int, or as a String, with values like “Dead” or “Alive”, you are delegating in all your developers the responsibility of writing that values correctly. In other words, you are duplicating the need for the ability to write it correctly in many many different places, and by many different people, instead of centralizing in a single point.
It’s quite likely that, from time to time, someone makes a mistake. So if any of them misspells a string value (“Deaz” instead of “Dead”), or simply misplaces an int, writing “1” instead of “0”, the compilator won’t say a thing, and the application will seem to run just fine. But... What are the effects of setting the status of a player incorrectly in a single, deep point of your code? Absolutely unpredictable. That can manifest as any kind of error in the application, what makes it very difficult to debug, trace and fix.
You must try to avoid this kind of duplication too, centralizing decisions, and reducing the number of places where a mistake can be made. 

Strong-type, baby

We said it before, but let’s just analyze another alternative for storing the “State” of the player in our game. What about Enums?
  • Enums are as fast at runtime as an Int or an hex flag
  • Enums are as comprehensible as Strings at debug time
  • Enums are convertible to and form Int, what makes cross-platform easy
  • Enums are convertible to and from String, what makes printing information easy
  • Enums are much more confortable to use, thanks to the Intellisense, you don´t need to remember the values, nor type them, just select them on the list
  • Enums are strongly typed, which will:
    • Minimize the so-called Duplication of Abilities. Since you select values on a list (thanks to the Intellisense) instead of typing them, you centralize the responsibility of making no mistakes in the enumeration
    • Even if any one ignores the Intellisense, and types the values manually, the presence of “hard to find” errors is also minimized, as a miswritten Enum value will be detected at compilation
So, YES! Enums ROCK! And thanks to the static helper methods found in the .Net Framework (Enum.Parse, Enum.GetNames, Enum.GetUnderlyingType, Enum.GetValues, Enum.IsDefined, etc), they are very versatile too.
So… Use them!!!

An additional security shield

Even if you are already strong-typing, there’s another thing you should always do, specially in big projects that cannot be tested completely too frequently… exactly, that’s correct: UNIT TESTING.
Again, designing good unit tests can take weeks, and again, students will say: <<Weeks! The it’s better not to use unit tests>>, and again you will have to tell no no no…
Unit test are the definitive way for giving big projects the robustness they need, going into places where the compiler can’t go, and testing deeper that just syntax. A unit test can detect a wrong player State, but of course, it has to be well designed. If you want to know more about unit testing, please refer to the following article by Roy Osherove:

Conclusion

Every time you find yourself doing a Copy-Paste, ask yourself:
  • Why are you doing it
  • Is it really necessary to duplicate what you are duplicating
  • Can it come to problems if something changes in the future
  • Is there any way of avoiding that duplication
Try to find implicit or hidden duplications, that can be problematic in the future. Try to reduce the number of places where mistakes can be made. Try to reduce the number of people that can make mistakes (and I mean something deeper than firing dumb-asses!). Strong-type and Unit-Test when possible!
Finally, apply some common sense to all of this. Sometimes, you should do just the opposite to what I´m telling… ja ja… ;)
Take Care!