Showing posts with label random. Show all posts
Showing posts with label random. Show all posts

Monday, June 27, 2011

Dearest Recruiter

Update:I expanded on this a bit over here: http://blog.jdconley.com/2011/07/how-to-recruit-great-engineering-talent.html

I'm taking some time out of my lunch break today, when I'd much rather be indulging in some geek porn over at Hacker News, to submit a plea on behalf of all the in-demand geeks out there.

You probably found my resume, my consulting company, my blog, my Linked In, my Facebook profile, the MySpace profile I haven't taken the time to delete, my Stack Exchange profile, and some personal blogs about my kids via Google. Did you actually read any of it? No? I am an entrepreneurial generalist that prefers to balance business, product, and technology. I do not want a heads-down, order-following, engineering role.

Yes, I joke about golden handcuffs, but I am happy in my current position. I work from home for the most part. I am working on autonomous startup-like projects that provide great satisfaction. I have some cool benefits and awesome perks. Oh yeah, and I'm paid well.

But, I digress. I do enjoy money. I am human, and a good American consumer. I like to buy stuff. My wife likes to buy stuff. We like vacationing. It's fun. So I'll make you an offer. I will consider your position if you can provide compensation like Sergey Aleynikov. Let's round it up to $500k/yr total compensation, and the work better be self rewarding as well. Yes, I'm serious.

Do I feel bad for asking for such a huge sum? No, I don't. Am I entitled to it? Probably not. But I'm happy in my position and a few thousand dollars extra will not change my mind. I am not interested in a market-competitive salary. I am not interested in being the 25th employee at the next great Groupon clone. I understand how company capitalization and ESOP's work.

Now, I might be interested in being the first employee at a startup or a technical cofounder, but it had better be really darn interesting. I've got my own ideas and stack of half finished prototypes to productize. :) On that note, consulting arrangements at > $200/hr will also be considered.

Stop contacting me with inappropriate jobs that have nothing to do with my experience. Stop attempting to relocate me to Indiana. Stop asking what it would take for me to move to a new position. Stop wasting my time. Please. Stop.

Best Regards,

The In-Demand Geek

Monday, February 9, 2009

You might be a great hacker if you...

