Interview with the Hedge Fund

by Kofi Sarfo 24. August 2009 00:03

We interviewed with a London-based Hedge Fund last Friday and, as usual, it was interesting. The first guy I saw (head of development) is a graduate of Conchango, a company that writes software of excellent quality using good developers, the latest software technology and techniques, etc. Also, they often kindly host the London Dotnet User Group meetings at their offices near London Bridge.

Naturally the interviewer asks fair questions along the lines of Value Types versus Reference Types and Garbage Collection. Inheritence and Shadowing. So far so good. Only when we get to the Messaging architecture used and extended at the previous client's site is there a little uncertainty. Without the source code, which we didn't take with us, we can't remember enough detail about the implementation from July 2008 so there's one shaky answer.

Next up is a question about our exposure to SQL Server 2005. Yup, we used it. Oh, which bits? That will be the new Try-Catch (after a little prodding about error-handling). We mention not having used CLR functions but being aware of the possibility which leads to a question about the components of the CLR... and we've a blank moment!

The JIT compiler! In fact we mentioned just JIT.

This is *all* that arrives. That's it. Nothing about Exception-Handling, Memory Management, Thread Management, Garbage Collection, Security, Managed Code, Type Safety - this is an impressive list already - Portable Executables nor IL never mind debugging and profiling services offered. Oh, there's more that wasn't mentioned. Code management (loading and execution), Application memory isolation, Access to metadata (enhanced type information) and Interop. Nice.

Then comes the first of a few quirky incidents. Hint: If ever an interviewer testing your C# knowledge offers the Base Class Library as a component of the CLR it's probably worth saying something. To prevent an already lengthy entry from growing needlessly still a summary will do here. When Interviewer #1 is replaced by a senior developer I then learn that impersonation does not work the way I've used it. Apparently, I've misundersood all along that using the identity element in the web config for an ASP.NET web application will not allow me to use credentials for a SQL Server connection. Maybe at that point I should have just looked it up on my iPhone and shown him this:


<system.web>
<identity impersonate="true" userName="domain\username" password="password" />
</system.web>
Of course that might have seemed a bit smug. Both nice guys. Both almost certainly good developers. I'd still like to work with them on the enterprise reporting solution due by the end of the year. However, during my next interview we won't assume that the interviewers have a monopoly on .NET understanding.

It's easier to forget the details of SQL Transaction Isolation levels (during interview)

by Kofi Sarfo 26. June 2009 00:45

So I interviewed again yesterday with a City-based asset management company you've probably not heard of but a cash rich client is exactly what we need right now. Shaking off a cold hit-hard mid-week wasn't ideal circumstance but it wasn't feeling less than fabulous that did the trick but in part, in fact, not being able to remember how each of the SQL Server Transaction Isolation levels might impact queries on the same table.

This is partly why I like interviews. Potentially embarrassing situations during which one is able to demonstrate what one cannot remember. Here's what the MSDN entry has to say about the SET TRANSACTION ISOLATION LEVEL (Transact-SQL) command which controls the locking and row versioning behavior of Transact-SQL statements issued by a connection to SQL Server. Yay.

So the story in a nutshell is that using this command it's possible, amongst other things, to allow dirty reads if that's the desired result. In order to try the code below in SQL Management Studio use one tab to run the transaction once all the necessary database objects have been created and another tab to view the results of the different isolation levels.

We create a table to use for holding some random values.

CREATE TABLE RandomLetters
(
     ID int IDENTITY(1,1) NOT NULL
    ,Letter varchar(32) NOT NULL
) 

In order to populate this table with some random values we rely on a stored procedure inspired by one over here.

CREATE PROCEDURE sp_GenerateRandomLetters
     @Length int
    ,@randomLetters varchar(32) OUT
AS
DECLARE @counter smallint
DECLARE @RandomNumber float
DECLARE @RandomNumberInt tinyint
DECLARE @CurrentCharacter varchar(1)
DECLARE @ValidCharactersLength int
DECLARE @ValidCharacters varchar(255)

