June 2007 - Posts

What is your favorite data structure?

I always enjoy the behind-the-scene interview movies in Channel9. One of my favorite in each Q&A session is when interviewer asking participant to draw his favorite data structure. Try to download one of the movie and see how it was going. Big names like Anders, Rob Short, etc, have their own favorites.

Now, imagine if I ask you the same question. Please draw your favorite data structure in a paper, scan and post it to your blog with clear explanation and sample codes (ASM, C, C++, C#, VB.NET, Java Script, VB Script, are welcome). I believe that each INDC geek will have different favorite, right? This could be a funny and challenging because other people can learn and ask question by post comments.

Now, lets play a simple game.
- Each participants draw and explain favorite data structure
- Others can post comments, questions, etc
- I will be the single judge to decide who has the best posting. My opinion will be opened to public.

For the Winner, I personally will give the following:
- Cash IDR 200.000,- (for your starbuck)
- Original "Introduction to Algorithm" book, Cormen et.al.

Have a nice day!

Note : This challenge is valid until July 31, 2007. I will announce the WINNER in August, 1st.  

Thx - RAM

Share this post: | | | |

Little Puzzle

Little problem from Irwansyah, here is my answer:

#include<stdio.h>
int s[10] = {-7,-6,-5,-4,-3,42,-2,-1,0,42};
int *PrintArray(int *p);

int main(void)
{
    int *p = s;
    do{PrintArray(PrintArray(p));}while(s[0]<990);
    return 0;
}

int *PrintArray(int *p)
{
    for(int i = 0;i<10;++i)if(i==5||i==9){printf("%c",*(p+i));*(p+i)=42;}else{printf("%d",*(p+i));*(p+i)+=8;}
    return p;
}   

Thx - RAM

Share this post: | | | |

My Favorite Technical Interview Questions

One of my favorite interview question for people who applied to DPE is "How you can make stack without collection" ? No one can answer it well until now (possibly because no one really read ECMA 334). Sadly said, not even fresh grad! The answer is YES, you can do that. Let see below.

First, just define a class called Entry that contains a current object data initialized in the Entry's constructor. Then make a field member with Entry reference type called next that will contains next object in the stack that we will make. Both data and next are initialized in the Entry's constructor.

public class Entry
{
     public Entry next;
     public object data;
     public Entry(Entry next, object data) 
     {
           this.next = next;
           this.data = data;
     }
}

Entry
object will represent the current entry element in stack in which we can only POP it out or PUSH next element on top of it. We can add previous element but it is not necessary as we assume that our stack only need to have POP and PUSH methods. Now let see our stack class looks like. We need an Entry type to store the top element, say it top. When we push an object, always set it as top element in the stack (see the Push method). When we pop, get the data from top and set the next member of Entry as the top element to replaced the popped one. It will looks like below:

 

using System;

namespace SimpleStack
{
    public class Stack
    {
        Entry top;
        public void Push(object data)
        {
            top = new Entry(top, data);
        }

        public object Pop()
        {
            if (top == null) throw new InvalidOperationException();
            object result = top.data;
            top = top.next;
            return result;
        }

    }
}
 

Now test your program with a simple test class:

class Test
{
    static void Main()
    {
        SimpleStack.Stack s = new SimpleStack.Stack();
        for (int i=0;i<=10;++i)s.Push(i*10);
        for (int i=0;i<=10;++i)Console.WriteLine(s.Pop());
    }
}


It is pretty simple right? To make our stack has a better look, we can make Entry class nested to SimpleStack class.

using System;

namespace SimpleStack
{
    public class Stack
    {
        Entry top;
        public void Push(object data)
        {
            top = new Entry(top, data);
        }

        public object Pop()
        {
            if (top == null) throw new InvalidOperationException();
            object result = top.data;
            top = top.next;
            return result;
        }

        public class Entry
        {
            public Entry next;
            public object data;
            public Entry(Entry next, object data) 
            {
                  this.next = next;
                  this.data = data;
             }
         }

    }

}

My other favorite question is, what is the different between x++ and ++x  in C++ and C#? Like you guess, everybody know that x++ is post increment and ++x is pre increment. But you know, as interviewer, I want to measure your understanding around the virtual machine that you work with and your abstraction level . Let me explain you for C++ case (lower abstraction). Make the simple C++ code below and compile it with CL /Fa to generate its assembly codes:


void main()
{
    int x = 0;
    int y = x + x++; // change to y = x + ++x; later
}


Now see x++ ASM codes:

mov    eax, DWORD PTR _x$[ebp]                 // think DWORD PTR _x$[ebp] as x location and move its value to EAX register
add    eax, DWORD PTR _x$[ebp]                  //
locate x, read its value and add that value to EAX register
mov    DWORD PTR _y$[ebp], eax                 // move value of EAX register to location of y
mov    ecx, DWORD PTR _x$[ebp]                 //
locate x, read its value and move that value to ECX register
add    ecx, 1                                                    // add 1 to the value of ECX register
mov    DWORD PTR _x$[ebp], ecx                 // move ECX value to x location


What about ++x ?

mov    eax, DWORD PTR _x$[ebp]                 // think DWORD PTR _x$[ebp] as x location and set its value to 0  
add    eax, 1                                                    // add 1 to the value of EAX register 
mov    DWORD PTR _x$[ebp], eax                 // move value of EAX register to location of x
mov    ecx, DWORD PTR _x$[ebp]                 // locate x, read its value and move that value to ECX register 
add    ecx, DWORD PTR _x$[ebp]                  // locate x, read its value and add that value to ECX register 
mov    DWORD PTR _y$[ebp], ecx                 //
move ECX value to y location


Now, can you see the difference? Look on how the codes add 1 to register. If we write x++, means that, locate x, read its value, move to register (to do processing) then send it back to x location then add 1 to its value. Different thing happen if we write ++x. It means, locate x, read its value and add 1 to it, then send to register.

What about if the C++ codes running on CLR virtual machine? Just compile the codes with /clr /Fa to see the generated assembly codes. Let start with x++ first.

ldloc.0                ; _x$
dup       
add       
stloc.1                ; _y$
ldloc.0                ; _x$
ldc.i.1        1       ; i32 0x1
add       
stloc.0                ; _x$


Compare it to ++x result as following:

ldloc.0                ; _x$
ldc.i.1        1       ; i32 0x1
add       
stloc.0                ; _x$
ldloc.0                ; _x$
dup       
add       
stloc.1                ; _y$


Can you see the same pattern? The generated assembly codes are different because C++/CLI target is CLR JIT, not Win32 loader. JIT will compile the IL to machine language (1-on-1 correspondence to ASM) and the lowest level mechanism will be the same.

Happy coding !

Thx - R.A.M

Share this post: | | | |

Pointer Arithmetic and Array Indexing

In C/C++ there are two ways to access element of an array : pointer arithmetic and array indexing. Although the standard array indexing like a[10] is easier to understand, most of C++ developers prefer pointer arithmetic because it is faster. How it can be like that? Let see the following C++ codes:

int main()
{
    int *p, i;
    int x[10];               
// declare array x contains 10 integer elements  
    for(i=0;i<10;i++)x Idea =i;  // define x
    p=x;                        // array name without index is pointer to first element 
    p[2] = 100;             // assign using index (x[2] = 100)
    *(p+2) = 100;          // assign using pointer arithmetic

    return 0;
}

You can compile it using CL /Zi /Fa to get its ASM codes. In C/C++, array consists of contiguous memory locations with the lowest address corresponds to the first element and the highest address to the last element. Pointer to the first element in an array can be simplified by specifying the array name (without index) to a pointer. So, p = x, means p points to the first element x, or p == &x[0] is true. 

Pointers are sometimes used to access arrays because pointer arithmetic is often faster than array indexing. Statement like p[2] is equal to *(p+2). WHY it is faster? Let see patterns in its ASM codes below:

; p = x
    lea      EAX, DWORD PTR _x$[ebp]
    mov    DWORD PTR _p$[ebp], EAX
; p[2]=100

    mov    ECX, DWORD PTR _p$[ebp]
    mov    DWORD PTR [ECX+8], 100            ; 00000064H
; *(p+2) =100

    mov    EDX, DWORD PTR _p$[ebp]
    mov    DWORD PTR [EDX+8], 100            ; 00000064H


The only different is registers used by those two statements (ECX and EDX). ECX is a general purpose register that holds the count for various instructions. In the 80386 and above, ECX can hold the offset address of memory data. EDX holds a part of result from a multiplication or part of the dividend before a division. In 80386 and above this register can address memory data. In certain condition, addressing memory directly is faster than offset. That is why *(p+2) often faster than p[2]. For example, look at the following favorite C++ function:


void putstr(char *s)   // passing array of char s to a function using pointer
{
    register int t;
    for(t=0;s[t];++t) putchar(s[t]);
}

could be faster with

void putstr(char *s)
{
    while(*s) putchar(*s++);
}


Ok, now what happen in C++/CLI? Ok, simply just compile it using CL /clr /Fa. Here is the generated ILASM codes:

; p = x
    ldloca.s    3        ; _x$
    stloc.1               ; _p$
; p[2]=100
    ldloc.1               ; _p$
    ldc.i.8        8      ; i32 0x8
    add       
    ldc.i4.s    100     ; i32 0x64
    stind.i4   
; *(p+2) = 100
    ldloc.1                ; _p$
    ldc.i.8        8       ; i32 0x8
    add       
    ldc.i4.s    100      ; i32 0x64
    stind.i4   


There is no different, right? Means that both statements generate exactly the same ILASM codes. CLR (stack based) will generate equal machine codes for both!

Let assume this is one example why native C++ can over-perform C++/CLI. But some people argue, the execution environment (AppDomain isolation) in CLR virtual machine is safer. Interesting! Can anyone prove CLR is safer in this case?  

Thx - RAM

Share this post: | | | |

Re-Read C# Language and CLR Books

First time I learnt C# from ECMA 334 spec document then I read other language books like "Inside C#" and "Thinking in C#". Until now, I cant remember how many books I have "reviewed" (read some chapters without finish all), but I know that I keep the  following C# language books at my desk (of course at home):

- Printed ECMA 334 and 335
- The Complete Reference 2.0, Herbert Schildt
- The C# Programming Language, Anders Hejlsberg

For language, I feel enough with those three, but for CLR I consult regularly to the following:

- CLR via C#, Jeffrey Richter
- Essential .NET, Don Box
- Professional .NET Framework 2.0, Joe Dufffy
- Expert .NET 2.0 IL Assembler, Serge Lidin
- Essential Shared Source CLI, Dave Stutz

As my work load will slow down in June-July (at least no events), this is the time to read seriously. I plan to re-read ALL of those books one more time until the end of July. A lot of reading, but I will enjoy long nights again as my 2nd son will come in mid of July.

Thx - RAM

Share this post: | | | |

Abdul Kalam again

For developers, please interpret his advice as following:

"Thinking should become your capital asset, no matter whatever ups and downs you come across in your life." You have to think before you write codes (TFCL, thing first code later), not doing code first code later (CFTL). No matter how strong the pressures, make the best codes and ship the best product.

"Thinking is progress. Non-thinking is stagnation of the individual, organization and the country. Thinking leads to action. Knowledge without action is useless and irrelevant. Knowledge with action, converts adversity into prosperity." No matter how simple your tasks should be, think deeply and take necessary actions. Remember that you can't solve your current problem with your current knowledge. 

"When you speak, speak the truth; perform when you promise; discharge your trust…. Withhold your hands from striking, and from taking that which is unlawful and bad…". Let people know that you write the codes, you understand what you write/change (put comments). Be honest to your self first then to other people who will read your codes.

Those advices are critically important when you write codes to make product in an ISV (Independent Software Vendor). You are the key success of your company!

Happy coding!

Thx - RAM

Share this post: | | | |

Sometimes we forget about GC

When we use new operator to create an object, the object's memory is obtained from the managed heap. When GC claims that sufficient garbage has accumulated, it performs a collection to free some memory. GC consists of the following steps:

1 - The garbage collector searches for managed objects that are referenced in managed code.
2 - The garbage collector attempts to finalize objects that are not referenced.
3 - The garbage collector frees objects that are not referenced and reclaims their memory.


GC is fully automatic, "but to some degree", behavior of the garbage collector can be controlled via static methods on the class System.GC. This class can be used to request a collection to occur, destructors to be run (or not run), and so forth. Let see some of GC methods:

System.GC.Collect

Forces a garbage collection. You should generally avoid this and let the runtime determine the appropriate time to perform a collection. The main reason that you might be tempted to call this method is that you cannot see memory being freed that you expect to see freed. However, the main reason that this occurs is because you are inadvertently holding on to one or more objects that are no longer needed. 

System.GC.WaitForPendingFinalizers
Suspends the current thread until the finalization thread has emptied the finalization queue. Generally, this method is called immediately after System.GC.Collect to ensure that the current thread waits until finalizers for all objects are called. However, because you should not call GC.Collect, you should not need to call GC.WaitForPendingFinalizers.


When using GC.Collect, you can not see and control the order of how GC perform the collection. Let see following codes :


using System;
class X
{
    ~X() { Console.WriteLine("Kill X");}
}

class Y
{
     object Ref;
     public Y(object o) { Ref = o;}
     ~Y() { Console.WriteLine("Kill Y");}
}

class Test
{
      static void Main()
      { 
          Y y = new Y(new X());                      // Y and X objects will be created 
          y = null;                                            // y is set to null, GC will work on x and y
          GC.Collect();                                    // forces GC 
          GC.WaitForPendingFinalizers(); 
       }
}


You can not expect to see only "Kill Y" then "Kill X". It is possible to see "Kill X" then "Kill Y".

System.GC.KeepAlive
Prevent an object from being prematurely collected by holding a reference to the object. A common scenario is when there are no references to an object in managed code but the object is still in use in unmanaged code. GC does not recognize references to an object from unmanaged code, and might free objects that are being used exclusively in unmanaged code unless explicitly prevented from doing so. This method provides a mechanism that prevents the garbage collector from collecting objects that are still in use in unmanaged code.

System.GC.SuppressFinalize
Prevents the finalizer being called for a specified object. Use this method when you implement the dispose pattern. If you have explicitly released resources because the client has called your object's Dispose method. Dispose should call SuppressFinalize because finalization is no longer required.

High level recommendations to help improve garbage collection performance:

  • Identify and analyze your application's allocation profile.
  • Avoid calling GC.Collect.
  • Consider weak references with cached data.
  • Prevent the promotion of short-lived objects.
  • Set unneeded member variables to Null before making long-running calls.
  • Minimize hidden allocations.
  • Avoid or minimize complex object graphs.
  • Avoid preallocating and chunking memory.


In scenario when you need to release at a specific time, classes can implement the IDisposable interface, which contains the IDisposable.Dispose method that performs resource management and cleanup tasks. Classes that implement Dispose must specify, as part of their class contract, if and when class consumers call the method to clean up the object. The GC does not, by default, call the Dispose method; however, implementations of the Dispose method can call methods in the GC class to customize the finalization behavior of the garbage collector.

Please consult to MSDN, Rico Mariani PnP book and his blogs for clear strategy around working with GC. Happy coding!


Thx - RAM

Share this post: | | | |

From A.P.J. Abdul Kalam

 

Song of Youth,  A.P.J. Abdul Kalam

"As a young citizen of India, armed with technology, knowledge and love for my nation, I realize, small aim is a crime.
I will work and sweat for a great vision, the vision of transforming India into a developed nation, powered by economic strength with value system
I am one of the citizens of the billion; Only the vision will ignite the billion souls.
It has entered into me ; The ignited soul compared to any resource is the most powerful resource on the earth, above the earth and under the earth.
I will keep the lamp of knowledge burning to achieve the vision - Developed India
If we work and sweat for the great vision with ignited minds, the transformation leading to the birth of vibrant developed India will happen.
I pray the Almighty: "May the divine peace with beauty enter into our people; Happiness and good health blossom in our bodies, minds and souls".


Note : change the red color to Indonesia.

I visited his website to learn about him, http://presidentofindia.nic.in/. I got some of his inspired quotes that I want to share with all of INDC geeks :

"Thinking should become your capital asset, no matter whatever ups and downs you come across in your life."

"Thinking is progress. Non-thinking is stagnation of the individual, organization and the country. Thinking leads to action. Knowledge without action is useless and irrelevant. Knowledge with action, converts adversity into prosperity."


"When you speak, speak the truth; perform when you promise; discharge your trust…. Withhold your hands from striking, and from taking that which is unlawful and bad…"


"My worthiness is all my doubt His Merit – all my fear- Contrasting which my quality Does however appear "

You can read more about Abdul Kalam from Wikipedia and his website.

Thx - RAM

Share this post: | | | |

ATL Server on CodePlex

VC++ team is released of ATL Server library code as a shared source project on CodePlex! We now have the opportunity to add all the features and functionality to ATL Server and we can even share our expertise and code directly with the ATL community. ATL Server is a library of C++ classes that allow developers to build internet based applications. It provides much of the functionality required to build large scale internet sites, such as SOAP messaging, caching facilities, threading facilities, regular expression processing, management of session-state, performance monitoring, MIME support, integration with IIS and class for interacting with security and cryptographic infrastructure.

Project Site here.

The following parts of ATL Server are part of the shared project:

  • Core ATL Server Framework classes in atlisapi.h, atlstencil.h, atlserr.h
  • Caching classes in atlcache.h
  • Cryptography classes in atlcrypt.h
  • HTML generation on server side and reading on client sides in atlhtml.h
  • Performance monitoring classes in atlperf.h
  • Extension management classes in atlextmgmt.h
  • Server and client side support for SOAP based Web services in atlsharedsvc.h, atlsoap.h
  • Session-state classes and interfaces in atlsession.h
  • MIME/SMTP support in atlmime.h and atlsmtpconnection.h
  • Regular Expression support from atlrx.h
  • Stream helpers in atlsoap.h and atlhtml.h

The source code to the following tools will also become part of the shared source project:

  • clstencil.exe - used in running Request Handler DLLs or SRF Files from the command line
  • sproxy.exe - used in generating proxy classes for SOAP based Web Service clients
  • vcdeploy.exe - used in deploying ATL Server projects to IIS

Nice to have internal codes published !

Thx - R.A.M

Share this post: | | | |

STL / CLR in Orcas

Visual Studio Orcas Beta has been released. It contains a major refresh of STL/CLR (– implementation of STL that can operate with objects of managed types) with many bug fixes and two new adapters. You can try by downloading Orcas VPC and read the specs here. STL/CLR enables C++ developers to achieve the following :

- Use STL-like containers to store objects of managed types
- Use iterators to access elements stored in STL/CLR containers
- Use STL-like algorithms to operate on STL/CLR containers
- Use BCL generic and non-generic collection interfaces to operate on data in STL/CLR containers
- Use STL/CLR specific generic interfaces to operate on data in STL/CLR containers 

STL/CLR containers are "garbage collected", and the implementation is ‘verifiable’ allowing developers use these collections in Mixed (/clr), Pure (/clr:pure) and Safe (/clr:safe) modes.  STL/CLR containers cannot be used to store objects of native types and native pointers. Safe programming :) !