A number of years ago I was doing some mentoring at a California state agency that shall remain nameless. I got my butt up in time to be into their office at 8am. (Ok, I'll be honest, usually I got up in time. I was late on a few occasions.) I led them down the path of learning ASP.NET from scratch. Together we built a great product that is still in use today on a highly trafficked web site. Some time late in the mentoring project a student came up to me and asked the strangest question. He wanted to know how I learned everything I was teaching them. He wanted to take the same classes.




The guy was an amazing engineer. He was methodical, had great documentation, dotted all his i's and crossed all this t's. But he wasn't a great hacker. He was a bit slow, and didn't have much creativity. It was around that time I started paying more attention to traits of great hackers, before Paul coined the term. The bastard! At that time I was really just looking for people that learned quickly and could get things done faster than the rest. Some day maybe I'll figure out how to be all witty and important and coin terms.

So, here we go, in no particular order – except the first one, which is the obvious transition from my enticing story above:

  • started off as a script kiddie

    A typical scenario looks something like the following, though could occur in any area (not just video games):

    1. Play Quake 2
    2. Get stupidly good at Quake 2
    3. Get bored with Quake 2
    4. Figure out how to cheat by writing scripts to rocket jump or speed hack
    5. Realize what you just did was coding, and it's fun and amazingly rewarding
    6. Change all direction in life (yes, even when you're 12 years old) so you can do more coding

  • often forget to shave

    "Wait a minute, you mean people do their own laundry?" Yes, you are exceptionally lazy. That's ok. You have more important things to do in life than worry about how you smell/look.

  • have ever worked on a project for 24 hours straight

    "Hold on! You don't work without sleep until a problem is solved?" And no, last minute procrastination doesn't count, and neither do production outages. Everyone's been there. I'm talking about all night sessions working to solve a problem that could have been done over a few normal working days

  • instantly quiet a room when you speak

    You don't talk much. You spend most of your time listening to others. You find idle chit chat to be boring and have quantitatively determined it's a waste of time. Maybe it's because you don't have much to say. But, what I think is more likely is that you only say things that are relevant and important. Thus, when you speak, the room listens. A room full of strangers doesn't count. They won't know you only say important things until you've trained them that way.

  • have ever gone to visit a friend and proceeded to ignore them because you must finish that stupid puzzle they had on their coffee table before putting it down

    See photo at top of post.

  • get asked to help debug other people's code

    There's a certain amount of pride a developer has over their code. No matter how logical it is to call someone in for help, it's always the last thing we do. If you're the guy people call for help, you're on the right track.

  • are naturally good at video games

    Ever pick up a game, and within minutes beat or come really close to beating, someone who's been playing it for months? This is a sure fire sign of your analytical and problem solving skills. Come to think of it, I think I'm going to start adding this to my interview process.

  • use every operating system in existence

    Sure, you think Windows sucks, but you use it because you play games on it and deep inside you know it doesn't really suck much worse than the competition. You know Linux is the best (DUH!) but you play with FreeBSD. You have OSX running on your laptop because those big icons and MacBooks are sexy. But really, it's more about curiosity than anything.

  • make a habit of picking up a new technology over the weekend

    Lego Mindstorms, anyone? Oooh, how about Adobe AIR or Microsoft Azure or iPhone development. You catch my drift.

  • are extremely critical of everything

    You find fault in everything from your takeout food to web sites to world economic systems. The world is an imperfect mess that needs to be cleaned up. And, of course, you could do it with a weekend and your new favorite development platform (that you haven't used yet)!


This is all I could come up with in the time I set aside for this blog post. So what do you all think? What am I missing? I'll update the post with your ideas as they come in, if they don't suck.

Tuesday, January 20, 2009

Concurrency. It's like doing the dishes

Since we moved to Palo Alto I've had the luxury of walking to work every day. Usually that's where I do my deep thinking. By the time I cruise by the Whole Foods it's really easy to ignore the activist-of-the-day petitioning something about global warming. But yesterday was different.

My walks to and from work were pretty normal. When I got home I decided to clean up a bit around the house, was doing the dishes, and had an odd moment of clarity. I threw down the sponge and ran over to my laptop to jot this down.

Usually I'm at a loss for analogy when explaining how concurrency works to a developer who has never had to deal with it before. So I throw out all kinds of highly technical terms and their eyes glaze over. But you know, it's actually really simple.

Managing concurrency is like doing the dishes. You can hand wash everything and be sure it gets cleaned perfectly every time or you can stick the dishes straight into the dish washer and take your chances. Most of the time everything will come out clean, but every couple loads you'll get a dish you need to wash again. Going straight into the dishwasher is way faster, and you can even do more than one dish at a time (assuming you have two hands).

If you want the technical description, I leave that as an excercise to the reader. Here's a Wikipedia article. And another over at Microsoft that's specific to database concurrency. See, told ya it's like doing the dishes.

Saturday, May 24, 2008

Windows Server 2008

For anybody who's been watching you will have noticed that I have had some fun trying to get x64 Windows Vista stable on my workstation. Well, because of all that fun I've been running good ole trusty XP Pro 32 bit (and Ubuntu) for the last 8 months or so. I noticed both Server 2008 and Vista SP1 came out and I thought, "hey, it's time for an upgrade!"

After my last episode installing Vista x64 on my workstation, I decided I should instead go for Windows Server 2008 x64 – I know, it shouldn't really make a difference, but it made me feel better! So I login to MSDN, download it, burn it to disc, and away I go. Before I know it, everything is installed and working. It's been over a week now and it's still working. Not a single crash! Amazing... It's almost like, dare I say it, I got a Mac crossed with Open BSD and a touch of Linux! ;)

I have to say, they did something right with Windows Server 2008 for us hardcore workstation users. It is the perfect blend of security, cutomizability, and sexiness. You gotta love a server operating system with all the IIS 7 goodness that lets you turn on Aero. :) Both of my printers even have drivers now!

However, I must confess, I did cheat a little bit. I disabled my on-board sound card that was the culprit for many of my BSOD's with the prior attempts at Vista x64 and bought a PCI sound card. Ah well, Server 2008 rules, Vista sucks! There. I said It.

Oh yeah, I did have one issue. For some stupid reason it didn't want to activate, giving me the stupid error:

Windows Activation Error: A problem occurred when Windows tried to activate. Error Code 0x8007232B. For a possible resolution, click More Information. Contact your system administrator or technical support department for assistance. DNS name does not exist.


Luckily there are about a million hits on Google on the subject. Here's the most concise one. Yeah, you read that right, enter the same exact product key and click activate again. You would think that's an error that would have been fixed in over a year...

Thursday, February 28, 2008

C# 3.0 Overview

It's been forever since my last post. I promise I'll do better. I've just been juggling three jobs. ;) But that has changed (more on that soon)!

The last couple of nights I did the same talk at two different user groups. Sacramento .NET User's Group and the Central California .NET User's Group. Thank you guys for having me, and not throwing any tomatoes. I think we had a good time at both events. Though, I did take up the whole two hours both times.

The talk was based on Jon Skeet's upcoming book titled C# in Depth which I had the pleasure of reviewing and providing technical feedback. We went through the evolution of C# from 1.0 to 3.0, explored a bunch of the new features, played Human LINQ (hilarious). Oh yeah, it was pointed out to me in the Sacramento group that the word "jumped" should really be "jumps". That's what I get for copying my work! hah! If anybody in the Sacramento area wants to help, I'd like to do it again and video tape it...

Stuff to Download
  • C# 3.0 Overview Presentation – In both talks I didn't have enough time to bore you guys with the "in depth" slides. Pick up Jon's book to learn the nitty gritty about how all that stuff works.
  • A Sorted Affair 2 – - A few weeks ago I published the first version of this on my blog. This one is much cooler.
  • Human LINQ – The code we executed with our Human LINQ provider.
  • Sort Performance – A quick exploration of the relative sorting speeds using different sort methods.

I'll write up another quick blog in a bit on the sort performance. It's quite interesting, indeed.

Friday, December 14, 2007

Unadulterated Expurgation!

Alright, so, occasionally I post something funny that happened recently. Yesterday I received a spam company broadcast email from an anonymous customer of mine. You know who you are! :)