SET @ValidCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+&$'

SET @ValidCharactersLength = len(@ValidCharacters)
SET @CurrentCharacter = ''
SET @RandomNumber = 0
SET @RandomNumberInt = 0
SET @RandomLetters = ''

SET NOCOUNT ON

SET @counter = 1
WHILE @counter < (@Length + 1)
BEGIN
        SET @RandomNumber = Rand()
        SET @RandomNumberInt = Convert(tinyint, ((@ValidCharactersLength - 1) * @RandomNumber + 1))
        SELECT @CurrentCharacter = SUBSTRING(@ValidCharacters, @RandomNumberInt, 1)
        SET @counter = @counter + 1
        SET @RandomLetters = @RandomLetters + @CurrentCharacter
END

And because we're going to populate this table with more than the one record:

DECLARE @randomLetters varchar(32)
DECLARE @randomLettersCount int

SELECT @randomLettersCount = 0

WHILE (@randomLettersCount < 1000)
BEGIN
        EXEC sp_GenerateRandomLetters 12, @randomLetters OUT
        INSERT INTO RandomLetters (Letter)
        SELECT    @randomLetters
        SELECT @randomLettersCount = @randomLettersCount + 1
END

None of this is even nearly shattering. It's not meant to be. Also, the following ought to error the first time it's run.

DROP TABLE ##OriginalRandomLetters

Now let's make that table which gets dropped by the statement above.

CREATE TABLE ##OriginalRandomLetters
    (
         ID int NOT NULL
        ,Letter varchar(32) NOT NULL
    )

And we sync this global temporary table with those values in the permanent table created above

INSERT INTO ##OriginalRandomLetters
    SELECT ID, Letter
    FROM RandomLetters

Confirm that we are good.

SELECT * FROM ##OriginalRandomLetters

And back on that other tab and therefore using another connection...

BEGIN TRANSACTION

    DECLARE @RandomUpdateCount int
    DECLARE @RandomID int
    DECLARE    @randomLetters varchar(32)

    SELECT @RandomUpdateCount = 0

    SET NOCOUNT ON

    WHILE @RandomUpdateCount < 20000
    BEGIN
        SELECT @RandomID = 1 + RAND() * 999
        -- SELECT @RandomID '@RandomID'

        EXEC sp_GeneratePassword 12, @randomLetters OUT
        -- SELECT @randomLetters '@randomLetters'

        UPDATE    RandomLetters
        SET        Letter = @randomLetters
        WHERE    ID = @RandomID

        SELECT @RandomUpdateCount = @RandomUpdateCount + 1
    END

ROLLBACK TRANSACTION

And finally let's try one of these transaction isolation levels

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
    SET TRANSACTION ISOLATION LEVEL SNAPSHOT
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

And the result of the following query will depend on the chosen isolation level.

SELECT * FROM RandomLetters

For example the READ UNCOMMITTED isolation level will allow you to see the changes being made to the values in the RandomLetters table whilst the transaction to update values is being run whereas most of the other isolation levels will cause SELECT * FROM RandomLetters to hang until the transaction is complete. In the case of SNAPSHOT there's an error: Snapshot isolation transaction failed accessing database 'WimiroDemo' because snapshot isolation is not allowed in this database. Use ALTER DATABASE to allow snapshot isolation.

I might be forgiven for not remembering all this behaviour during interview but not having a handle immediately on the correct strategy for ASP.NET paging and the 10 steps of the ASP.NET Page Life Cycle might have been forgetfulness too far. But that's what the internet is for, I say. Fingers crossed I get the gig anyway.

Tags:

SQL Server

AJAX and the URL short(ening)

by Kofi Sarfo 16. June 2009 23:42

A popular choice for shorterning URLs on Twitter is Bit.ly. It's just so nice and tidy with great analytics. For example, not long after shortening http://cnn.com/ we discovered that there have already been 2,659 clicks to that URL via Bit.ly.

