Thursday, November 15, 2007

Sorting a Generic List of Custom Objects Simply

For a defect I was working on today, I just wanted to sort a list of users by username in a very simple fashion.

Google failed me. I wasn't able to find a good example of how to do this easily in VB.NET. As usual, most examples are full of noise, like this, this, this, or that.

So, once I figured out how to do it, I thought I should share it.

First, we create a function to handle our comparison.

Private Function UsernameComparer(ByVal x As User, ByVal y As User) As Integer
Return x.UserName.CompareTo(y.UserName)
End Function

Next, we use it.

myUserList.Sort(AddressOf UsernameComparer)

Now our user list is sorted by username.

In C# 2.0, using anonymous methods, it can even be done all at once:

myUserList.Sort(delegate(User x, User y) {
return x.UserName.CompareTo(y.UserName);
});

If you know of an even simpler way to do this, leave some comments and let us know!

Wednesday, October 17, 2007

MSDN code examples are terrible

This is the page that really got my goat. I'll list the relevant parts here for ease of reading.

Page.RegisterOnSubmitStatement Method

Allows a page to access the client OnSubmit event. The script should be a function call to client code registered elsewhere.

   1: '[Visual Basic] 
   2: Dim scriptString As String = "<script language=JavaScript> function doClick() {"
   3: scriptString += "document.write('<h4>' + myForm.myHiddenField.value+ '</h4>');}<"
   4: scriptString += "/" + "script>"
   5: RegisterHiddenField("myHiddenField", "Welcome to Microsoft .NET!") 
   6:  
   7: RegisterOnSubmitStatement("submit", "document.write('<h4>Submit button clicked.</h4>')") 
   8:  
   9: RegisterStartupScript("startup", scriptString) 


   1: //[C#] 
   2: void Page_Load(Object sender, EventArgs e) 
   3: { 
   4:    String scriptString = "<script language=JavaScript> function doClick() {";
   5:    scriptString += "document.write('<h4>' + myForm.myHiddenField.value+ '</h4>');}<";
   6:    scriptString += "/" + "script>";
   7:    RegisterHiddenField("myHiddenField", "Welcome to Microsoft .NET!"); 
   8:    RegisterOnSubmitStatement("submit", "document.write('<h4>Submit button clicked.</h4>')"); 
   9:    RegisterStartupScript("startup", scriptString);
  10: } 

Ok, how many things can you find wrong with this simple example?


  1. string concatenating to make a script block

  2. a bunch of totally unrelated code that muddies the point

  3. document.write() - who does that?

  4. VB and C# code don't even match; C# includes the method declaration; VB only includes the method body

  5. scriptString += "/" + "script>"

  6. definition says "The script should be a function call to client code registered elsewhere." but that is not what the example code does

Here's my stab:



   1: //[C#] 
   2: void Page_Load(Object sender, EventArgs e) 
   3: { 
   4:   if (!IsClientScriptBlockRegistered("doClickScriptKey"))
   5:   {
   6:     String scriptString = @"
   7:     <script type='text/javascript'>
   8:         function doClick() { alert('the form is about to submit!'); }
   9:     </script>";
  10:     RegisterClientScriptBlock("doClickScriptKey", scriptString);  //"registered elsewhere"
  11:   }
  12:   RegisterOnSubmitStatement("submitScriptKey", "doClick();"); //"function call to client code registered elsewhere"
  13: } 

Friday, September 14, 2007

Conversation about Patterns, Developers, and whatnot

(9:10 PM) Robert:

how's the job going this week?

(9:11 PM) Daniel:

better actually, we're digging into this arcade game
and I'm starting to understand things more

(9:11 PM) Daniel:

but its all-consuming in my head, i can't seem to think about anything else
i.e. dave's game

(9:12 PM) Robert:

that's understandable

(9:12 PM) Daniel:

I really want to help dave though, cause I want him to finish it

(9:13 PM) Daniel:

maybe on the weekends I'll have time