Team Anonymous Company,

In each office Anonymous Company employees have inhabited, many attempts have been made to keep our refrigerators clean and sanitary. Keeping clean refrigerators only works if we all participate – yet despite the best team players on the planet, we’ve fallen short of the goal. Common comments run the gamut from, "I’ll never put 'my' lunch in there," to the more lyrical, "There’s a fungus among us!"

As a result of this circumstance, the many must suffer the failings of a few – meaning:

Every Friday afternoon at 4:00 p.m. our Sergeant of Sanitation, will remove and dispose of everything from every refrigerator – as in: any one thing, each thing, the sum of all things, collectively all, the aggregate of all, anything at all, the totality of all within, including or comprehending all things, a comprehensive sweep of any and all things, whatever it is, whatever is left, nothing will be left, the sum total of all things, the Full Monty, the whole enchilada (frozen and unfrozen), the whole shebang. In short, every Friday at 4:00 p.m. all the refrigerators will experience an unadulterated expurgation!

Many thanks in advance for your cooperation and understanding,

The Management


Good thing I don't use the fridge...

Thursday, December 6, 2007

Geeks With Kids

I was just IMing with a good geek friend of mine. This is what happens when you give paranoid geeks kids (names removed for obvious reasons).

(5:08:06 PM) Geek Friend: i'm outta here, i gotta go home,
looks like the kids are fighting
(5:08:15 PM) Geek Friend: no adult supervision
(5:08:20 PM) Me: haha
(5:08:26 PM) Me: you watching them on camera?
(5:08:27 PM) Geek Friend: i'm so glad my parents didn't have
video cameras all over my house when i was their age
(5:08:30 PM) Me: hahahha
(5:08:34 PM) Geek Friend: watching, listening
(5:08:39 PM) Me: and they know?
(5:08:42 PM) Geek Friend: going to go ground two of them
(5:08:44 PM) Geek Friend: yeah, they know
(5:08:47 PM) Me: wow
(5:08:56 PM) Me: and they still act up
(5:08:56 PM) Me: crazy
(5:09:04 PM) Geek Friend: kid0 was straight up punching kid1
just now
(5:09:08 PM) Geek Friend: elbowed him in the face
(5:09:17 PM) Geek Friend: tried to gouge his eyes with her
fingers...
(5:09:17 PM) Me: nice
(5:09:19 PM) Geek Friend: crazy fight
(5:09:25 PM) Geek Friend: never seen them do anything like
that before
(5:09:30 PM) Me: well get goin!
(5:09:33 PM) Me: before one of them dies
(5:09:38 PM) Geek Friend: i called them
(5:09:42 PM) Me: ah
(5:09:43 PM) Geek Friend: they're sitting in the corners
of the room
(5:09:46 PM) Me: lol
(5:09:47 PM) Geek Friend: and can't move
(5:10:05 PM) Geek Friend: i turned on the alarm, i told
them if they move, the alarm will go off and the police
will come
(5:10:21 PM) Geek Friend: (not true though) just a really
loud noise until i shut it off
(5:10:49 PM) Geek Friend: later

Friday, November 30, 2007

An Entrepreneurial Story

I don't remember how exactly I got there, but while clicking through my morning feeds I ended up at the very interesting story of an Australian .NET micro ISV startup called Shuffle Text. They outline pretty much everything we learned when we started Coversant nearly seven years ago.

Some Gems
"And while we believed that technical differentiation would be enough to sell our product, we ended up being dead wrong."
"Change, it turned out, ended up being one of our worst development enemies."
"Of all those Google Ads signups, we got 0 feedback. All feedback on the product beta came from friends or friends of friends."
"There’s a bajillion ISV’s out there all competing to sell their crappy untested memory leaking piece of junk software. No matter how much time you spend perfecting your algorithm, improving the performance, and making sure you’ve got zero tolerance for leaks, NOBODY CARES. At the end of the day, it’s getting noticed that matters, convincing people that they should take a bet on you to solve their problems."

Don't give up guys. The product's been out less than a month and people are blogging about you! Your marketing seems pretty solid to me. While I don't have a use for your software at this very second. I'll certainly keep it on my radar. Oh yeah, consider putting out a completely free version, as in beer, not a trial.

Tuesday, November 27, 2007

How much space are all my sql tables using?

I deal with a few dozen databases on a daily basis. Often times I wonder "What the heck is making this database 100GB?" Sure, you can click around in Management Studio and find figures on a table by table and index by index basis, but there has to be a better way!

So, I asked a colleague of mine – who happens to be the guy that did all the database work on the SoapBox products and the best database dude I know. He didn't have a good answer for me so he whipped up this tiny script [Edit: After reading my blog he told me he actually adapted the script from one he found on the net that didn't quite work] in a few minutes. It makes my head spin. It's not perfect, but it's darn close.

WITH table_space_usage
( schema_name, table_name, index_name, used, reserved, ind_rows, tbl_rows )
AS (
SELECT s.Name
, o.Name
, coalesce(i.Name, 'HEAP')
, p.used_page_count * 8
, p.reserved_page_count * 8
, p.row_count
, case when i.index_id in ( 0, 1 ) then p.row_count else 0 end
FROM sys.dm_db_partition_stats p
INNER JOIN sys.objects as o
ON o.object_id = p.object_id
INNER JOIN sys.schemas as s
ON s.schema_id = o.schema_id
LEFT OUTER JOIN sys.indexes as i
on i.object_id = p.object_id and i.index_id = p.index_id
WHERE o.type_desc = 'USER_TABLE'
and o.is_ms_shipped = 0
)
SELECT t.schema_name
, t.table_name
, t.index_name
, sum(t.used) as used_in_kb
, sum(t.reserved) as reserved_in_kb
, case grouping(t.index_name)
when 0 then sum(t.ind_rows)
else sum(t.tbl_rows) end as rows
FROM table_space_usage as t
GROUP BY
t.schema_name
, t.table_name
, t.index_name
WITH ROLLUP
ORDER BY
grouping(t.schema_name)
, t.schema_name
, grouping(t.table_name)
, t.table_name
, grouping(t.index_name)
, t.index_name

I hope that hurts your head as much as it does mine. Just goes to show that I'm no SQL guru, I guess. But hey, if you ever want to know where that space is going in your database, this script will tell you!

Tuesday, November 20, 2007

More Visual Studio 2008 Beta 2 to RTM Upgrade Gotchas

Yesterday I posted on the first thing I ran into. Today I ported another project and hit a couple more snags.

  1. Linq to Sql Unicode Byte Header
  2. Linq to Sql Add/Remove Method Changes
  3. ASP.NET Listview Changed from itemContainer to itemPlaceholder
Linq to Sql Unicode Byte Header

The xml document that makes up the Linq to Sql dbml file is declared to be in unicode format. For some reason my file was not saved with the unicode byte header. Apparently this didn't matter to the beta 2 framework, but in RTM release the project failed to build and double clicking on the designer caused the error "There is no Unicode byte order mark. Cannot switch to Unicode."

When the error occurs it opens the dbml file as XML. So, I just moved my cursor to the first position. Hit enter then backspace and saved the file. Visual Studio 2008 RTM put the Unicode Byte Header in for me and everything was kosher.

Linq to Sql Add/Remove Method Changes

The Linq to Sql Table<T> and ITable has changed the signature for adding and removing entities. Instead of the Add and Remove methods there are now InsertOnSubmit and DeleteOnSubmit. This makes sense, as it was not obvious what Add and Remove would do. These new names make a lot of sense to me and were outlined in a msdn forum posting a few months ago.

ASP.NET Listview Changed from itemContainer to itemPlaceholder

It looks like a few bloggers already beat me to this one, but the behavior of the itemContainer in an ASP.NET Listview has changed and the new control ID you have to use is called itemPlaceholder. Daniel Moth has a good description on his blog here. The annoying thing about this change for me was that it showed up at runtime, and not compile time. Though the runtime message is pretty descriptive: System.InvalidOperationException: An item placeholder must be specified on ListView 'ListView1'. Specify an item placeholder by setting a control's ID property to "itemPlaceholder". The item placeholder control must also specify runat="server".

Wrap Up

Well, that's all I've run into so far. I'm sure I'll find more issues as I wrote quite a bit of (production) code under 2008 Beta 2. I'll make sure to summarize any more findings here.

Tuesday, November 13, 2007

ASP.NET MVC Framework

I'm a huge fan of Test Driven Development and I've been looking forward to the ASP.NET MVC (Model View Controller) Framework to increase the level of testability of web projects. Scott Gu just posted a great and frighteningly in-depth article – I don't know how he has the time. If you like releasing quality/tested, code, check it out. If you're not a developer, make your developers look at it.

Friday, November 9, 2007

Dvorak's Gone Mad

Maybe I'm just young, arrogant, and naive, but I think John's getting a little senile. In his latest rant for his PC Mag column he bashes Google's plans for the Open Handset Alliance with the title "The Google Phone is Doomed". Go read that if you haven't already and work your way back here. Don't get me wrong, I'm not convinced the project will work either – more on that later, but his reasoning confuses me.

Why Dvorak Thinks it Won't Work
  1. Google isn't charismatic
  2. Smartphones suck
  3. Nobody wants the internet on their phone

Google isn't charismatic? People don't love Google? Really? Google has more mindshare than pretty much any internet company out there. Ok, so they put out a crappy social networking tool called Orkut that nobody has heard of. I'm not sure how that relates to the potential success of an open phone product.

Smartphones currently suck. I definitely won't be arguing with that. The operating system user interfaces are crap and the software packages suck. However, I don't get how that has anything to do with a vaporware smarthpone due out some time in the future. If anything, an open platform should lead to a bunch of startups trying to build the next great phone interface. If they can pull it off, this should jumpstart an entire industry of reform. Apple did some good things with the iPhone. I see no reason why the same can't happen with OHA.

I'm not sure what year he's living in, but pondering why anyone would want internet on the phone when they could use the phone is just plain dumb. How do you know the phone number of the restaurant without the internet (or finding a phone book somewhere)? And why would I want to talk to someone when I can get more information myself on Google or [insert name of search startup here]? Maybe it's just me, but this seems like someone arguing to keep their fax machine instead of getting email, or keep their email instead of getting instant messaging.

Why I think it might not work

Alright, so maybe I don't agree with everything John brings up, but I do agree with one. Google wants to roll up the entire mobile market. The carriers, the operating systems, the software, and the hardware manufacturers. I don't see one of the biggest industries in the world taking that lying down.

In addition to the huge hurdles on the business side of things the technical challenges are staggering. Phones are not simple platforms to build on. And from what I've seen Google has yet to produce a large, complex, consumer facing product. They have a great back end platform and a boatload of itty bitty – dare I say widget – sized front end applications. An operating system and SDK that runs on a phone will prove to be a huge task, indeed.

In any case, "doomed" is pretty uncalled for. Of course, I did read his article, look at his ads, and now all of you are going to head over there too. So, I guess that's a success... And hey, I'm just a punk kid anyway! :)

Sunday, October 7, 2007

Vista Rant

Next month Vista will have been out in RTM for a year (it was released on 11/30/2006 to the volume/dev world). Why is it then, that it still doesn't work?

When I originally bought my current workstation, almost two years ago, I set it up with four partitions (I had a terrabyte RAID). I installed XP Pro 32 bit for games and Windows Server 2003 x64 for development. I left two open partitions, one for Vista, and one for some flavor of Linux. For the first six months of its life I spent most of my time in XP Pro x86. It worked, but I was wasting my fancy 64 bit hardware!

The beginnings — x64, take 1

On June 6 2006 I blogged about my experience installing Vista on my workstation. At the time it went reasonably well. Heck, my system passed the hardware compatibility wizard with flying colors! However, I really should have posted some follow-ups.

A week later — x64, take 2

After I started actually using Vista, it started crashing, a lot. I'd get at least one blue screen a day. I looked at the minidumps and they were all related to one of my NVidia drivers. It would be either the NIC or the sound or the SATA or the RAID — yeah, pretty much everything that comes with my motherboard (I bought it for the pretty colors). One day I noticed a Windows update for my NVidia RAID drivers. "Cool", I thought. Maybe they sped them up or improved stability. The drivers installed; my system rebooted; it bluescreened; repeat. After much frustration I switched to XP Pro x64.

A month later — x64, screw you

XP Pro x64 was fairly stable, but I still had serious issues with the interaction of the drivers. If I was using the network heavily and then started using the sound card heavily: Kablammo! BSOD! I sort of learned how to work around this and would mute my music before doing anything intensive over the network. Needless to say this was very annoying. I switched to XP Pro x86.

December, 2006 — Vista x64 RTM install

"Ok, Vista is RTM now", I thought. "Surely NVidia has got their act together now!" They're working closely with Microsoft on this stuff, right?!

December, 2006 — Vista x86 RTM install

"Ok, x64 is the bastard child of hardware", I thought. "Surely this will work."

December, 2006 — Back to the trusty XP Pro x86 partition

Yeah, back on XP. I'll spare you the details.

August, 2007 — Vista x86 install

"Ok, it's been a million computer years now", I thought. "Surely all my crash reports and support incidents have caused some bug fixes." Not so much. I even installed it on a PATA drive, no RAID required. To add to the pain, I also purchased a D-Link DWA-130 USB Wireless N Adapter for my desktop at the same time. I can't pass on the promise of speed with no wires. "What?! No Vista drivers?! I quit!" What's with a new product (released in July 2007) not having Vista drivers? Oh, there are beta ones available now — they don't work either.

August, 2007 — XP x86 Pro for life

After over a year of struggling and giving it a chance, I've given up. Either Microsoft or these hardware/driver vendors need to get their heads out of their asses, take some initiative, and fix this crap. I'm officially a hateful bastard until someone shows me some reason not to be.

October, 2007 — The world should know

I wrote this blog. It feels good to vent. Much cheaper than a therapist.

Wednesday, September 5, 2007

List of Country Names

Today I had to build yet-another-list of country names for a web site drop down form. I did some Google searching for about 10 minutes and didn't find anything that was free. I dunno, maybe I'm just blind... I did, however, find a list on Wikipedia. So, I decided I'd pull it down and parse it up. Here's the code:

static void Main(string[] args)
{
string fullpage;
using (WebClient wc = new WebClient())
{
byte[] pageBytes = wc.DownloadData(
@"http://en.wikipedia.org/wiki/List_of_country_name_etymologies");
string encoding = wc.ResponseHeaders["Content-Encoding"];
fullpage = wc.Encoding.GetString(pageBytes);
}

MatchCollection countryMatches = Regex.Matches(fullpage,
@"<p><b><a href="". ""\s*title="". "">(?<country>. )</a></b>:</p>",
RegexOptions.Multiline);

foreach (Match m in countryMatches)
{
Group g = m.Groups["country"];
Console.WriteLine(g.Value);
}

Console.WriteLine("done");
Console.ReadLine();
}

As you can see it's dirt simple. Just a WebClient to download the page (holy crap it's big) and a simple Regex call. Presto! A list of countries I'll be dropping into a database so we can edit it later.

Tuesday, August 21, 2007

Relocation

Well, I've officially relocated my blog here, to jdconley.com. The old blogging engine I was using really sucked. This one seems a lot better. And if I don't like something, the source code looks pretty clean so I can get my hands dirty and change it. I'm also a fan of one of the Haacks that wrote it -- well, his blog at least.

In addition to a new blog engine my new location has implicitly granted me a little freedom. Fear not, my blog will no longer be 100% about Coversant related items. I've been exploring the wide world of .NET 3.5, Visual Studio 2008, and everything in between. I've got a few articles that need some polish and I'll be posting them here.

Wednesday, June 20, 2007

Friend Photosaver for Facebook

By now everybody who knows what Facebook is, knows they announced an open platform for integrating with it. Interestingly enough Microsoft was a launch partner of theirs so there is also a shared source .NET API layer available. We decided to jump on the opportunity and published SoapBox for Facebook. Chris mentioned this in his announcement blog earlier.

But, as with anything that goes to production, adding cool features quickly turned into fixing uncool bugs, scope discussions, planning sessions, and then it became work.

I had a bit of a realization yesterday. I hadn't written code for the sheer fun of it in a really long time. Don't get me wrong, I love the stuff I do (almost) every day. We're coding cutting edge stuff here and it's a blast. But, I wanted to do something for me! So I wrote a screensaver.

Strange, huh? The guy that writes blogs on memory management, async programming, and other maddening things decided to hack together a screensaver. You'll just have to get over the shock of it all... Research was done, scope was decided, fingers flew. A few hours later, I had a screensaver! At 2am I decided on its name (probably a bad idea), Friend Photosaver for Facebook, whipped up an installer and submitted the app to Facebook. Catchy isn't it? Yeeeah. Anyway, though the name stinks, I think it's a pretty cool screensaver.

It aggregates the list of all your photos with all of the photos of your friends, and picks them at random. It then stuffs the photo in a random spot on the screen where it will be visible. Right now it only displays on the primary screen. Secondary screens are blank. Here's a little preview:

Screen Saver

If you're a Facebook user you can login and install my screensaver. The rest of you... well, this is pretty useless. But you should be on Facebook too. Oh, and (shameless plug), don't forget to use SoapBox for Facebook. :)

Thursday, April 5, 2007

YouTube Getter

Usually everything I post here is serious business. Well, not today! Today, we're going to look at how to get the raw video stream for YouTube videos. Why, you ask? Well, curiosity, mostly. :) Some people like sports, I like problem solving. There are a number of browser plug-ins and web sites that do this already, but hey, it was still fun.