I am using the C# API from @kersney by the way and found out that Bit.ly does do the sensible thing and return the same shortened URL each time you supply an unadulterated URL. What I've not yet done is built chains of shortened URLs that lead to each... seemingly endless possibilities! What the C# API code is missing is &history=1 querystring parameter to have the shortened URL added to the list displayed in Bit.ly History.

Some Default.aspx code to give this a go:


<body>
<form id="form1" runat="server">
<div style="width: 100%;">
Original URL:
<asp:TextBox ID="TextBox1" runat="server" Width="100%"></asp:TextBox>
<div style="text-align: right; width: 100%">
<asp:Button ID="Button1" runat="server" Text="Shorten" onclick="Button1_Click" />
</div>
</div>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</form>
</body>

And some codebehind:

protected void Button1_Click(object sender, EventArgs e) { TextBox2.Text = API.Bit("bitlyapidemo", "R_0da49e0a9118ff35f52f629d2d71bf07", TextBox1.Text, "Shorten"); }

Now we pretend that bit.ly takes ages to return a shortened URL so we use javascript instead.


<script src="http://bit.ly/javascript-api.js
?version=latest
&login=bitlyapidemo
&apiKey=R_0da49e0a9118ff35f52f629d2d71bf07"

type="text/javascript">
</script>

<script type="text/javascript">

BitlyClient.addPageLoadEvent(function()
{
BitlyCB.shortenResponse = function(data)
{
var s = '';

var first_result;
// Results are keyed by longUrl, so we need to grab the first one.
for (var r in data.results) {
first_result = data.results[r]; break;
}
for (var key in first_result) {
s += key + ":" + first_result[key].toString() + "\n";
}

document.getElementById("bitlyUrl").value = first_result['shortUrl'];
}
});

function getBitlyUrl()
{
BitlyClient.shorten(document.getElementById("rawUrl").value, 'BitlyCB.shortenResponse');
}
</script>

No prizes for guessing the elements in the document.


<body>
<form id="formeula1" runat="server">
<div style="width: 100%;">
<br />Original URL:
<br /><input type="text" id="rawUrl" size="100" value="http://wimiro.com" />
<input value="Shorten" type="button" onclick="getBitlyUrl()"/>
<br />
<br />Bit.ly URL:
<br /><input type="text" id="bitlyUrl" size="20" />
</div>
</form>
</body>

So, there are no postbacks anymore but does this make it AJAX? Honestly, I have no idea. I see mention of callback_method_name in the bit.ly javascript api so my guess is that, yes, this is asynchronous. But shall we bother to test this or do we try and involve jQuery?

I wonder whether I can piggy-back Twitter authentication

by Kofi Sarfo 15. June 2009 00:46

Didn't really fancy maintaining credentials for an application that is designed to work in tandem with Twitter so enter OAuth.net: "An open protocol to allow secure API authorization in a simple and standard method..."

What is this new thing then and why had I not heard of it before? See October 2007 entry in Hueniverse: Beginner’s Guide to OAuth. Not so new then.

