Sunday, July 20, 2014

Understanding the C# Yield

We have all seen the new "yield" keyword in C# at one point or another, but if you are like me, sometimes, we just say, "what's the big deal, I can do that myself" and move on.

But this weekend, I took time to get a bit more understanding of "yield."  I looked around on the net to to see various examples, but none of them still made sense to me.  So I decided to write a bit of code to experiment. The example included on this post contains the complete code that you can run as a console app.

I found that most examples show the use of the yielding function from within another loop, and that did not make much sense to me, since if you do that, then I would think that why not even bother having a separate loop. But hardly no examples showed me to use an Enumerator to iterate through, throughout a part of program, and that's what I plan to demonstrate here.

First, a bit about the example. Let's say that we need a program for the shipping department of a computer store and you want to make sure the employees will not forget to pack each part in the right box. You would have a list of parts like monitor, keyboard etc., and display the instructions what goes where etc.

What I wanted to get out of this example is to see if my assumptions are correct, and in one case I was not, and glad I caught that by writing this example.

So here is what I have learned;

It's a Way To Implement the Deferred Computation Pattern

  • The yield consutruction is probably good for performing complex calculations within a loop and especially the computation for a specific part of iteration is not performed until you request it, you might save resource or time.

    This approach appears to be very effective if I create an Enumerator then use MoveNext() to the next item, and that's where its power lies. For example, accessing a database or looking up something from a web service. You can defer the computation like this just until you call MoveNext(), and you do not need to write a special state management between the calls. Come to think of it, that's how LINQ works and that's the core of IEnumerable is about. Makes sense!

    We can certainly do this without yield, but to do the same thing, I have to keep track of the states and either store them as private data members or in a separate class structure and pass that back and forth. Also some loops take a decent effort to initialize, and in the yeild approach, we can certainly reduce that effort.

    As the functional programming approch recommends, the more states we create and must manage locally, they tend to cause hard-to find/fix bugs.

    So the advantage with this is a much simpler (hence reliable and testable) design.

My Bad Assumption Cleared

  • If you create a foreach loop again, the iteration will reset from the position 0 for each loop. I misunderstood this aspect. I thought if I have left the loop (say picked up first 3 items) and then did another loop for the next set, I thought I can pick up from where I left off. It does not work that way. So you have also been warned now.

The Code

using System;
using System.Collections.Generic;
using System.Linq;

namespace Yield
{
    class Program
    {
        static void Main(string[] args)
        {
            var sample = new YeldSample();
            sample.Run();
        }
    }

    public class YeldSample
    {
        public void Run()
        {
            var packingList = new List<string>
            {
                "A: Memory""A: Disk""A: DVD Drive",
                "B: Display",  "B: Monitor Cable""B: Monitor Power Cord",
                "C: Mouse""C: Memory Card""C: Keyboard",
            };

            var itemCount = 0;
            var iterator = YieldPart(packingList);

            var enumerable = iterator as string[] ?? iterator.ToArray();
            foreach (var item in enumerable)
            {
                Console.WriteLine("{0} Done!", item);
                itemCount++;
                if (itemCount == 3) break;
            }

            Console.WriteLine("\r\nBad Example Below. This will begin the loop from the start again.\r\n");
            itemCount = 0;

            foreach (var item in enumerable)
            {
                Console.WriteLine("{0} packed again!", item);
                itemCount++;
                if (itemCount == 3) break;
            }

            Console.WriteLine("\r\nExample Using the Enumerator\r\n");

            var items = enumerable.GetEnumerator();

            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);
            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);
            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);

            Console.WriteLine("\r\nTake a break!\r\n");

            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);
            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);
            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);

            Console.WriteLine("\r\nTake a break!\r\n");

            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);
            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);
            items.MoveNext();
            Console.WriteLine("{0} Done!", items.Current);

        }

        public IEnumerable<String> YieldPart(List<String> parts)
        {
            foreach (var part in parts)
            {
                var dest = "";
                if (part.StartsWith(("A:"))) dest = "main carton.";
                if (part.StartsWith(("B:"))) dest = "monitor carton.";
                if (part.StartsWith(("C:"))) dest = "accessory carton.";

                var phrase = String.Format("Put {0} in the {1}", part.Substring(3), dest);
                yield return phrase;
            }
        }
    }
}

Thursday, July 17, 2014

Google Drive Windows & Mac - "Sign into a different account" does not work

Symptom:


You have either left a company that was using the Google Apps, or you may have recently removed a Google Account and then changed to another. Now you try to connect to the Google Drive, it won't let you change the account, instead it remembers your previous account, and clicking the "Sign into a different account" performs nothing.


Do Not Go Down This Route!


First, it took me about 8 hours to solve this fairly serious flaw and I also checked on the net to see if there has been any solutions.

  • There is no need for you to go to the C:\Users... \Drive folder to remove it. 
  • There is no need to uninstall.
  • There is no need to run CC Cleaner
  • There is no need to clear the history of Chrome. It's not where this issue is happening.
  • There is nothing in the registry so don't look there.

Root Cause:


It is the IE caching the log-in credentials. Not the Chrome. But to make the matter worse, you need to log-into the new Google Account in the IE to clear the previous credential that was cached.

The Fix

I will now explain the steps.

First, go to the Internet Options of the IE, then Delete the browsing history.




Now this is the important part. By default "Preserve Favorite website data." You would not want to do that. So you must UNCHECK that box. The illustration below shows it is checked. Again uncheck this (if you know what to do, you could just remove the cookie for your previous account.)


Wait for the cache to be cleared, then, next thing you need to do is to Sign In to Your New Google Account with the User and Password of the new account.




Mac OS Mavericks Procedure (Inconclusive but Worked For Me)


You will run into the identical problem if you also have a Mac. You are also likely to have Safari and Firefox installed, therefore you need to do this with Chrome, Firefox and Safari in that order.

First, clear the stored password from every browser you have.

Then close all the browsers and do the following steps on every browser from Chrome, Firefox and then Safari in that order.

  • Go to http://www.google.com and if it is still logged into a Google account, log out of it and then log back in.
  • Go to http://drive.google.com now and click your profile photo on the top right of the page. If you do, you should see Add Account button. If you do not see this button, log out and log back in. If you have more than one Active account, then you should add those now.
  • Close the browser and do the same to the next browser.
When you are all done with them, you have cleared the any cached log-in information and you can now re-launch the Google Drive app and you should be able to log-in.

You may still get the following dialog box after all of that;




This is due to the leftover config files that's been on your ~/ (home) directory. There are two places
  • Remove everything in the Google/Drive folder  
    • /Users//Library/Application Support/Google/Drive
  • Remove 
    • in /Users//Library/Preferences

    • com.google.GoogleDrive.plist com.google.GoogleDrive.plist.lockfile



Mazda IT: TomTom Navigation Map Starts to Spin Aound For No Good Reason

Symptom

Around June of 2014 or later, your Mazda TomTom (CX-5 in my case) map start to jigger and spin around and also indicate "acquiring a signal."

What Fixed It

Update the firmware on your TomTom, this is possible by going to the TomTom web site and then downloading the TomTom Home software then update the SD card.

Visual Studio 2012 Installation Hangs

Note: You might be wondering why this is about VS 2012 and not 2013. It turns out that I had to install 2012 for a gig that required it, then I ran into this problem.

Symptom:

You started to install Visual Studio 2012 (Pro in my situation). You have tried the Web install as well as the DVD install and it launches the installer, but shortly after there is no window and installation is hang up no matter how long you wait.

Fix:

Uninstall .NET Framework 3.5.1 (or possibly any other ones) before proceeding to start the installer. Your .NET Framework is likely corrupted in the manner that VS 2012 would not work.

Friday, July 04, 2014

IIS 8 - Get 405 (Method Not Allowed) on DELETE

Symptom


You have implemented an Web API interface (in my case Web API 2) for Delete operation. Your GETs as well as POST works, but when you try to execute DELETE, you get a 405 error code.

DELETE http://localhost/MySite/MyApp 405 (Method Not Allowed)

What Worked For Me


Since I have explicitly set up my environment not to get into CORS situation, it was clear to me that something else was an issue. However, if you are using the built-in IIS from the Visual Studio to test your interface, it will come with a special port number and it is highly likely that you are running into the CORS situation so be sure to check that as well.

What fixed was to modify a part of the web.config file in the following manner.


By removing ExtensionlessUrlHandler-ISAPI-4.0_64bit, it started to work.

The Microsoft KB Article http://support.microsoft.com/kb/224609 was most helpful in deriving this solution for me.

According to the above article, the configuration catches "like" configurations first and thus by the time it is at your level of web application, the configuration is basically "messed up."


Side Note


Also, I did not have a proper configuration on my web interface declaration and after above issue was fixed I was starting to get an error code 500. This goes to say that if you get the error 500, the DELETE is trying to execute and you are out of the web.config issue.

In my case, I forgot to add "{id}" in my Route declaration.

      [Route("{id}")]
        [HttpDelete]
        public void Delete(Guid id)
        {


Thursday, July 03, 2014

Super Beginner Guide to AngularJS - Uncaught Object

OK, I will admit. I am just starting out learning AngularJS and already spent numerous hours where an experienced programmer won't step into. Well, just a few months from now, though, I won't be in that situation, nor I would remember the kind of traps I got into. So it's time to blog about them because if I ran into them, you would too.

What to Do If You Get Uncaught Object on Chrome Console

So your text book author said, "you can test in any browser you choose so long as it is Chrome." And you believed it, didn't you. You tried your first program, and you get the following message in the JavaScript console.

Uncaught object
  (anonymous function) angular.js:78
  (anonymous function) angular.js:1751
  ensure angular.js:1675
  module angular.js:1749
  (anonymous function) app.html:9

Unlike a debugging in C# or Java, it does not tell you where and what the issue is. Very frustrating. You even set a breakpoint where the issue was found and it says "missing ngLocale" module to that effect when you have not even plan to reference such a module in your code.

This turns out to be a current (as of July 2014) bug in Chrome. May be it has been fixed by the time you read this, but it goes to say that when debugging JavaScript it might be worthwhile trying another browser than just Chrome. Especially Firefox and IE are great choices as the JavaScript implementation is totally different from Chrome or Webkit based.

Error: [$injector:nomod] Module 'undefined' is not available! You have either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.3.0-beta.11/$injector/nomod?p0=undefined angular.js
Error: [$injector:nomod] Module 'mtSample' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.3.0-beta.11/$injector/nomod?p0=mtSample angular.js

Now at least here the debug console output will be more specific as to the nature of the problem. For above example, I have purposely eliminated a comma after "mtSample" from angular.module("mtSample" ["ngRoute"]).

Go Ahead, Try the IE too!

I know, I know, we are supposed to sit and code at Petes with our latest Mac Books and bash the IE ( I am writing this artile on my iMac by the way). But you will be surprised to know how much changes Microsoft has made to embrace the latest open source technology. You can even run Linux on Microsoft Azure now!

So, even on the IE, the message is clear! In fact, it is the cleanest and clearest of all in this specific example. So at least, let's give some hands to the Micrsoft folks. We should not lose a sight that as software engineers our task is to get our job done. I would use any tool I can lay my hands on.



A Side Note - Do Not Mix and Match Angular Libraries

I have accidentally mixed in additional Angular components (like routing package) from the latest into the rest which was in a pervious version. If you do this, you will run into a very similar issue. When in doubt, refresh the complete AngularJS library to the same perstine version.


... to be continued.