Three Is It

Because two isn't enough and four is just too many

Our nation is somewhat sad, but we’re angry. There’s a certain level of blood lust, but we won’t let it drive our reaction. We’re steady, clear-eyed and patient, but pretty soon we’ll have to start displaying scalps.
George W. Bush
Home Blogs Genealogy Brad's Bookshelf Subscriptions Contact Sign in
 

About the author

Brad Butts is a .NET developer and architect. He is married with children and enjoys reading, working out, and genealogy is his five minutes of spare time.
E-mail me Send mail
National Debt Clock

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010

CodeMash 2009: Day 2

Key Note Speaker: Eric Meyer

Eric Meyer headlined the morning keynote for CodeMash 2009, day 2.  I think the title of his talk was something like, “How Javascript will Save the World.”  He talked about innovations using Javascript to play flash movies and to standardize fonts on the web and he talked about how Microsoft browsers tend to screw up the standardization effort.  He also mentioned other cool Javascript efforts like Nifty Corners and Bluff.  A problem he sees in this space, though, is that all these efforts invariably produce new Javascript libraries: why not have these libraries parse and process CSS instead?

Like the other keynoters, Eric was quite entertaining and obviously a thought leader in web UI.  I must confess that I am far out-of-the-loop on such things.  He briefly covered microformats mentioning some Yahoo group that seems to be involved in the movement.  Finally, my notes mention ObjectiveJ, 280slides.com, and Capuccino.  I suppose these are more innovative web UI platforms.  Moving on…

 

Session: IronRuby In The Real World

Michael Letterle led the talk on IronRuby in the real world; however, based on his presentation, I don’t see how it could be ready for the real world—or at least the real business world.  His demo began with a C# desktop application.  We were to pretend that the original developer left and no source code could be found (and, I guess, .NET Reflector didn’t exist either…or maybe the code was just obfuscated).  At any rate, Michael showed how you could just overlay the desktop app with an IronRuby executable to change the behavior of the desktop app and implement new business requirements.  That is pretty cool, but I just don’t see how that would be a practical approach to solving the business problem. 

Some online resources for IronRuby include Jimmy Schementi’s blog, the grand wizard himself John Lam, and Ruby itself.

 

Session: Language Oriented DDD

It seems that everywhere I turn, someone is talking about Domain Driven Design (DDD).  I guess, much like Eric Meyer’s Javascript, DDD will save the universe.  David Laribee led the only talk with DDD in the title, so I thought I’d better attend.

David kicked things off with a reference to the book The Design of Everyday Things—a book that points out examples of good and not-so-good constructions.  Later on, he launched into a discussion of various patterns:

  • Layered Architecture; eg. MVC
  • Application Services, which should not be “transactional” (as in database transaction?), vs. Domain Services, which should be small and focused
  • Model Controller; eg. that which connects a model to a queue
  • Published Language
  • Aggregate Root
  • Routing Method
  • The Repository
  • Collocated Specifications, used for entity matching requirements
  • Anti-Corruption Layer – the use of explicit interfaces

He also enumerated a few anti-patterns:

  • Anemic Model
  • Ambiguous Command – opposing the use of explicit interfaces
  • Reflective Mappers

I’m sure DDD is much more than several five dollar words, but I’ll let you know for sure when I’m done reading the book.

 

Session: A Programmers Guide to User Experience

My UI skills stink.  I know this.  However, I am desperate to eliminate my UI handicaps.  If any of you know of a good class, book, webcast, or some other medium that could help me in this effort, please let me know.  So, in my continuing quest to become a better UI guy, I attended Josh Walsh’s presentation. 

Josh is a professional UI designer-type guy for Design Interactive.  He walked through how he meets with clients to develop user interfaces that meet their needs.  For one thing, he conducts interviews: what does the project mean to you, Mr. Customer?  He defines scenarios and processes.  He builds a specification document of these scenarios and he writes out tasks and groups them accordingly.  He does a lot of hand sketching, too, on graph paper (with a Sharpie).

Next, he performs some tests with the users—without even writing code yet.  He’ll walk his documents (and sketches) in to the client and use them as they walk through different scenarios.

That’s all well and good, but can you give me any nuggets of advice that I can use immediately?

  • Use standard HTML controls…hmm.  Don’t ASP.NET and third party controls ultimately render to HTML controls, anyway?
  • Use Arial or Helvetica for body text.  These fonts are known as sans serif fonts.
  • Use Georgia for header text.  Georgia is known as a serif font.  What?  No Comic Sans?
  • Josh recommends a dark grey as a good back color.
  • Line height should be 1.5em.
  • A page should have space on either side and the middle part (with the content) should be only 40-60 characters wide.  There goes my idea of using as much real estate as possible.
  • Try blurring the page to see where your eyes focus.  This can help you determine the focal point of the page.

Books Josh would recommend: Don’t Make Me Think, Getting Real (a free ebook from 37signals.com), and, possibly, Prioritizing Web Usability

 

Session: Reverse Engineering Applications

My original plan was to attend Drew Robbins’ Modern Web Applications with .NET presentation, but Drew was sick in bed (or maybe he just stayed out a little too late the night before at the CodeMash after-hours party…hmm).  So, I went to Joe Kuemerle’s Reverse Engineering session.  The notion of reverse engineering software to see its source code is not new to me, but Joe did tackle the topic in a pretty comprehensive manner.

Popular reverse engineering tools include:

The primary way to combat disassembly of your compiled code is to obfuscate your code—Joe, as an employee of PreEmptive solutions, certainly knows this!  [Although, to his credit, Joe in no way pimped Dotfuscator.  Someone in the audience asked how you combat such reverse engineering tactics and it was only then that Joe mentioned part of what his company does.  He even went so far as to mention the Phoenix Project—a free obfuscator for .NET.  I wonder if he really meant the Babel obfuscator, built on Microsoft’s new Phoenix framework?]

Joe mentioned strong name signing of your assemblies, not to combat reverse engineering per se, but to at least offer some form of integrity or validation.  The last thing Joe mentioned was authenticode signing of .NET binaries.  I had never heard of this technique before until several months ago when someone in my company told me about problems he was having with Enterprise Library.  He was running a web app using Enterprise Library (version 4.0, I believe) on an internal web server.  The first time his app made a call to EntLib, EntLib would try to call out to Microsoft.com.  My company’s firewall rightfully blocked the call, but the process would sit for about 10 seconds until timing out and continuing with the rest of the operation.  The developer determined that this was due to the fact that EntLib was authenticode signed and was trying to do some validation of the certificate.  Don’t know how the story turned out—hopefully he found that hotfix—but this authenticode business sounds dicey…and kind of expensive.

 

Wrap Up

Well, that’s another CodeMash.  For the price and locale, you can’t really beat it.  Conferences are always a double-edged sword to me: they’re a great way to learn about new and existing technologies/methodologies and an opportunity to ask questions of the experts that normally would be tough to do otherwise.  However, they also tend to depress me more than usual.  I go away thinking that I’ve fallen so behind in knowledge and experience—I’m barely cognizant of DDD, barely practicing TDD…not to mention Agile, WPF, SilverLight 2.0, Ruby, blah, blah, blah.  Either most of these people are exaggerating their experiences, have no life and code all the time, or have great jobs that let them gain deep experience in lots of technologies and methodologies.

Well, I’m going to stop whining and do something this year to keep up.  Not sure what, but something.  Maybe I should put up one of those trite New Year’s Resolution posts.  Hmm.  Gotta think about that one. 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: Technology Blog
Posted by Brad on Saturday, January 24, 2009 11:28 PM
Permalink | Comments (0) | Post RSSRSS comment feed

CodeMash 2009: Day 1

A little late, but here’s my post-mortem on CodeMash 2009…

The Drive

This time, my drive up experience was much more pleasant.  My friend Matt Brewer—via Twitter—learned that another CodeMasher, Justin Kohnen, was looking for a traveling companion.  So, Justin and I went there and back together.  Justin also came equipped with a nice GPS device, so we were fairly well protected from making any wrong turns in the back-country of Northern Ohio.  Humorously, during the conference, they would run a slide show which included one slide picturing a dead end road and the caption, “Google Maps and CodeMash directions don’t mix” (or something to that effect)—I certainly know what they mean.

 

PreCompiler Envy

During the days leading up to the event, I couldn’t help but feel some regret for not signing up for the Precompiler event.  I definitely would have enjoyed taking in the Ruby 101 session with Jim Weirich and Joe O’Brien.  The TDD session with Leon Gersing and Phil Japikse, the Kanban 101 session with Dave Laribee, and even the Java, Groovy, and Grails 101 session with Chris Judd and Jim Shingler all sounded intriguing, as well. 

Later, I learned that at least Jim Weirich made his self-paced Ruby session available here (the file called rubykoans.zip).  I will definitely download it and walk myself through the session.

 

Key Note Speaker: Venkat Subramaniam

World famous technologist Venkat Subramaniam gave the first keynote address.  As I would expect, Venkat was quite entertaining as he pointed out the traditional software development paradigms and how they tend to fail the majority of the time.  He emphasized repeatedly asking the question, “why?”  We shouldn’t necessarily accept a given process/requirement simply because a business has been doing it for X number of years.  He recommended the book The Fifth Discipline as a tool that would help us better understand/refactor traditional (antiquated) processes at our companies.

One hilarious analogy he used in his presentation was to equate unit testing with exercising.  He described a time in his life when he began feeling chest pains.  His doctor prescribed daily exercise—when he exercised daily, the chest pains would disappear.  When he failed to exercise, the pains would reemerge.  He likened this to unit testing: to avoid future pain, we should unit test.  Unit testing may not be enjoyable, but it will likely help us avoid pain and death later on.  Maybe next year I’ll get up there and equate unit testing with nail bending.  I did write down another book recommendation, Dreaming In Code, but I don’t remember the context in which he recommended it. 

 

Session: A Lap around the Live Framework and Mesh Services

Jeff Blankenburg presented on the Microsoft Live services, including Mesh Services.  It seems you can’t click a link anymore without encountering Cloud Computing, Azure, or some other buzz word for moving your software and services to the great tubes in the sky.  As for Microsoft’s foray into this space, they have given us Azure which includes: Live Services (Live Id, Virtual Earth, Messenger, etc.), .NET Services (support for .NET applications uploaded into Azure), SQL Services, SharePoint Services, and Dynamics/CRM Services.  The Azure platform also supports Java, Ruby, Python, and PHP applications.  Another cool feature Jeff pointed out is that, should the services you host in the Azure platform require more processing power, you can very easily add more virtual servers to your virtual farm (at an additional cost, no doubt).