Also, a little while ago we were in a room with developers and they brayed when asked if anyone liked the ASP.NET 2.0 Membership Controls. I think the Login control was mentioned specifically. They worked fine for me. So we go looking for reasons this - their seeming unpopularity - might be. Stack Overflow (because there's been no reference in minutes) answers one question of what to use for membership in ASP.NET. We're still none the wiser.

And there's more from the timely discoveries department. Tweetsharp: "A C# fluent interface for Twitter, designed for app developers" -- downloading source. I remember being corrected for returning this (or it could have been me) circa 2004 which we did so that we could chain methods but I can't remember what the argument against it might have been.

Listening to folks talk REST whilst running 10km

by Kofi Sarfo 12. June 2009 02:24

Caught .NET Rocks show #445 with Kenn Scribner on REST. A useful discussion about REST, SOAP, the evolution of 'web services' technology and where WCF best fits in. Listen here.

Notes:

.NET Rocks talk transcript

Full Circle on Action<T>

by Kofi Sarfo 6. June 2009 00:02

Reminded recently of a method for determining Prime Numbers (Sieve of Eratosthenes) and saw some Generic Collection Class action (p. 97 C# In Depth)

            List<int> candidates = new List<int>();

            for (int i = 2; i <= 100; i++)
            {
                candidates.Add(i);
            }
 
            for (int factor = 2; factor <= 10; factor++)
            {
                candidates.RemoveAll(delegate(int x)
                    { return x > factor && x % factor == 0; }
                );
            }
 
            candidates.ForEach(delegate(int prime)
                { Console.WriteLine(prime); }
            );

Bouncing around looking for code samples to see what we're missing in terms of Generics... we spot something. Switch on the Code: The Built-In Generic Delegate Declarations.

Difference between Func<T> and Action<T> is the latter doesn't have a return type. Too obvious to miss? Maybe. Quick search shows difference between new Action() and Lambda at Stack Overflow. Response from author of code sample above. Jon Skeet. 3900 answers on Stack Overflow in 8 months. Or 16 answers a day, every day.

Notes:

MSDN: Lambda Expressions

CodeBetter: Back to Basics - Delegates, Anonymous Methods and Lambda Expressions

BlogEngine.NET Deployment

by Kofi Sarfo 2. June 2009 05:53

First take involved opening solution in Visual Studio 2008 and publishing to localhost and then using FTP to send files individually whereupon we discover that using O2 mobile broadband (via USB) results in files arriving "successfully" on remote web server with file size 0KB. Yuck! Many more takes to replace "successfully" transfered files. Don't blame FileZilla because it's doing only as it advertises and we've had issues with FTP ourselves quite recently from within code we'd written.

Digression: It was necessary to compare file content between local and remote files before assuming successful transfer. Not pretty. Never discovered a better solution that didn't involve MoveIt.

Finally everything copied across and directory turned into Web Application using the DiscountAsp.Net unsurprisingly named Web Application Tool. Instead of blog appearance we have this compilation error!

So it turned out there are at least two ways of resolving this without trying to understand intricacies of ASP.NET Dynamic Compilation and being frustrated by not being able to delete Temporary ASP.NET files on a remote server which denies access to said directories and probably with good reason. Wondering why WebDAV isn't an option here though... probably a good reason I'm not aware of.

If you see this then everything's turned out okay. Global warming has been corrected. If you care in even the slightest this application defaults to using an XML file datastore and so we need to weigh up whether there's any advantage to pushing this into SQL Server. Climb the mountain because it's there? Okay, it's probably not quite a mountain and we'd not do it in a tutu.

Notes:

MSDN: Understanding ASP.NET Dynamic Compilation

Post Script:

It's a love/hate relationship with Infrastructure.

  • By their being responsible for deployment I'm sometimes spared the headache of failed deployment.
    • In this first instance someone else discovers/solves the problem.
  • By their being responsible for deployment I'm sometimes victim of failed deployment.
    • In the second instance someone else *is* the source of the problem.

Poetry very incidental.

Kiva Loans

  • Margret

    Margret

    Personal Housing Expenses

    Requested loan: $625

    Amount raised: $0

    Masindi, Uganda

    to buy iron sheets and doors for her house.

    Loan Now »

  • St Theresa Women Group

    St Theresa Women Group

    Clothing

    Requested loan: $3100

    Amount raised: $0

    Kasese, Uganda

    to buy clothes.

    Loan Now »

  • Zephanus

    Zephanus

    Fish Selling

    Requested loan: $200

    Amount raised: $0

    Kasese, Uganda

    to buy fish to sell.

    Loan Now »

To see more entrepreneurs »

Make a loan to an entrepreneur across the globe for as little as $25. Kiva is the world's first online lending platform connecting online lenders to entrepreneurs across the globe.