(9:24 PM) Robert:

i hate words that have extraneous letters
such as Lincoln

(9:24 PM) Robert:

what's that second L doing in there?

(9:24 PM) Daniel:

just hangin out man

(9:24 PM) Robert:

nobody says "Leen-koln"

(9:25 PM) Robert:

back to programming a bit...

(9:25 PM) Daniel:

I feel your pain

(9:25 PM) Robert:

have you read about "design patterns"?

(9:26 PM) Robert:

(along with "anti-patterns")

(9:26 PM) Daniel:

I'm staring at a book called Design Patterns at this very moment

(9:26 PM) Daniel:

not reading it, its on the table

(9:26 PM) Robert:

"Elements of Reusable Object-Oriented Software"?

(9:26 PM) Daniel:

you're meaning things like the factory method, singletons...etc

(9:27 PM) Robert:

yeah

(9:27 PM) Daniel:

yeah, that's the one

(9:27 PM) Robert:

cool

(9:27 PM) Daniel:

dedrick had it in the office and I'm borrowing it

(9:27 PM) Robert:

you're already light-years ahead of most developers

(9:27 PM) Robert:

of your own accord or upon his suggestion?

(9:28 PM) Daniel:

no, I've been wanting to learn about them

(9:28 PM) Daniel:

and it turns out he had just the book I was going to buy

(9:28 PM) Robert:

i was teaching Greg at work about the Strategy pattern today

(9:29 PM) Daniel:

I guess I don't know greg

(9:29 PM) Robert:

you don't

(9:29 PM) Daniel:

but yeah, I've been wanting to read up on the patterns for awhile now
after learning they existed

(9:29 PM) Robert:

do you know if that book also talks about "anti-patterns"?

(9:29 PM) Daniel:

not sure

(9:30 PM) Daniel:

not in the index
anyway

(9:32 PM) Daniel:

I don't understand something

(9:33 PM) Daniel:

you mention a lot that most developers don't do this, or know about that
but jeez, what do they know?

(9:33 PM) Robert:

they know how to write "spaghetti code" until it just barely works

(9:34 PM) Robert:

"spaghetti code" is probably what your early expirements looked like

(9:34 PM) Daniel:

that sucks, they don't even want to make it good?

(9:34 PM) Robert:

nope
they are victims of "good enough"

(9:37 PM) Robert:

http://www.amazon.com/AntiPatterns-Refactoring-Software-Architectures-Projects/dp/0471197130/ref=pd_bbs_1/104-0707808-5144724?ie=UTF8&s=books&qid=1189647010&sr=1-1

(9:37 PM) Daniel:

I guess I don't have enough time working with dedrick and the other guy to see what they're attitude is, they seem to be okay

(9:38 PM) Daniel:

sounds like a funny book
interesting

(9:39 PM) Robert:

this is the exact reason why i think i told you before - i'd rather hire a mediocre-but-passionate dev than a well-trained-but-unmotivated dev

(9:39 PM) Daniel:

I can see that

(9:40 PM) Daniel:

do you ever get input on who your company hires?
give input

(9:41 PM) Robert:

passion begets constant improvement and excellent developers that can encourage other devs

(9:42 PM) Robert:

lack-luster begets wasted time/effort and code that is difficult to maintain
no

(9:43 PM) Robert:

though i was asked to write a small code-snippet that would be presented to interveiwees to see what they understand about it
i'll show you - you won't get it - it's probably too difficult

(9:43 PM) Daniel:

ok

(9:46 PM) Robert:

    static class Foo<T> where T : new()
    {
        private static T bar = new T();
        public static T Bar
        {
            get { return bar; }
        }
    }
that's the whole class, and it's quite useful

(9:47 PM) Daniel:

ok, let me look

(9:47 PM) Robert:

i had to replace real names with Foo and Bar or else you'd know right away

(9:48 PM) Daniel:

don't tell me

(9:49 PM) Robert:

the point of the code in the interview isn't to see if you get it right, it's to see how much of it you can explain

(9:50 PM) Daniel:

it looks like a generic class that just makes things
to me

(9:50 PM) Daniel:

some parts of the code confuse me however

(9:51 PM) Robert:

explain...

(9:51 PM) Daniel:

explain what I don't understand?

(9:51 PM) Robert:

yeah

(9:52 PM) Daniel:

in the class heading, you have "where T : new()
I don't get that

(9:53 PM) Daniel:

maybe I'm just reading it wrong

(9:54 PM) Robert:

that is a "generic type parameter constraint"

(9:55 PM) Robert:

it say's "you can use any T as long as it has a default public constructor"

(9:55 PM) Daniel:

I see

(9:55 PM) Daniel:

is this an object factory?

(9:56 PM) Robert:

if a type only had a private constructor or the only public constructor (abbrv. "ctor") requires any parameters

(9:56 PM) Robert:

that's close - it's a very special type of "factory"

(9:57 PM) Robert:

want me to explain?

(9:57 PM) Daniel:

yeah, don't think I can get any closer

(9:58 PM) Robert:

hint: it's not building very many objects - "new T()" is only called once

(9:59 PM) Daniel:

a singleton?

(9:59 PM) Robert:

yep
it externalizes the concept of "singleton" to a separate generic class

(9:59 PM) Robert:

you would use it like this:

(10:00 PM) Robert:

WizardGame game = Singleton<WizardGame>.Instance();

(10:00 PM) Robert:

the Singleton class (Foo) ensures that there is only one

(10:01 PM) Daniel:

how does it do that?
what prevents you

(10:08 PM) Robert:

brb; putting dishes away

(10:09 PM) Daniel:

ok

(10:36 PM) Robert:

hey
i'm back

(10:37 PM) Daniel:

ok

(10:37 PM) Robert:

every question you ask me tells me more about what you know and don't know about C#/.Net

(10:37 PM) Daniel:

:)

(10:37 PM) Robert:

...as an interviewer

(10:38 PM) Robert:

at first, i knew that you at least understood the C# language at a basic level
and you understood the basic concepts of Generics

(10:38 PM) Robert:

but not some of the finer points (constraints)

(10:39 PM) Robert:

after my hint, i knew that you were familiar with the concept of "design patterns"

(10:39 PM) Daniel:

a lot of information from just a little bit of code

(10:40 PM) Robert:

and now i know that you aren't familiar with the intricacies of C#

(10:40 PM) Robert:

here's the non-obfuscated code:
    static class Singleton<T> where T : new()
    {
        private static T instance = new T();
        public static T Instance
        {
            get { return instance; }
        }
    }

(10:41 PM) Robert:

and now to answer your question...

(10:41 PM) Robert:

first, you have to understand that Singleton<Foo> is a different class than Singleton<Bar>

(10:42 PM) Daniel:

ok

(10:42 PM) Daniel:

seems logical enough

(10:45 PM) Robert:

was looking up some terms i forgot for a second

(10:45 PM) Robert:

Singleton<T> is called an "open" generic type as long as T is undefined

(10:46 PM) Robert:

Singleton<Foo> is a "closed" generic type b/c T has been defined as Foo

(10:46 PM) Daniel:

ok

(10:46 PM) Robert:

Singleton<T> == S<T> from now on

(10:46 PM) Daniel:

ok

(10:47 PM) Robert:

so now that you know S<Foo> is a totally different class than S<Bar>...

(10:47 PM) Robert:

notice that the class is static - both member (field and property) are both static

(10:47 PM) Daniel:

I see

(10:48 PM) Daniel:

so you don't need an instance of the class, but it returns an instance
of T

(10:50 PM) Robert:

    class Foo
    {
        public object bar = new object();
    }
is basically the same as...
    class Foo
    {
        public object bar;
        public Foo()
        {
            bar = new object();
        }
    }

(10:50 PM) Robert:

first initializes bar inline; second initializes bar inside the constructor

(10:51 PM) Daniel:

I'm with you

(10:51 PM) Robert:

first is essentially converted to second when compiled

(10:51 PM) Robert:

C# guarantees that all fields will be initialized before any user-defined ctor code is executed

(10:52 PM) Daniel:

ok

(10:52 PM) Robert:

    class Foo
    {
        public int bar = 3;
        public Foo()
        {
            bar = 2;
        }
    }

(10:52 PM) Robert:

in this case, bar is initialized to 3, then immediatly overwritten with 2

(10:53 PM) Daniel:

I see

(10:53 PM) Robert:

C# also guarantees that a static constructor will be executed exactly one time per class (per AppDomain)

(10:54 PM) Robert:

and that it will be executed immediatly before the first access of any static members of the class

(10:54 PM) Daniel:

does the constructor need an access modifier?

(10:54 PM) Robert:

static constructors can't have access modifiers

(10:55 PM) Robert:

instance constructors follow the same rules as other members - everything without an access modifier is private by default

(10:55 PM) Daniel:

ok
let me soak in what you wrote

(10:57 PM) Daniel:

so its the static keyword in the constructor that makes it the singleton

(10:57 PM) Robert:

the class i sent you doesn't even have an explicit constructor

(10:58 PM) Daniel:

oh, you're right

(10:58 PM) Daniel:

hmm

(10:59 PM) Daniel:

so the fact that its a static class then

(10:59 PM) Robert:

sorta - in C# a static class is just a way to ensure that all members are static
it doesn't mean much

(11:01 PM) Robert:

(in .Net 1.x they shipped with a class that was expected to be "static", but it had a public instance method and the only instance ctor was Private - that meant that there was no way for anyone to instantiate the class and use the public method - in .Net 2.0 they added the concept of a "static class" to prevent things like that in the future)

(11:02 PM) Daniel:

I see

(11:03 PM) Robert:

i have given you all the info you need to answer your orig. question

(11:04 PM) Robert:

(inline initialization == ctor initialization; static ctor is called exactly once and just before first access of any static member)

(11:06 PM) Daniel:

I get it

(11:06 PM) Robert:

you grok it?

(11:06 PM) Daniel:

no, I don't want  to say I grok it until I've used it

(11:07 PM) Daniel:

so pretty much that's how you do a singleton in .net?

(11:08 PM) Daniel:

or is that across other languages as well?

(11:08 PM) Robert:

other languages/platforms have different intricacies
and that's not the normal way to do a singleton
it's my own invention
:)

(11:08 PM) Daniel:

seems elegant

(11:09 PM) Daniel:

although I don't know the other way

(11:09 PM) Daniel:

I have a question for you

(11:10 PM) Daniel:

its C++ but more OOP specific

(11:11 PM) Daniel:

in the main class I'm doing at work, it has a bunch of functions that work with the member  data

(11:12 PM) Daniel:

it basically has one method, and inside that method I've broken tasks down into their own methods

(11:12 PM) Daniel:

but since its all within the class I don't have to pass anything into these methods since I already have access to them

(11:13 PM) Daniel:

but it feels weird or something

(11:13 PM) Robert:

it's a bad habit

(11:13 PM) Daniel:

I thought so, but I wasn't sure

(11:14 PM) Robert:

unless the data (state) needs to be persisted even after the call to the "basically one method" then it should be passed to each method as needed

(11:15 PM) Daniel:

ok, I felt that was the right way
tomorrow I'll fix it

(11:16 PM) Daniel:

I mean I felt that passing parameters was the right way

(11:19 PM) Robert:

this is the conventional singleton pattern
    public class Foo
    {
        // prevents public instantiation
        private Foo() { }
        private static Foo instance;
        public static Foo Instance
        {
            get
            {
                // this is called the "double-checked locking" singleton pattern
                // it attempts to solve a "race condition" that may occur in multi-threaded systems
                if (instance == null)
                {
                    lock (this)
                    {
                        if (instance == null) // another thread could have assigned it since the previous check
                        {
                            instance = new Foo();
                        }
                    }
                }
                return instance;
            }
        }
    }

