Thursday, January 14

The one good thing to come of the quake in Haiti ...

... is that we no longer have to put up with bullsh!t chatter on the "news" about Simon Cowell leaving American Idol. Hoohah!

Tuesday, January 12

On hiring, technical problems and tutoring

An interesting post popped up on the NYTM mailing list yesterday.


Hi,

I'm looking for a web programming tutor. I'm looking for someone to work with one of our web developers who has limited experience and wants to learn more. Our ideal candidate is someone with extensive experience creating and developing dynamic and robust websites from the ground up. Some of the major issues he will need help in is:


  • Identifying over framework/structure for site

  • Incorporating advanced GoogleMaps functionality

  • Account management features

  • CSS/javascript/ajax--front end functionality



We can compensate the candidate $25/hour. We will need the tutor to come to our studio for an hour long session 2-3 times a week. Our developer will have web development issues he is working on that the tutor will walk him through during the tutoring sessions. The structure will be fairly open and relaxed, and we're a really fun group, so the position should be (hopefully) enjoyable!

We will need the tutor to start ASAP. If you're interested or know someone who is, please contact me with a list of websites you created...


Trying to practice more patience, as well as indifference to those things which don't directly negatively impact myself or the important people in my life, I personally didn't bother to work out the math and respond, but tech-savvy DJ & entrepreneur Anthony Zeoli breaks it down for us:


I know you have good intentions and maybe you'll find someone to do this. It's just that, for someone to realistically get to your office three times a week, it's going to cost them $4.50 in train or bus fare if they can't walk to your office. They'd make $20.50. Now, let's chop 30% tax if it's not under the table. That leaves you with $14.35 to teach someone what they should already know? Let us factor in the to and from your office. Maybe that's another hour. Now, you're done to $7.17 (rounded down a penny) for two hours. That's below minimum wage!


$25/hour? In NYC? And you expect them to be BETTER than your existing developer who's having issues? Ludicrous is an understatement, and here's why:

1. Web development and teaching are two ENTIRELY different skillsets, and it's fairly rare to find good/great techies with equally good or great people skills that are critical to being able to effectively teach someone. Those relatively rare people with both tech AND people skills, as WELL as the inclination and patience to teach, are in a class by themselves, and often make a very healthy six figures as technical trainers with boutiques and large tech companies. Simply Hired tells us that a "web development trainer" makes an average of $136,000 annually in NYC; "sales trainer" in that category, $222,000.

2. A generic "tutor" in NYC on average makes $49,000 annually, per Simply Hired. A "computer tutor," also according to Simply Hired, makes $72,000 annually. Across all sectors and roles, technical roles in NYC average $91,000 annually. Mid-level .NET developers earn something like $82,000 annually; senior .NET roles, $92,000. Senior roles easily reach into healthy six figures of course, and architect and management roles soar far above.

How in the world, for three individual hour-long sessions per week, at Tony's calculated wage of $7.17/hour, can you expect to capture the interest of a worthwhile individual? What could anyone possibly not understand about this? Developing even "decent," not "great," business app software takes years of experience, and little of that is typically college time.

Furthermore, why are you bringing a tutor in-house to "fix" your broken developer? If readily-available, sometimes free, books, blogs, forums, videos, vendor websites or reasonable-cost on-demand training packages won't do the trick, then this developer is NOT worth investing in, and is probably simply not salvageable. In this business, you have to be motivated to learn, and capable of self-learning. Yes, it is GREAT to have a mentor -- HUGELY beneficial for both parties -- but even then, if the developer is not motivated or otherwise inclined to learn, then it's a waste of the mentor's time and the company's money.

Sounds like this company has a lot of issues, from interviewing and hiring through to day-to-day management. At a guess I'd say it's a newer, smaller operation trying to cut expenditures in the wrong places. You have to invest in your people, your equipment and your infrastructure -- from _day one_ -- in order to achieve success with software or web development. You can't build a sound building with rotten raw materials.

Finally, to be quite frank, what this REALLY sounds like is a company trying to get the wisdom & experience of a skilled developer for a paltry $75/week while expecting to have all their questions answered and problems solved, regardless of the ridiculously low wage and number of hours to be paid.

Wednesday, January 6

Custom URL Shortener/ID Encoder in Transact-SQL (T-SQL)

Recently I've been working on some public-facing web applications where I needed to expose non-sequential IDs to end users in email as both text and links. In a corporate intranet, or even client-serving extranet, environments, with help desk & administrative support available, I'd probably just use GUIDs all over the place, and let the help desk field the aggravation and educate the users on the cutting and pasting of, and pronouncing, GUID. (I'm evil, I know.)

Now in situations where user aggravation directly and/or substantially affects revenue or productivity, and the ability to leverage help desk type support is at a minimum, I decided to start encoding IDs, not unlike the hash a URL shortener like bit.ly gives you. (e.g. bit.ly/5tB2x5, where 5tB2x5 is your encoded or hashed value.)

I found a fairly simple to implement algorithm on Jonathan Snook's site. I initially encoded, or compressed, IDs in a C# port of Snook's work, and stored the result in SQL Server, as I had a bug in my decompression/decoding method and needed to lookup the values up.

I then found myself with a need to create these encoded ID values inside of stored procedures. I ported the work once again, this time to T-SQL. Again, encoding worked, but decoding failed. I was stymied until the keen eye of Patrick Muldoon, via Tech Valley Ruby Brigade, noticed a character set issue -- the decoding routine was not making the distinction between capital and non-capital letters, resulting in bad decoding. COLLATE to the rescue!

bad:


SET @currPos = CHARINDEX(@currentCharacter, @BigString)


good:

SET @currPos = CHARINDEX(@currentCharacter, @BigString COLLATE Latin1_General_CS_AS)


Thanks Patrick!

Complete T-SQL code for encoding:

CREATE PROCEDURE [dbo].[ShortenID]
@idToShorten numeric(18,0),
@shortenedID varchar(20) OUT
AS

BEGIN
SET @shortenedID = 'NULL ID'

IF @idToShorten < 1
RETURN

DECLARE @ShortChars varchar(100) = '8A2aBb95CcDdeFfGgHhJjK6kLMm3NnOPpQqRrSsTtUuV7vXxYyZ4z'
DECLARE @charBase int = LEN(@ShortChars)
DECLARE @currentCharacter char

DECLARE @shortened varchar(20) = ''

WHILE @idToShorten > 0
BEGIN
SET @currentCharacter = SUBSTRING(@ShortChars, (@idToShorten % @charBase), 1)
SELECT @shortened = @currentCharacter + @shortened
SET @idToShorten = FLOOR(@idToShorten/@charBase)
END

SELECT @shortenedID = @shortened
END


Complete T-SQL code for decoding:

CREATE PROCEDURE [dbo].[ExplodeShortID]
@shortenedID varchar(20),
@idExploded numeric(18,0) OUT
AS

BEGIN
SET @idExploded = -1

IF LTRIM(RTRIM(@shortenedID)) = ''
RETURN

DECLARE @ShortChars varchar(100) = '8A2aBb95CcDdeFfGgHhJjK6kLMm3NnOPpQqRrSsTtUuV7vXxYyZ4z'
DECLARE @charBase int = LEN(@ShortChars)
DECLARE @currentCharacter char
DECLARE @currPos int = 0

DECLARE @exploded numeric (18, 0) = 0

DECLARE @lenShortenedID int = LEN(@shortenedID)
DECLARE @i int = @lenShortenedID
DECLARE @pow int = 0;
DECLARE @someInt int = 0

WHILE (@i > 0)
BEGIN
SET @someInt = (-1 * ( @i - LEN(@shortenedID) ))
SET @currentCharacter = SUBSTRING( @shortenedID, @someInt+1, 1 )
SET @currPos = CHARINDEX( @currentCharacter, @ShortChars COLLATE Latin1_General_CS_AS)
SET @pow = POWER(@charBase, @i-1)
SET @exploded = @exploded + (@currPos * @pow)

SET @i = @i - 1
END

SET @idExploded = @exploded
END