I am downloading Orcas now and print STL/CLR specs for my weekend.

Stay Tune Guys !

Thx - R.A.M

Share this post: | | | |

Ruby Programming Language

My Indian colleague, Ramkumar, asked me to take a look on Ruby. I installed it and I'm playing with its code samples while enjoying its free book, The Pragmatics Programmer's Guide. Below what I have read:

- Ruby is a true OO language. OO fans will find much in Ruby: everything's an object, meta classes, closures, iterators, and ubiquitous heterogeneous collections.
- File-based source code (more flexible than Perl)
- Ruby is easy to learn. It follows the Principle of Least Surprise---things work the way you would expect them to, with very few special cases or exceptions.
- Ruby a transparent language. Closer to the problem domain.
- Ruby is interpreter. It is a powerful scripting language like Phyton and Perl.

People learn Ruby to program better cos it can help them to focus on the problem, with fewer distractions. It will make our life easier (I think all languages promote this quote). Look how we create class and object in Ruby:

class Employee
  def initialize(fname, lname, level)
       @fname   = fname
       @lname    = lname
       @level      = level
  end
end

initialize is a special method in Ruby. When we call Employee.new to create a new Song object, Ruby creates an uninitialized object and then calls that object's initialize method, passing in any parameters that were passed to new. This gives us a chance to write code that sets up our object's state like constructor. To test it:

anEmployee = Employee.new("Risman", "Adnan", 10)
anEmployee.inspect » "#<Employee:0x401b299c @fname=\"Risman\", @lname=\"Adnan\", @level=10>"


Let see how this class can be inherited:

class TemporaryEmployee < Employee
  def initialize(fname, lname, level, duration)
    super(fname, lname, level)
    @duration = duration
  end
end

The ``Employee'' on the class definition line tells that a TemporaryEmployee is a subclass of Employee. Like what you guess Employee is a superclass of TemporaryEmployee. Pretty simple right? What about accessibility?

class MyClass
      def method1    # default is 'public'
        #...
      end
  protected          # subsequent methods will be 'protected'
      def method2    # will be 'protected'
        #...
      end

  private            # subsequent methods will be 'private'       def method3    # will be 'private'         #...       end   public             # subsequent methods will be 'public'

      def method4    # and this will be 'public'         #...       end end



In Ruby, we can access all the underlying operating system features. It has strong theoretical roots and an elegant, lightweight syntax. Although you can use Ruby for scripting jobs, many people use it for general-purpose programming. GUI applications, managing server machines, databases to middle-tier server processes. Ruby can server Web pages, interface to databases and generate dynamic web content. Now people are writing artificial intelligence and machine learning programs in Ruby. Ruby's finding a home as a vehicle for exploratory mathematics. And people all over the world are using it as a way of gluing together all their different applications. It truly is a great language for producing solutions in a wide variety of problem domains.  


Look on the graph and see how Ruby produced that using OpenGL Library:

require "opengl"
require "glut"

$ctrlpoints = [
    [[ -1.5, -1.5, 4.0], [ -0.5, -1.5, 2.0],
    [0.5, -1.5, -1.0], [1.5, -1.5, 2.0]],
    [[ -1.5, -0.5, 1.0], [ -0.5, -0.5, 3.0],
    [0.5, -0.5, 0.0], [1.5, -0.5, -1.0]],
    [[ -1.5, 0.5, 4.0], [ -0.5, 0.5, 0.0],
    [0.5, 0.5, 3.0], [1.5, 0.5, 4.0]],
    [[ -1.5, 1.5, -2.0], [ -0.5, 1.5, -2.0],
    [0.5, 1.5, 0.0], [1.5, 1.5, -1.0]]
].flatten;

$texpts = [[[0.0, 0.0], [0.0, 1.0]], [[1.0, 0.0], [1.0, 1.0]]].flatten;

display = proc {
    GL::Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT);
    GL::Color(1.0, 1.0, 1.0);
    GL::EvalMesh2(GL::FILL, 0, 20, 0, 20);
    GL::Flush();
}

ImageWidth=64
ImageHeight=64
$image = []

def makeImage
    for i in 0...ImageWidth
    ti = 2.0*3.14159265*i/ImageWidth.to_f;
    for j in 0...ImageHeight
        tj = 2.0*3.14159265*j/ImageHeight.to_f;

        $image[3*(ImageHeight*i+j)] =  127*(1.0+Math::sin(ti));
        $image[3*(ImageHeight*i+j)+1] =  127*(1.0+Math::cos(2*tj));
        $image[3*(ImageHeight*i+j)+2] =  127*(1.0+Math::cos(ti+tj));
    end
    end
end

def myinit
    GL::Map2d(GL::MAP2_VERTEX_3, 0, 1, 3, 4,
        0, 1, 12, 4, $ctrlpoints);
    GL::Map2d(GL::MAP2_TEXTURE_COORD_2, 0, 1, 2, 2,
        0, 1, 4, 2, $texpts);
    GL::Enable(GL::MAP2_TEXTURE_COORD_2);
    GL::Enable(GL::MAP2_VERTEX_3);
    GL::MapGrid2d(20, 0.0, 1.0, 20, 0.0, 1.0);
    makeImage();
    GL::TexEnv(GL::TEXTURE_ENV, GL::TEXTURE_ENV_MODE, GL::DECAL);
    GL::TexParameter(GL::TEXTURE_2D, GL::TEXTURE_WRAP_S, GL::REPEAT);
    GL::TexParameter(GL::TEXTURE_2D, GL::TEXTURE_WRAP_T, GL::REPEAT);
    GL::TexParameter(GL::TEXTURE_2D, GL::TEXTURE_MAG_FILTER, GL::NEAREST);
    GL::TexParameter(GL::TEXTURE_2D, GL::TEXTURE_MIN_FILTER, GL::NEAREST);
    GL::TexImage2D(GL::TEXTURE_2D, 0, 3, ImageWidth, ImageHeight, 0,
         GL::RGB, GL::UNSIGNED_BYTE, $image.pack("C*"));
    GL::Enable(GL::TEXTURE_2D);
    GL::Enable(GL::DEPTH_TEST);
    GL::Enable(GL::NORMALIZE);
    GL::ShadeModel (GL::FLAT);
end

myReshape = proc {|w, h|
    GL::Viewport(0, 0, w, h);
    GL::MatrixMode(GL::PROJECTION);
    GL::LoadIdentity();
    if (w <= h)
    GL::Ortho(-4.0, 4.0, -4.0*h.to_f/w, 4.0*h.to_f/w, -4.0, 4.0);
    else
    GL::Ortho(-4.0*w.to_f/h, 4.0*w.to_f/h, -4.0, 4.0, -4.0, 4.0);
    end
    GL::MatrixMode(GL::MODELVIEW);
    GL::LoadIdentity();
    GL::Rotate(85.0, 1.0, 1.0, 1.0);
}

    GLUT::Init();
    GLUT::InitDisplayMode (GLUT::SINGLE | GLUT::RGB | GLUT::DEPTH);
    GLUT::CreateWindow ();
    myinit();
    GLUT::ReshapeFunc (myReshape);
    GLUT::DisplayFunc(display);
    GLUT::MainLoop();


Cool :). As maybe some of you have heard, Silverlight will adopt Ruby for scripting, ... so take a look on that.

Thx - R.A.M

Share this post: | | | |

Teaching .NET Design Pattern at AIT

Again, I have to conduct design pattern training for Microsoft customer. This time we are at AIT (www.aithome.com) Batam with around 15 enterprise developers like Mr. Dondy. Honestly I am not really pattern man like Mr. Norman, but I do like its idea. 

Conceptually, design pattern is a "general repeatable solution to a commonly occurring problem in software design". Physically, it is design experiences in form of pattern catalog initiated by GoF (creational, structural and behavioural) and adopted/improved/customized by some people. Don't think design pattern as a component or code snippet, because no direct transformation from a pattern into codes. When you learn it, invest your time to understand the problem space, then use  pattern as template or "guru advice" for you to solve problem. You may find unique situations (constraint or requirement) in such a way you have to creatively custom your pattern implementation, but if you really understand the problem, I believe you can solve it.

For me design pattern is just another mental tools like math, algorithm and common data structure to sharpen our design skill. It needs lot of practices to master it once you got the ideas. Take pencil and paper to practice your math, algorithm, data structure and pattern (I do it until now). If I have to read books, use pink color highlighter (like me) to help you read faster other times. That was old and ancient way of learning that I just can't stop :). 

.NET design patterns typically show relationships and interactions between classes or objects for some specific design problems. Don't ever expect final application classes or objects. Design patterns are not for computational problems, they are collection design problems and its solutions. Design patterns deal specifically with problems at the level of design process (a language for software design engineer) and algorithms will be needed at the level of construction process. Once you got the pattern idea, you will find that not all software patterns are design patterns. Mr Dondy knows other patterns (I never agree with him, honestly) like software architect, enterprise application, service orientation and enterprise integration patterns. Believe me, those are awesome for you CV cosmetics but it will limit yourself. Be a developer who learn/know all of it but don't box you self in a box called analyst or architect. It works perfectly if your interviewer/manager doesn't understand about it (as usual) but in other side, it can stop you learning the most fundamental parts in software construction like discrete/concrete math, algorithm, and data structure, because you think you are high level analyst/architect. Just like C#, you should be able to box/un-box your self (I am welcoming Dondy to argue) between design and construction boxes to make you an high skilled developer.

Thx - RAM

Share this post: | | | |

Cool XBAP Demo

Take a look : http://www.00001001.ch/download/HOL/WPF_XBAP/OutlookWPF/OutlookUI%20Browser.xbap

Lab manual can be downloaded from: http://www.00001001.ch/download/HOL/WPF/Outlook_HOL_WPF.pdf


The lab binaries are located here: http://www.00001001.ch/download/HOL/WPF/Outlook_HOL_WPF_projects.zip

 

Thx - RAM

Share this post: | | | |

VSTS Training

Finally, Narenda Wicaksono joined DPE team as IT Pro evangelist effectively June 4, 2007. Nice to have ex- Student Ambassador and ex - MVP in my team! He spent his first week with me to conduct VSTS training for Chevron and now we are at AIT Batam for the same training. No training for himself. He had email communication with me before then he just joined, and we went to customers. 1st lesson for him, "learning by doing". Sometimes he asked me what is the content for tomorrow, and I said "let see tomorrow". That is the 2nd lesson! And of course, many more lesson as he is hired as fresh grad.

Actually, we can define contents of "messages" in our training, but we cannot define "communication protocol" until we know who are our target. At Chevron, our target is diverse audiences (IT admin, analyst, project manager, developer and tester) and our first challenge was to have a good scenario first that can attract attentions. I didn't know what was that. I just flew and talked about CLR compilation and code security (IL, code signing, round-tripping, reflection, etc). Once we got their attention, we flew naturally and brought them VSTS contents. I really enjoyed to explain them the core components of TFS (IIS Architecture, Web Services, SQL Server 2005, WSS, Reporting Service, etc), TFS core (version control, WI tracking, build automation and reporting), MSF process guidance, VS - architect (AD, SD, LDD), developer (CA, UT, CF, CC) and tester (LT, MT, TC) features. Yes, it took 5 days at Chevron and now we have to minimize it to 4 days at AIT.

I hope we will have one community session for VSTS later. I know some of you (let say, Mr Dondy) already know application, system and logical data center designs. But not many of you understand load, unit and performance tests in depth. These include profiler and team test APIs. 

Watch your INDC Geeks mailing list for our invitation.

Thx - RAM.

Share this post: | | | |