(11:20 PM) Robert:

http://www.ibm.com/developerworks/java/library/j-dcl.html

(11:21 PM) Robert:

"The bottom line is that double-checked locking, in whatever form, should not be used because you cannot guarantee that it will work on any JVM implementation."
same thing on the .Net platform

(11:23 PM) Robert:

"Listing 10" in that article is "good" but not great in .Net b/c it isn't lazy enough

(11:24 PM) Robert:

access to *any* static member will instantiate the "instance" field even though i may not be using it
anyway, it's bedtime
i think you've got enought for tonight
:)

(11:24 PM) Robert:

i had fun teaching you

(11:24 PM) Daniel:

for sure, thanks

(11:25 PM) Daniel:

interesting how you merged our two topics
did you notice that?

(11:25 PM) Robert:

no?

(11:25 PM) Daniel:

we were talking about design patterns then about programmers you don't like, which lead to my question about how much input you have in the hiring

(11:26 PM) Daniel:

which lead to you giving me the example snippet you wrote for interviewees

(11:26 PM) Robert:

which went back around to patterns

(11:26 PM) Daniel:

which was about a singleton
:0-)
uh, :)

(11:26 PM) Robert:

i'm just good like that :)
goodnight

(11:26 PM) Daniel:

guess so, night

Wednesday, July 25, 2007

Object Oriented? You can't even define classes, can you?

For some reason, unlike other modern languages, the ability to define custom types seems to be a Javascript language feature that is often passed over. Only advanced Javascripters seem to ever get around to learning about this underused feature. Defining a new type in Javascript is easy; you just have to get used to the syntax and understand that in Javascript, everything is an object; Functions are Objects, too.

   1: function Person(fname, lname)
   2: {
   3:     this._fname = fname;
   4:     this._lname = lname;
   5: }
   6: var dave = new Person("Dave", "Haynes");

The code above defines a function called Person which takes two parameters; notice how it assigns the value of the parameters to a pair of expando properties on this. What is this?

First, notice the new keyword used in the assignment to dave. The new keyword basically calls the function in the context of a new object of type Person - this refers to that new object within the scope of the function. The function then adds new expando properties to this object, then the object is assigned to dave. You can consider the Person function to be both the constructor for and the definition of the Person type. Without the new keyword, the expando properties would be added to the global scope and dave would be assigned the return value of the traditional function call. Since the function doesn't have a return statement, it implicitly returns null.


Remember earlier when I said "Functions are Objects, too"? Let's expand the sample a bit...



   1: function Person(fname, lname)
   2: {
   3:     this._fname = fname;
   4:     this._lname = lname;
   5:     
   6:     this.GetFullName = function(){
   7:         return this._fname + " " + this._lname;
   8:     }
   9: }
  10: var dave = new Person("Dave", "Haynes");
  11: alert(dave.GetFullName());

Now we have added a new expando property called GetFullName, but this time it is assigned a function that takes no formal parameters. This demonstrates that a function is an object just like everything else in Javascript. It can be passed around to other functions, stored in variables, garbage collected, etc.

Wednesday, April 25, 2007

Garbage Collection? That's gross!

"Garbage Collection" probably sounds like a strange term if you've never heard of it before. So what is it? Well, you've all probably heard of a "memory leak" before. Garbage Collection, or GC, is essentially an attempt to prevent memory leaks. Back in the old days, developers had to be very diligent about cleaning up after themselves. If an object was allocated repeatedly but never "destroyed" or cleaned up the system would gradually use more and more memory until there was no more available memory and the application would crash.