Several pre-existing Live Services are already available for our use, including: Map Point, Live Mesh, Contacts, and many more.  I found Live Mesh particularly cool and useful because you can use it to sync files between computers.  Microsoft even gives us 5gb of space in the cloud on which to store files (apart from Live Spaces).  Very sweet.  Unfortunately, there’s no Live Mesh desktop client for Windows XP 64bit.  Very disappointed at that.

 

Session: Re-thinking UI - WPF DataTemplates

Carey Payette ran this presentation.  Other than some lame SilverLight 1.0 work, I’ve done no XAML at all.  It has long been my intention to dive into it, but I just haven’t found the time yet.  Hopefully, some of Carey’s hints will spare me future pain.  So, here are some “notes to self”:

IValueConverter – this interface converts data to a better UI representation.  By implementing this interface, Carey was able to convert ranking data (integers) into a stars graphic (ala Amazon.com) and even able to skew the pictures she bound to a listbox giving them a nice touch.

DataTemplateSelector – this feature of WPF lets you conditionally load a template.

DataTrigger – this feature let’s you change the template.

ItemPanelTemplate/StackPanel – my notes are sketchy here, but I believe these features let you change the flow of the listbox.

As far as getting up to speed on WPF, Carey recommended the Sams Teach Yourself WPF in 24 Hours.  It looks like Carey has made her code available on her blog over a 4 Part series: Part 1, Part 2, Part 3, and Part 4.

 

Keynote Speaker: Mads Torgersen

Microsoft’s Mads Torgersen gave the lunchtime keynote address.  Yes, as we ate our sandwiches and chips, poor Mads got to speak about the future of .NET and C#.  The .NET platform is definitely trending toward the dynamic end of the spectrum, what with the Dynamic Language Runtime (DLR) library component and the introduction of the “dynamic” keyword in C#.  Personally, I’m still interesting in hearing more of the “when” and “why” in the dynamic language argument: under what circumstances should I move from my static language comfort zone to a dynamic language and why?  Fortunately, since the CLR and DLR are suppose to live nicely together, it sounds like a single application should be able to use a mix of static and dynamic language artifacts.

 

Session: Groovy/Grails for non-Java developers

Michael Kimsal, of Groovy Magazine and Web Dev Radio, gave this talk.  Groovy is a dynamic, object-oriented language similar to Java, Python, and Ruby.  It began in 2003 and includes features like a compact syntax, closures, and easy XML processing.  Closures reminded me of anonymous functions, but this is supposedly a common mistake.  Michael used the following code to depict a closure:

[1,2,3].each{print it}    [NB Michael used Groovy Console as his editor.]

Grails is a web framework built with both Java and Groovy.  Michael used Net Beans for his Grails editor.  For cool Javascript manipulation, where Ruby on Rails incorporates Prototype and Scriptaculous, Grails incorporates Yahoo UI

 

Session: Managed Extensibility Framework

Microsoft’s Drew Robbins presented on the Microsoft Managed Extensibility Framework (MEF).  MEF is a framework that makes it easy to extend your applications.  MEF will actually ship with .NET 4.0.  Right now, you can download it from CodePlex.  Drew mentioned that there was a demo out there, Cash Maker, that demonstrated the use of MEF, WPF, and Parallel FX…but I can’t seem to find it anywhere.

At any rate, Drew had his own demo app where he exposed extension points and showed how available extensions could be discovered at runtime.  He used a feature called ObservableCollection to do some of this.

MEF has three important components:

Parts – manages import and export functionality

Contracts – fairly obvious, although he did demonstrate this notion of string contracts, which was pretty cool

Containers – containers can be used to explicitly add in extensions

Other important points:

No defaults – you must always specify at least one import and one export when using MEF. 

You can add parts to a container explicity or via a catalog.

Duck typing is supported.

A potential use for MEF could be with HttpModules (I’m still waiting for an example of how to unit test an HttpModule, though).

I did ask Drew to explain the overlap between MEF and the new System.Addin namespace.  Drew said that the two teams were talking, but was not aware of any merging of concepts.  His take was that MEF was actually more flexible.  I’ve not used System.Addin, but I’ve heard that it has a steep learning curve.  Drew hooked up MEF in only a few lines of code that made sense to me, so I might be predisposed to learn MEF before System.Addin.

 

Session: Modeling types with extension methods

I ended the day with Bill Wagner and his presentation on Extension Methods.  Bill is somewhat of a quiet and dry speaker—sorry, Bill—but his grasp of C# is legend.  I absolutely must get his More Effective C# book.

Bill ran through examples of bad intefaces in the BCL—bad BCL, bad!  The he wrote some really cool extension methods to make these interfaces more fluent.  He talked about how we need to be careful when we code collection classes—that we should be careful to not necessarily force a specific implementation: eg. PersonCol : List<Person>

He even talked about ways to exchange extension methods for enums and how that would make better sense.  This presentation was just fantastic—I certainly need to spend some more time reviewing the code and slides.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: Technology Blog
Posted by Brad on Saturday, January 24, 2009 1:35 PM
Permalink | Comments (4) | Post RSSRSS comment feed

Of low-tech address books and surname distributions

address_pageWarning: this post will either a) show that I’m obsessive/compulsive and must be stopped, b) prove that I’m a fool/moron and should be left to my own devices, or c) all of the above.

I’ve been reading David Allen’s Getting Things Done (GTD) with the hope of actually getting something done in 2009.  One of the core concepts of GTD is having a trusted system in which you place data on all your projects, next actions, calendar data, tickler entries, etc.  As a geek, I’d love my trusted system to be some electronic widget that can easily sync with my home and office Outlook, Google Calendars, and so on.  But should that widget be something I combine with my phone—as in a Blackberry, smart phone, iPhone, or whatever—or should it be something separate as in a Pocket PC, PDA, or the like?  Would a tablet PC or one of those tiny notebooks be a better choice?

Surprisingly, I’m finding that many tech-savvy GTDers are going to the low-tech moleskines, Hipster PDAs, and such.  For one thing, there’s no boot time with these low-tech organizers.  (Matthew Cornell has cataloged some discussion points on high-tech versus low-tech trusted systems here.)  So, for the time being, I’m going low-tech.

The wife bought me one of those Franklin-Covey planners and I began loading it into the seven-ring binder when I encountered a dilemma: the paper planner includes 17 double-sided blank address pages.  A little box in the upper right corner seems to shout, “write a letter in me!”  But what letter do I write?  If I write “A” on the first side of page 1, do I write “B” on the backside of page 1 or do I write “A” again and write “B” on the first side of page 2?  How many sides should I allocate for surname letters I perceive to be more popular, like R, S, and T?  To solve this dilemma, I thought I’d take a scientific approach to the problem: namely, google around to see if anyone has posted frequency data on surnames beginning with the various letters of the alphabet.  At this point, I would just be happy with data relegated to the United States.

Alas, as far as I can find, no one has published such information.  However, the United States Census Bureau has published surname frequency data from the 1990 Census (more info here).  This report is a sampling of around 88,000 surnames ranked by popularity and percentage frequency in the sample population.  Hmm.  How could I coalesce this information to show the percent frequency of surnames that begin with the various letters of the English alphabet?  I know, PowerShell (if you haven’t noticed, I’ve been on a bit of a PowerShell rant of late)!  Actually, the solution I came up with combined PowerShell and LogParser

I downloaded the report and found that it was persisted in a fixed width format.  Unlike Comma Separated Value (CSV) files, PowerShell doesn’t seem to deal well with fixed width data files.  MOW did some intense work here, but that looks like a lot of work, so I just borrowed this idea to convert the fixed width file to a CSV file and then process the results:

 

 

 

 

 

#from http://www.eggheadcafe.com/software/aspnet/33254303/fixed-width-column-import.aspx
$fixedWidthFile = 'C:\data_files\personal\other\dist.all.last'
$newCSVFile = $fixedWidthFile + ".csv"

if(!(test-path $newCSVFile))
{
    $pat = '^(.{15})(.{7})(.{10})(.{2})$'
    $rep = '$1,$2,$3,$4'
    (gc $fixedWidthFile) -replace $pat, $rep -replace ' ' > $newCSVFile
}

With the CSV file in hand, I could then write my LogParser query to perform my calculations.  I would have liked to use Linq for my queries and thus keep my solution purely within the domain of PowerShell, but I’m not quite sure how to use Linq in PowerShell—or if it’s even possible with version 1.0.  That’s one more research item to add to my list.

Anyway, while constructing my LogParser query, I found something interesting: the percent frequencies of the surnames in the sample don’t add up to 100%.  Rather, they add up to something like 147%.  I wasn’t expecting that.  So, I guess if I want to get an accurate percent frequency of a given surname (and then sum those percentages together for all surnames beginning with the same letter), I’d better divide the value by the true total, 147, and use those results.  Of course, I don’t want to hard-code that total value—I want my query to calculate it for me.

To do this, normally I would nest a SELECT SUM(Percent) AS TotalValue within my larger SELECT query that produces the report I’m interested in, but LogParser seemed to have a problem with this kind of nesting—my guess is that LogParser doesn’t like two or more SELECTs together that are reading from the same file.  Alright, I’ll perform two separate calls to LogParser: one to get my total percent value and the second to use this value to calculate the percentage of each letter in the sample population.  One thing I learned by doing that first query is that I can actually capture the LogParser results back into a PowerShell variable:

$query1 = "SELECT SUM(Field2) FROM " + $newCSVFile
$totalPercent = & logparser $query1 -i:CSV -headerRow:OFF -q:ON

Now, with that value in hand, I can use PowerShell and LogParser to render the report I’m looking for (notice that I’ve included a calculation for recommended Address Page allotment into my query by calculating the percentage frequency by 34—the number of blank address pages):

$query2 = "SELECT SUBSTR(Field1, 0, 1) AS SurnameLtr, `
        SUM(Field2) AS SummedFreqAmt, `
        DIV(SummedFreqAmt, " + $totalPercent + ") AS PercentOfFreqAmt, `
        ROUND(MUL(PercentOfFreqAmt, 34)) AS PagesToAllocate `
    FROM " + $newCSVFile + " GROUP BY SUBSTR(Field1, 0, 1) ORDER BY SurnameLtr"

& logparser $query2 -i:CSV -headerRow:OFF -rtp:26

And my report in the PowerShell console:

surnameDist1

And now I have a more reasoned way of allotting my blank address pages to particular letters of the alphabet without just guessing.  Of course, the page allotments total 35—I only have 34 to dole out.  And what happens if I meet someone with a last name starting in U or Z?

After I explained this work to my wife, she just said, “why don’t you keep the pages blank until you need them?  If you end up needing more, you can always buy more.”  Huh.  Never thought of that.  Guess that’s a more rational approach.  Darn it.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Sunday, January 04, 2009 9:26 PM
Permalink | Comments (2) | Post RSSRSS comment feed

Shrinking picture sizes en masse

Last year, I bought a Gold Lantern digital picture frame.  I also bought a 2gb SD card on which I dropped over 2000 pictures.  The frame worked well cycling through all the pictures—for about three months, anyway, at which point it basically blew up (the brightness of the picture dimmed to almost total blackness, the frame smelled of burnt rubber, a thin coil of smoke rose from the AC adapter, etc.).  I replaced the AC adapter with another one from the company, but the problems persisted, so I’m pretty sure it was the frame, not the adapter. 

Out of frustration, I threw away the Gold Lantern frame and bought a new Nextar digital frame.  I plugged in the frame, slipped in the 2gb SD card I used successfully in the old frame, turned on this new one and…nothing.  The thing basically just hourglassed as, I suspect, it was attempting to load the pictures.  Later, my wife tried her 1gb SD card that she uses in her digital frame at work and the Nextar frame played it with no problem.  Thinking then that maybe the frame couldn’t handle a large quantity of files, I made dramatic reductions in the number of photos on my 2gb card all to no avail until eventually I slashed the number down to 20 pictures—which the [expletive deleted] frame happily played.

One idea I had during my futile iterations of edits to my card was that maybe the frame was having a problem rendering my pictures down to its 640 x 480 pixel screen size.  Most of my pictures were taken by my 8mb point-and-shoot camera resulting in 1+ Mb, 2272x1704 JPG files.  I thought that if I could resize my photos down to approximately 640x480, I could ease some of the burden on the frame’s processor—the files themselves would be smaller in size and little-to-no work would need to be done re-rendering the photos to the smaller size of the frame.  Normally when I resize a photo, I do it by hand in some editor.  I was not about to resize over 2000 photos, so what could I do? 

PowerShell, baby!  I wrote the following script to shrink all photos in a given directory, with due credit to this post, this one, and this one:

[void][reflection.assembly]::loadwithpartialname("system.drawing")

$imageDir = "C:\data_files\personal\other\test"
$destDir = $imageDir + "\shrunk\"
$flipType = [system.drawing.rotatefliptype]'Rotate180FlipNone'

if (!(Test-Path -path $destDir))
{
    New-Item $destDir -type directory
}

gci $imageDir *.jpg | % {
    "processing " + $_.FullName + "..."

    $file = [System.Drawing.Image]::FromFile($_.FullName)

    $newFileName = [IO.Path]::GetFileNameWithoutExtension($_) + "_tn" + $_.Extension

    $file.RotateFlip($flipType)
    $file.RotateFlip($flipType)

    #I want to reduce the image width to 640, so I need to calculate the appropriate factor
    $factor = $file.Width/640

    #reduce the image size by the appropriate factor
    $thumb = $file.GetThumbnailImage($file.Width/$factor, $file.Height/$factor, $null, [intptr]::Zero)
    $thumb.Save($destDir + $newFileName)
    $thumb.Dispose()
    $file.Dispose()
}

Unfortunately, shrinking the size of my photos didn’t seem to solve my problem, but I thought I’d post this script anyway because it might be helpful in the future.  As an aside, anyone know why the Gold Lantern frame could play all my photos but this Nextar one couldn’t?  There must be some spec associated with digital frames that will tell me the limits of how many photos a frame can process, how big these photos can be in file size and pixel width/height, etc.  I didn’t do a whole lot of research in this area, but it would sure be nice to know before I buy any more frames.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Sunday, January 04, 2009 1:43 PM
Permalink | Comments (1) | Post RSSRSS comment feed

CodeMash 2009

CodeMash 2009

“At two o`clock we took the railroad; the travelling on which was very slow, its construction being indifferent, and the ground wet and marshy; and arrived at Sandusky in time to dine that evening. We put up at a comfortable little hotel on the brink of Lake Erie, lay there that night, and had no choice but to wait there next day, until a steamboat bound for Buffalo appeared. The town, which was sluggish and uninteresting enough, was something like the back of an English watering-place, out of the season.”

--Charles Dickens, describing his trip to Sandusky, Ohio, 1842

 

Yep.  I’ll be attending CodeMash this year for the second time.  The conference is cheap, covers a wide swath of technology, and gives me another opportunity to mix with the locals…er, regionals.  It’s also relatively close, although there are no direct highway routes from Cincinnati.  Last year, I found myself wandering the back country of northern Ohio for hours (in the dark) wishing I’d packed my banjo.  Hopefully this year, my travel experience will be better.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: Technology Blog
Posted by Brad on Sunday, January 04, 2009 12:50 PM
Permalink | Comments (3) | Post RSSRSS comment feed

Calculating the size of my Playlist

Over the holidays, I bought a Sansa c250 mp3 player, a) because it was cheap and b) because it contains a microSD card expansion slot, which, in theory, would allow me to expand the disk capacity indefinitely.

Before I learned how to upgrade the firmware on the player, I was relegated to using software like Windows Media Player to move MP3s onto the device—a pox on all devices that force you to use special software to move files onto them (like this dumb digital ornament I bought for my dad—sorry, Dad).  At any rate, I wanted to begin using the device and learn how to use the expansion slot later, so I built up a playlist of tons of my favorite podcasts.  Since the player’s disk was only 2gb, though, I had to be careful not to pack too many files into the playlist.  So my question, how do I know the sum total of all the files I’m trying to sync to the player?

Windows Media Player will tell you the total number of files you have in your playlist, it’ll even tell you the total number of hours and minutes your playlist represents, but as far as I can tell it won’t tell you total size of the files represented by the playlist (even though the Library tab will tell you the size of each individual file).

playlist1

Fooey on that.  PowerShell can tell me the answer.  I wrote this script to calculate the total size of the files:

$playlistName = "C:\Documents and Settings\Administrator\My Documents\My Music\My Playlists\talk.wpl"
$playlist = [xml](cat $playlistName)
$totalSize = 0

$files = $playlist.smil.getElementsByTagName("media")

foreach($file in $files)
{
    if(test-path $file.getAttribute("src"))
    {
        $totalSize += (get-item $file.getAttribute("src")).length/1Mb
    }
}

"The total size of " + [io.path]::GetFileName($playlistName) + " is: " + $totalSize + " Mb"

The script produced the following results:

playlist

So it looks like my playlist will fit nicely on my 2gb player.  Problem solved.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Sunday, January 04, 2009 12:06 PM
Permalink | Comments (1) | Post RSSRSS comment feed

A Printable Amazon Wishlist

I maintain several Amazon wishlists broken out by the particular topics in which I’m interested.  These wishlists have become the central repository for most/all things (not just books) I’m contemplating purchasing in the future—already, you can buy a great many things from Amazon or their affiliates, but their cool Universal Wishlist Widget kind of seals the deal.

But I have a problem: whenever I visit my favorite book store, my wishlists out on the tubes are useless.  I need to be able to print my lists. 

As far as I can tell, there’s no easy way to do this.  Sure, I can print each page from my browser—I can navigate to page 1, hit the print button in my browser, then navigate to page 2, rinse and repeat.  But that’s lame and time-consuming.  Plus, it would print lots of information and pictures that I don’t need—and needlessly kill my ink cartridge.  Ideally, I’d like to just be able to print a list of the books and authors on my lists.  Even better, I’d like to sort my list alphabetically by the last name of the author since that’s how book stores order their books.  So, here’s how I solved my problem:

Requirements:
Microsoft PowerShell (free)
A free Amazon Web Service account
XML, XSLT, and your favorite browser (my script uses IE)

Step 1: Construct the AWS (Amazon Web Service) url and do my service calls

I’m using PowerShell as the primary engine to do all these operations.  I could have written C# code or the like to perform these tasks, but using PowerShell seemed a little slicker.

Figuring out how to construct the web service URL would have been tough were it not for this article on pulling back an XML representation of one’s wishlist.  I also should credit this article for letting me borrow the PowerShell script they used to call the AWS service.  (Alternatively, I could have scraped my wishlist to get the data I need.  Here’s a hilarious article on someone doing just that—to quasi-subversive ends.)  Here’s my URL syntax:

$urlTemplate =  "http://webservices.amazon.com/onca/xml?Service=AWSECommerceService"
$urlTemplate += "&Version=2006-06-07"
$urlTemplate += "&AWSAccessKeyId=YourAWSIdHere"
$urlTemplate += "&Operation=ListLookup"
$urlTemplate += "&ListType=WishList"
$urlTemplate += "&ListId=YourWishlistIdHere"
$urlTemplate += "&Sort=DateAdded"
$urlTemplate += "&ResponseGroup=ItemAttributes,ListItems,ListInfo,Offers"
$urlTemplate += "&ProductPage={0}"

[Side note: I was glad to see Scott Hanselman’s post on how he highlights code in his blog posts.  This very post marks the first time I’m using Live Writer.  I guess we’ll see how this turns out.  After that, I intend to experiment with how I can use Live Writer to highlight my code.  I suspect, though, that most of these syntax highlighting plugins focus on highlighting the syntax of standard programming languages like C#.  I wonder how these tools deal with PowerShell script?]

Back to the topic at hand…notice the placeholder for the ProductPage querystring argument.  AWS will only send back a few entries per page.  So, I had to write a loop to call the service several times—once for each page—changing that ProductPage value with each call.  Also, with every iteration, I had to persist each service call result, so I created a second XML document that I used to stitch together the results of each call.

Step 2: Reformat the author names for sorting

For each book, AWS returns one or more author elements (or sometimes one or more editor elements).  The value is the full name of the individual (eg. John J. Doe).  Sometimes, the individual has a suffix like Jr., Sr., III, etc.  In order for me to be able to sort by author last name, I had to write script to parse the name and reformat it as last name, first name.  Here’s what I did:

$authors = $stitchedXml.StitchedXml.getElementsByTagName("Author")

foreach($author in $authors)
{
    $authorFullName = $author.get_InnerText().Split()
    $lnamePos = $authorFullName.length - 1
    $newAuthorName = $authorFullName[$lnamePos] + ", "
    if($authorFullName[$authorFullName.length - 1] -match "jr|sr|ii|iii")
    {
        $lnamePos--
        $newAuthorName = $authorFullName[$lnamePos] + " " + $authorFullName[$lnamePos + 1] + ", "
    }
    for($i = 0; $i -le $lnamePos - 1; $i++)
    {
        $newAuthorName += $authorFullName[$i] + " "
    }
    $author.set_InnerText($newAuthorName.Trim())
}

Clunky, yes, but it seems to get the job done.

Step 3: Use XSLT to generate my report

After reformatting all the author names in my stitched up xml file, all my script needs to do now is save the file to disk, then open it up in a browser.  When I originally created my conglomerated XML file, I assigned it a style sheet, as so:

$stitchedXml = [xml] '<?xml-stylesheet href="WishListReport.xslt" type="text/xsl"?><StitchedXml/>'

As soon as I load the XML file up in a browser, the browser will do the heavy lifting for me, using the associated stylesheet to transform the XML file into whatever…in this case, my sorted list I’m looking for.

And here are the final results:

wishlist1

Notice the two books at the top of the list with no authors: turns out these books have editors, not authors.  If I wanted to be really fancy, I probably could have wrote more sophisticated XSLT to treat editors like authors and alphabetize accordingly—I might save that for a rainy day.

Another interesting situation I encountered is that AWS returns all the entries I’ve ever made to my wishlist, even though I’ve deleted several entries over the years (clicked the Delete button in the Web UI).  There’s no “deleted” flag, but there is a QuantityReceived element that seems to serve as a deleted flag.  I had my XSLT script filter out entries where the QuantityReceived value was greater than 0.  If you’re interested in this stuff, I’ve posted both my PowerShell script and my XSLT file for your use.  Feel free to post back with suggestions for improving these operations.

Post Script: I printed my list and walked it into my favorite book store, and immediately encountered a problem…how can I move from section to section, thumbing through 6 pages of authors and books I want to purchase?  One improvement I need to make is to group my sorted list by category: fiction, non-fiction, science, philosophy, etc.  As far as I can see, the AWS service doesn’t offer such category information.  Hmm.  I wonder if I could take the ISBN number of each book (AWS does provide the ISBN) and call some other service to get the book’s category.  If I can’t do that, Amazon does provide a Comments field for each book.  I could type in a category in that field.  That would be a lot of work, but the results might be worth it.  The AWS service doesn’t appear to return this field, but I might be able to alter the call to get this field returned.  Looks like I have some more work ahead of me.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Wednesday, December 24, 2008 6:44 PM
Permalink | Comments (2) | Post RSSRSS comment feed

Builds and references in the GAC

I've been doing some MSBuild experiments lately and pondering what a build server should look like and ran into an interesting challenge:

Suppose I am trying to build an application that references some third party assembly (a pre-built assembly that is not part of the solution being built)--a good example of this might be a project that references Log4Net.  How can I ensure that my solution will build successfully and not encounter broken references to the third party assemblies that I use?

I know how to reconcile broken references on my desktop--I covered that in my Resolving Reference Problems post.  However, I shouldn't be checking in .USER files in source control, so that solution isn't relevant here.

I could hardcode a full reference path to something like C:\Program Files\log4net, but how do I know that's where the Build Masters have installed the binary?

You're probably saying, "Brad, you dummy, just add the binary to a solutions folder in your solution and reference it with a relative path!"  Well, let's just assume that my friendly neighborhood Source Control policeman won't let me check in files that are not explicitly source code--of which, I guess, a DLL is not.  What now?

What's interesting is that, so long as MSBuild can find my third party assembly in the GAC of the build server, it doesn't matter where the DLL lives in the rest of the file system: C:\Program Files\log4net, C:\Program Files\some-mysterious-sub-dir, wherever (or nowhere, as in, the Build Master deletes the binary after he installs it to the GAC).

Further, if you create such a scenario on your Dev machine and open up the project in Visual Studio 2008, you don't get the dreaded broken reference symbol (and your solution will compile).  I wonder if that's a new thing in Visual Studio 2008?  I could have sworn that Visual Studio 2005 would still show me broken  references when my hintpaths wouldn't resolve to a physical assembly even if that assembly was in the GAC.  Hmm.

Anyway, I had several JPGs to attach showing how I arrived at my conclusions, but I don't think this little factoid is worth all that extra work.  However, feel free to play with the code yourself--attached are two solutions.  One produces a signed class library and the other is a WAP that references the DLL produced by the first solution.  Build that class library, put it in the GAC, delete it from the bin directory, then see how the WAP can still build successfully.

GACRefTest.zip (332.83 kb)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Friday, November 21, 2008 5:13 PM
Permalink | Comments (9) | Post RSSRSS comment feed

Hyperlink Text in a SharePoint 2003 List

Yes, it's 2008 and MOSS 2007 has been out for some time, but some of us are still flailing along with SharePoint 2003.  One gripe I have with SharePoint 2003 (among many), is the limited range of text markup you can do in a standard List--I guess this is largely due to the text editor control in SP2003.

One thing I would really like to do is create nice hyperlink text in the bodies of my list items.  Since the text editor control contains no feature to do this, I'm forced to literally paste hyperlinks into the body of my text.  This makes my posts less than attractive, but seems to be the only way to do it...until now.

The "Hack"

So, what I'd like to do is add a new item to, say, my Announcements list that looks like this:

Hey, everybody.  Be sure to check out Scott Guthrie's new list of .NET links.  There's some cool stuff there!

Notice that "list" is an anchor to the link I'm announcing.  Instead of that nice, tidy post, I have to do something like this:

Hey, everybody.  Be sure to check out Scott Guthrie's new list (http://weblogs.asp.net/scottgu/archive/2008/11/06/nov-6th-links-asp-net-asp-net-ajax-jquery-asp-net-mvc-silverlight-and-wpf.aspx) of .NET links.  There's some cool stuff there!

Here, I have to literally paste the link into the text of my post.  That might be fine for one or two links, but if I have several links to drop into my text, the text can become quite hard to read.  Well, recently, I stumbled upon a solution to my problem.

Step 1
In the text editor, just type up the text how I'd like it to look...



Step 2
Now, copy the ScottGu link in my clipboard and replace the word "list" with the ScottGu hyperlink...



Step 3
Now, very carefully, highlight the entire URL and type your link word over it: in this case, type the word "list" over it.  Notice that "list" takes on the appearance of a hyperlink!



Step 4
Save your post.  Now, you have nice, clean text in your list item and the hyperlink is still there, too!



The only problem I've found with this approach is if you wish to make your hyperlink text a phrase instead of a single word.  For example:

Hey, everybody.  Be sure to check out Scott Guthrie's new list of .NET links.  There's some cool stuff there!

In the SharePoint text editor, as soon as you hit that space between "new" and "list", the link seems to stop; thus, only "new" would become hypertext while "list" would remain plain, ordinary text.  If you must make an entire phrase a hyperlink, I guess you could either put an underscore (_) between words instead of a space or go through the trouble of repeating Steps 1-4 for every word in the phrase.  That might drive you crazy, but at least you'd have nice text!

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Thursday, November 06, 2008 5:58 PM
Permalink | Comments (8) | Post RSSRSS comment feed

Suggestions for Microsoft, Part 1

Let's just call this Part 1 in a potentially lengthy series of frustrations suggestions aimed at Microsoft.  

To be clear, I like Microsoft: I make my living using Microsoft tools.  However, as with all things, I occasionally encounter frustrations with their tools and/or services and need a place to vent.  Well, here it is.

Suggestion: Please decouple the different tools within Visual Studio
One huge frustration for me is the apparent assumption that most/all Microsoft customers use the full stack of Microsoft tools.  I see this theme manifest itself in many different areas of software development, but for this post, I just want to focus on the tools for building, testing, and deploying .NET applications (mainly web applications).

So, here's my caveman view of the software development lifecycle (absent project management methodology jargon and concepts like iterative development):



In my diagram, I've identified different activities and where they occur: for instance, coding and authoring of unit tests take place on the developer's workstation while I expect formal builds, formal unit testing and analysis and even formal packaging operations to occur on the build server.  Finally, I've added suggested tools that are used for each activity.

Now let's talk about my frustrations: thanks to the tight coupling of the different tools within the umbrella of Visual Studio, we have to be very careful about what tools we use in development because those tools may not be available to build/test/package our code on the build server.  Unlike other shops, my company has quite a mixture of technologies in the software development stack--most important, this means no Team Foundation Server.  Note: I've observed most of these frustrations under Visual Studio 2005, but I'm not optimistic that they've been remedied under Visual Studio 2008.

My first problem is with unit testing.  When Visual Studio 2005 rolled out, my inclination was to run with MSTest.  That is, until I realized that MSTest required an instance of Visual Studio be installed on the build serverOthers have railed against MSTest in general, but my most immediate problem with it is the fact that I would have to corrupt my formal build environment with a developer tool.  It seems to me that having a development tool on the build server would be a violation of the separation of duties we try to practice at my organization, not to mention the silliness of having to buy an extra Visual Studio license just so it can sit on a build server and facilitate unit testing.  Frustration #1: MSTest cannot stand alone from the Visual Studio IDE.

So, let's scrap MSTest like Jeff Palermo did and go with one of the open source testing frameworks like NUnit (maybe, some day, Microsoft will decouple MSTest from Visual Studio).  That's great, but how do I calculate code coverage?  Visual Studio Team System will calculate code coverage but I assume that only works against tests written on the MSTest framework.  If I don't go MSTest, I guess that means I'll have to scrape together a few bucks (albeit not that much) and buy something like NCoverFrustration #2: VSTS Code Coverage only works with MSTest (this is an assumption, to be sure, so if I'm wrong here, someone please let me know--and let me know how to configure VSTS to calculate code coverage on NUnit tests).

Alright: let's assume we've moved past the unit testing and code coverage issues.  We've made all the right decisions so that our code is going through formal builds and unit tests on a nice, clean build server.  Now, how do we push out our compiled artifacts to our Production server?  I get the impression that most folks at Microsoft advocate either XCopy or Visual Studio Publish.  These tools either require the Visual Studio IDE outright or a deeper knowledge of Microsoft deployment tools than the average deployment lackey will have (remember, separation of duties means that developers won't be the individuals deploying applications to Production servers).  

Personally, I'm a fan of deploying via Windows Installer files--that is, an MSI or installation EXE.  What's more, Visual Studio includes Setup project templates that make it easy for a developer to author the script that installs his product on the Production server--after all, who better knows how an application should be installed on a server than the developer himself?  

So, on my clean build machine, I have MSBuild or, perhaps, Nant compile my source code, run my unit tests, and maybe even do some code analysis.  Once that's all done, I have MSBuild use the instructions of my Setup project to build my MSI and...er, that didn't work?  You mean to tell me that MSBuild can't build my Setup project?!  Well, that's just nice.  And what's Microsoft's suggestion: use devenv.exe.  Yes, once again, sully my formal build environment with the Visual Studio IDE.  Frustration #3: MSBuild can't build my MSI.  

So, now, I either have to scrape together more dollars for a commercial product like Wise or InstallShield or learn to grapple with Windows Installer Xml (there do appear to be some MSBuild tasks for building WiX artifacts, though).

Confound it, Microsoft!  You have great tools, but your build and deploy story is a Grimms fairy tale!  Ok.  I feel a little better (not really).  If I'm totally off track here or if you have any better suggestions, please let me know.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Brad on Sunday, October 26, 2008 9:12 PM
Permalink | Comments (19) | Post RSSRSS comment feed