YouTube offers a bit of an API for developers to mess with. It's mostly for grabbing sets of videos and preview images and such. They also let you embed their player in your pages. That's awfully nice of them, but what if I don't like their player? What if I want a sexier player? Well, if you've got something that can play/convert Flash Video (FLV's), here's the full C# code to grab the FLV URI (pieces dissected below):

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Collections.Specialized;

namespace JDFun
{
public static class YouTubeGetter
{
public static Uri GetFlvUri(string viewUri)
{
return GetFlvUri(new Uri(viewUri));
}

public static Uri GetWatchUri(Uri flvUri)
{
NameValueCollection qry = HttpUtility.ParseQueryString(flvUri.Query);

string videoID = qry["video_id"];
string watchUri = string.Concat("http://www.youtube.com/watch?v=", HttpUtility.UrlEncode(videoID));

return new Uri(watchUri);
}

public static Uri GetImageUri(Uri flvUri)
{
NameValueCollection qry = HttpUtility.ParseQueryString(flvUri.Query);

string imageUri = qry["iurl"];

return new Uri(imageUri);
}

public static Uri GetFlvUri(Uri viewUri)
{
// so either i've got the embed link or the watch link

//watch link: http://www.youtube.com/watch?v=up-RX_YN7yA
//embed link: http://www.youtube.com/v/up-RX_YN7yA

string toQuery = null;

NameValueCollection queryString = HttpUtility.ParseQueryString(viewUri.Query);

string videoId = queryString["v"];

if (null != videoId)
{
toQuery = string.Concat("http://www.youtube.com/v/", videoId);
}
else
{
toQuery = viewUri.ToString();
}

if (null == toQuery)
throw new InvalidOperationException("Not a valid YouTube Uri.");

Uri queryUri = new Uri(toQuery);
//ok we have the uri to query, now go there and get redirected.
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(queryUri);
req.AllowAutoRedirect = true;

// make them think we're coming from a direct link
req.Referer = string.Empty;

// firefox rules!
req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3";
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
{
string absoluteRedirectLocation = resp.ResponseUri.AbsoluteUri;

//replace the swf with the get_video request
if (!absoluteRedirectLocation.Contains("/p.swf?"))
throw new InvalidOperationException("Unrecognized Uri. YouTube changed something.");

absoluteRedirectLocation = absoluteRedirectLocation.Replace("/p.swf?", "/get_video?");

//return the absolute URI for this request
return new Uri(absoluteRedirectLocation);
}
}
}
}

Ok, wow, that's a lot bigger than I remember. Here's the basic idea.

  1. Get the video ID from the given URI. The URI could be the "watch" URI, or it could be the URI from the embed code they give you.
  2. Load the video directly based on the video ID, at the embed URI.
  3. Make a HTTP Request and get redirected to another URI, (which happens to contain the Image URI, and a special token "t").
  4. Know the magic URI where they keep the video streams (I cheated) and use it.

Now wasn't that fun? :)

Tuesday, November 21, 2006

XSLT For MSDN Product Keys

Here at Coversant we're Microsoft partners. We have MSDN subscriptions for all our developers/testers, and we share the same set of license keys. Rather than give everyone willy-nilly access to the MSDN download web site (ick, lots of bandwidth suck) we setup an internal file share for MSDN installation files, CD images, etc. We used to have all the product keys in there just saved as html from Microsoft's web site. However, that's no fun!

In the spirit of having fun and being developer friendly, Microsoft is nice enough to offer an "Export Key List to XML" button on the web page where we view all our product keys. So, I clicked the button. Out popped a very nicely/simply formatted XML document, like the following:

<?xml version="1.0" standalone="yes"?>
<Your_Product_Keys>
<Product_Key
Name="All products requiring a 10-digit product key"
Key="xxx-xxx-xxxx"
Key_Type="Retail"/>
<Product_Key
Name="Windows Vista Ultimate"
Key="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"
Key_Type="Retail"
Date_Key_Claimed="2006-11-20 17:36:11.787"/>
<Product_Key
Name="Windows Server 2003 R2 Standard Edition"
Key="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"
Key_Type="Retail"
Date_Key_Claimed="2006-11-20 17:36:08.270"/>
<Product_Key
Name="Office 2007 Desktop Programs"
Key="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"
Key_Type="Retail"
Date_Key_Claimed="2006-11-20 17:35:57.537"/>

...

</Your_Product_Keys>

I whipped up a quick XSLT you might find useful to transform this to a really ugly, really simple, x-html page (yeah without the namespace declaration).

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<body>
<h2>MSDN Product Keys</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th align="left">Product Name</th>
<th align="left">Product Key</th>
</tr>
<xsl:for-each select="/Your_Product_Keys/Product_Key">
<tr>
<td><xsl:value-of select="@Name"/></td>
<td><xsl:value-of select="@Key"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>

</xsl:stylesheet>

Then I made one quick edit to the xml file so friendly xslt aware web browsers will do the transform for me:

<?xml version="1.0" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="productkeys.xslt"?>
<Your_Product_Keys>
...
</Your_Product_Keys>

Presto-chango, we now have an easy to update central listing of our MSDN keys. Now if only MS had a web service that took my Live ID credentials and gave me back that XML...

Friday, September 29, 2006

The Catch with GoDaddy Dedicated Hosting

I'm not known to get easily frustrated or publicly rant about something, but here goes. The public web site and soapbox.net IM service for Coversant is hosted with GoDaddy using their dedicated server plans. This makes things real easy for us. We don't have to manage hardware somewhere in a colo. We get an ftp site for backups. And most of all we get the convenience and control of a dedicated system. It's also very reasonably priced. Ah, but there's always a catch.

Some time near the end of last month our daily and hourly SQL Server backups went on a rampage. The hourly transaction log backup we have scheduled was stuck in a loop so it never reset itself. We were uploading the entire transaction log for the month every hour. The end result was a constant stream of uploading to our FTP backup site, which is hosted by GoDaddy as well. Oh, I should mention the FTP backup is a service we pay for monthly in addition to any dedicated server plan. Here comes the fun part. The bandwidth used to connect to our FTP backup site is charged at the normal rate as if you were serving up web pages to customers. If you go over your monthly allotment you get charged the burst bandwidth rate of $1.99/1000MB. Last month we went over 661 times, or roughly 661GB. You can do the multiplication there. I should mention a nice customer support rep discounted it 50% for us. I'd really hate to have his job. . .

While this isn't that much money in the scheme of things, it is really freaking annoying. It would have been nice to get a phone call letting us know the first time we went over, not when we got our monthly statement. And why do we have to pay for bandwidth to a service we pay for that's hosted by our hosting provider and is very likely even located in the same data center. Aaargh!

So, in conclusion, we're researching what needs to be done to move to a local colo or perhaps another, slightly more expensive but not so unreasonable, dedicated hosting provider. Oh, we're still sorting out what caused the SQL backup issue.

About the Author

JD Conley is an entrepreneur and hacker, currently working away his golden handcuffs at Playdom, a subsidiary of the Walt Disney Company, since Hive7 was acquired. We make social games. The views and opinions expressed on this post are his and do not necessarily represent or reflect those of The Walt Disney Company.