Today, platforms like Java, .Net, Javascript, Perl, Ruby, and PHP have GC built-in. In platforms with GC, objects that are no longer referenced (because the reference has gone out of scope or because the variable was set to null) become eligible to be automatically destroyed and the memory used made available for new allocations. Notice that i said they become eligible; the objects are not immediately cleaned up when they go out of scope. The garbage collector only performs the collection when it is necessary, such as when the system is running low on memory.

Javascript has the ability to be garbage collected or to use explicit memory management when necessary or desired with the delete keyword. The two graphs below show the difference.

The first graph shows memory consumption over time while the garbage collector is allowed to manage the memory.

The second graph shows the same thing while the program manages it's own memory by explicitly deleting the objects when it is done with them.

   1: <%@ Page Language="C#" AutoEventWireup="true" Codebehind="Default.aspx.cs" Inherits="ItsJustJavascript._Default" %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4: <html xmlns="http://www.w3.org/1999/xhtml">
   5: <head id="Head1" runat="server">
   6:     <title>Untitled Page</title>
   7: </head>
   8: <body>
   9:     <form id="form1" runat="server">
  10:         <div>
  11:             <button onclick="cancel = false; useMemory(false);">
  12:                 start (normal)</button>
  13:             <button onclick="cancel = false; useMemory(true);">
  14:                 start (self cleanup)</button>
  15:             <button onclick="cancel = true;">
  16:                 stop</button>
  17:             <br />
  18:             <input type="text" id="output" />
  19:         </div>
  20:     </form>
  21:     <script type="text/javascript">
   1:  
   2:     var cancel = false;
   3:     var output = document.getElementById("output");    
   4:     
   5:     function useMemory(selfCleanUp)
   6:     {
   7:         if (cancel) return;
   8:         
   9:         output.value = (new Date()).toString();
  10:         for (var i = 0; i<100000; i++)
  11:         {
  12:             var foo = new Object(); //just consume a small amount of memory
  13:             foo.bar = new Object(); // and a bit more memory, plus an expando!
  14:             if (selfCleanUp)
  15:             {
  16:                 foo.bar = null;
  17:                 delete foo.bar;
  18:                 foo = null;
  19:                 delete foo;
  20:             }
  21:         }
  22:         
  23:         window.setTimeout("useMemory(" + selfCleanUp + ")", 1);
  24:     }
  25:     
</script>
  22: </body>
  23: </html>

Additional Info:

Monday, April 23, 2007

Presto Expando

It's hard to know where to start, but you've got to start somewhere, right?

JavaScript is a very dynamic language. That basically means that objects can be created and modified at runtime. It is also very loosely-typed which means that you can treat a string variable as an integer or an integer as a date, or a date as a string, or... well, you get the point.

So what do I mean by "objects can be created and modified at runtime"? In static languages, the members (attributes, properties, methods, etc.) and behaviors of a type are explicitly defined at design-time and then compiled. After compilation you cannot add or remove any of the members. I suppose you've already guessed what i'm going to say next. In dynamic languages (depending on the degree of dynamicism), any member can be added, removed, or replaced at runtime. In Javascript, members you add at runtime are commonly called "expando properties".

   1: var someObject = new Object();
   2:  
   3: //calls builtin toString method
   4: alert(someObject.toString());
   5:  
   6: // adding an attribute
   7: someObject.myExpando = "hello expando";
   8:  
   9: // replaces builtin toString method
  10: someObject.toString = function()
  11: {
  12:     return this.myExpando;
  13: }
  14:  
  15: // notice how the toString method has been replaced
  16: alert(someObject.toString());
  17:  
  18: // adding a new method to the new object
  19: someObject.tellTime = function()
  20: {
  21:     alert(new Date());
  22: }
  23:  
  24: someObject.tellTime();
  25:  
  26: //removing the method we just added
  27: delete someObject.tellTime;
  28:  
  29: //calling the method now will be an error
  30: try
  31: {
  32:     someObject.tellTime();
  33: }
  34: catch(e)
  35: {
  36:     alert(e.message);
  37: }

Additional Info: