Thursday, November 06, 2008 8:16:47 PM UTC #

This isn't my building, but you get the idea. Like my building, the elevators line both sides of a short hallway.

I had a moment of sudden disorientation during an elevator ride recently.

First, let me explain the elevator setup. In our fancy downtown building, we have a bank of five (or is it six?) elevators. Our elevator bank is housed in the center of the building, lining both sides of a short hallway. As fancy as we are, we aren't fancy enough to justify glass windows or any of the other elevator luxuries. The doors open, you get in, the doors close, and your new, smaller world is the four brushed-metal elevator walls.

So, as the scene had played out hundreds (or possibly thousands) of times before, the doors opened, I got on the elevator, the doors closed. This time, however, I was distracted—more so than usual—and wasn't paying too much attention to where I was walking.

As the elevator began its descent to the ground floor, and as is quite unusual for me, I had a new thought intrude—which elevator am I on? And which way do I turn when the door opens—left or right? I had no idea.

And for a brief moment, I was suddenly disoriented—almost in a physical sense.

We'll get back to the elevator story in a moment.

Conference that shall not be named so that keyword searches shall not pick it up

Last weekend I attended the open spaces event in Austin, and while I'd like to post something saying "it was a great time, well worth it, etc," I can't. There were only two impressions I have after attending the conference.

One: I'm not ready. I'm not even currently using the tools discussed by (and at times, designed by) the other attendees, nor (with my current technology stack) am I planning to use them. Tools aren't everything; my "I'm not ready" feeling also goes for the softer topics like lean/agile/kanban, which are definitely of interest to me, but not in the sense that I have any authority to make changes outside of myself. I'm not a "Big Tymer" like Manny Fresh and Baby.

Before we move onto the second impression, let me talk for a second about my learning queue, by way of Billy Hollis.

Learning queue

I listened to a fascinating Deep Fried Bytes podcast interviewing Billy Hollis. Most interesting to me was his discussion of how no one is keeping up with the .NET framework—while Microsoft is now pushing Azure and Windows 7 and C# 4.0 and whoops, throw out the old Workflow Foundation, we're pressing the reset button on Workflow 4.0—while all this is happening, of the developers Billy Hollis interviews, only ~1 out of 10 are using generics. Generics, which were introduced in 2005, and as Billy Hollis pointed out, not a large topic to learn, are still not in regular use by 9 our of 10 developers.

Sample bias noted, even if the developers he interviews aren't representative of the developer population, this is still something to sit up and take note. The key takeaway is that almost everyone is far behind. And he illustrates this with some stark (if anecdotal) numbers.

Meanwhile, over the last several years I've focused on SharePoint. I've been learning about web parts and workflow and InfoPath and web content management publishing features and ASP.NET app pools and IIS6 and XSL and Solution packages and Feature packages and governance and taxonomies and IA and so on—I've immersed myself in the SharePoint world. It was tough to keep up, especially given the magnitude of SharePoint itself.

But, at some point in the past, I publicly and officially declared, "I'm done." No more SharePoint learning, except what I need for my job, today. And it's really freed me up, in terms of mental weight. Now that I know I no longer need to learn how to do SharePoint workflow, for example, why would I ever want to learn it—especially now as they've announced WF4.0 will be completely new? Why would I want to research SharePoint object disposal best practices, when I myself no longer need this to get things done at work?

But something else happened, something unintentional. At the moment I declared I was no longer going to learn SharePoint—at that moment I experienced a similar moment of disorientation. If I'm not going to be a SharePoint guy in the long term, what now? The elevator doors will open soon; left or right?

Back to the conference

And we're back to talking about the open spaces conference I just attended. This was the conference where I was to meet up with what would become my new community of practice. This would be the group with which I could identify.

But for whatever reason, it didn't work out that way.

I've already mentioned that at the conference, I got the strong impression that I wasn't ready to attend; that I needed to do some homework before even being able to process most of what was discussed in the sessions, much less contribute.

Surprisingly, at this conference I also had a strong moment of disorientation again. Instead of cementing my understanding of software development into a rigid cast, and allowing me to fall into something of a comfortable pattern as I expected, I felt distinctly less comfortable afterwards.

I don't think it's necessarily a bad thing to be uncomfortable. If we're following the elevator story from earlier, a dubious metaphor to begin with, but hey, here we are at the end and we can't exactly go back and invent a new and possibly worse metaphor—well, let's stick with the elevator story. At the open spaces conference last weekend I experienced a kind of career vertigo—I'm in the moment just before the elevator doors opens. It's uncomfortable, but I'm sure the sensation will pass. And when it does, my world will have grown.
Categories: .NET
Technorati:
Thursday, November 06, 2008 8:16:47 PM UTC  #     |  Comments [1]  |  Trackback
Tuesday, October 28, 2008 11:46:47 PM UTC #
I couldn't hold out.

It's okay though, because today we're strictly business. In the course of developing a bunch of SharePoint timer jobs recently, I've learned several things, most of which aren't obvious from the get-go:
  1. Storing and retrieving configuration data is a problem. Because I don't have a farm-wide configuration list (yet—the temptation grows every day), I was forced to do some ugliness in order to store and retrieve configuration data. I don't necessarily recommend my approach; instead I'll just say I'm using a custom SPPersistedObject as my Timer Job's config store and I'll further say that it works, roughly, though I'd now prefer a better way. Consider setting up a farm-wide config list, it's a relatively big time investment but is probably worth it. Other traditional config storage options (such as the web.config, or a site-local config list, or your site-local property bag) aren't accessible to Timer Jobs without some sort of…configuration's configuration…hmm, yes…without something extra pointing the way. Anyway, it's a problem.
  2. ANYTIME YOU UPDATE YOUR TIMER JOB CLASS (or custom assembly), YOU MUST BUMP ALL SHAREPOINT TIMER SERVICES ON THE FARM! I learned this lesson the hard way. If you fail to bump the timer service, it will blissfully run the old copy of your timer job class; I don't know how or why it caches your assembly, but it does, and bumping the SharePoint timer service is the only way to clear the assembly cache(?) and force it to use your minty fresh assembly.
    1. Side-note: can we report this as a bug in the Solution framework? Because this is a big enough gotcha that the Solution framework needs to include an option to -bumptimersvc …or something. Maybe a custom stsadm command (stsadm -o resetadmsvc) or maybe tack something onto the Solution deployment API and associated stsadm commands…we need something.
  3. There are differences between the context of a test harness (i.e. something like an NUnit integration test running under the NUnit test runner) and a timer job running in the Timer service. This may sound obvious, but when you're troubleshooting something that "only breaks on the test farm," this little bit of trivia is important. If you need to troubleshoot your timer job as it runs on the timer service, specifically, this can get tricky.
Also, in the course of troubleshooting just such an issue (as outlined in #3) I've created a little script to speed up the code-compile-test loop; instead of scheduling a timer job for "0100 hours" and waiting until tomorrow to see the results, why not reschedule the timer job by your own self? And that's exactly what I did.

My script below will reschedule your timer job to run 10 seconds in the future
(read: instantaneously). All you have to do to get this script working for you is customize four variables to match your own timer job, then follow the quick "usage instructions" at the bottom of the script. Below is a rundown of the four variables:
  • $siteUrl - the site collection root URL. We need this to get a reference to the SPWebApplication that holds your Timer Job.
  • $customAssemblyName - the partial name of your custom assembly. This is necessary because we're going to new up an instance of your timer job, and thus we'll need to first load the containing assembly.
  • $jobName - this need only be a rough equivalent of your job name. I'm usually lazy and say something like "*custom profile job*" or the minimum necessary to identify my job from all the rest. Messy is good; we're running a one-off script, right? Or you can go ahead and type the perfect exact case-sensitive job name in there, that's fine too.
  • $timerJobClassName - again, we need this because we're going to new up a rescheduled timer job.
Assumptions:
  • Your original schedule doesn't matter, and may be destroyed. Because that's exactly what this script does, by the way—it destroys the original schedule and sets a "10 seconds from now" schedule. Incidentally, whatever it did before, your job now runs on a daily schedule :)
  • You're only concerned about the timer job running on one web application's context. Because in truth that's all that mattered to me when I wrote this script, I didn't consider the possibility of multiple jobs.
  • You're running a single-server farm (i.e. a developer VM). My script only stops the service on the local server.
  • No one else cares if you bump the SPTimerV3 service, including any other timer jobs that may be running presently. Note in the script below, PowerShell has some cmdlets to work with Windows Services. I was totally unaware of them until I had to bump this service; neat.
While these assumptions sound scary, trust me—you won't care. On a single developer VM, you won't care about all these things. Even on a multi-server test farm, you won't care—because this script is going to save you hours of troubleshooting.

The PowerShell script is as follows:

$siteUrl = "http://dev"
$customAssemblyName = "Corp.SharePoint.Assembly"
$jobName = "*your job name*wildcards*work*"
$timerJobClassName = "Corp.SharePoint.Namespace.TimerJob"

[void][reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint")
[void][reflection.assembly]::LoadwithPartialName("Microsoft.Office.Server")
[void][reflection.assembly]::LoadwithPartialName($customAssemblyName)

function Run-Init
{
    $global:s = [Microsoft.SharePoint.SPSite]$siteUrl
    $global:webApplication = $s.WebApplication
    $global:job = $webApplication.JobDefinitions | ? { $_.Name -like $jobName }
}

function Create-NewJob
{
    Stop-Service "SPTimerV3"
    Start-Service "SPTimerV3"
    $global:job.Delete()
    $global:job = new-object $timerJobClassName -arg $webApplication
    $sched = new-object Microsoft.SharePoint.SPDailySchedule
    $now = [datetime]::now.AddSeconds(10)
    $sched.BeginHour = $now.Hour
    $sched.EndHour = $now.Hour
    $sched.BeginMinute = $now.Minute
    $sched.EndMinute = $now.Minute
    $sched.beginsecond = $now.Second
    $sched.endsecond = $now.Second
    $global:job.Schedule = $sched
    $global:job.Update()
}

#Usage: paste this script directly into a PowerShell console; the quickest
#way is to right-mouse-button click. Then when you're ready,
#run the following commands (minus the # of course):
#
#Run-Init
#Create-NewJob
#
#Anytime you update your custom assembly "Corp.SharePoint.Assembly", you will need to
#DESTROY your open PowerShell console/session and create a new one. This is the cleanest way
#to unload your old custom assembly.

That's pretty much it. Change the variables to whatever you need, open a PowerShell console, right-click, then type "Run-Init; Create-NewJob". You're done! Step 3: Profit!

Tiny footnote: if you don't care about "context", this script also allows you to execute the timer job immediately. First run the "Run-Init" function, then just type $job.Execute([guid]::Empty) in PowerShell. You can also attach to the PowerShell.exe process and do "remote debugging" of your timer job, if desired. Though if you're going to go that far, you should probably just write an NUnit test that performs the same task, and debug THAT. I'm very pro-unit testing frameworks, really, they're great. Anything that closes the code-compile-test loop, in any way, is a good thing.


Tuesday, October 28, 2008 11:46:47 PM UTC  #     |  Comments [0]  |  Trackback
Tuesday, October 28, 2008 1:52:14 AM UTC #

Yes, I'm aware it's late in the year 2008, I'm aware this stuff isn't as fresh as WPF 3D or Ruby Processing.

As I've posted earlier, I've accrued some treasured junk. Now that I have all this junk, what am I to do? Well, um…I didn't really know either.

So I started messing around.

Messing around with System.Drawing: first, infrastructure

The first thing I did was to determine the average color for a single image. I'm not sure exactly where I'm going, but I figure, hey, if you want to get a rough "picture" of what an image looks like, it's not a bad idea to look at the average color value. And we're using the RGB breakdown for color, meaning white is #FFFFFF (256,256,256), black is #000000 (0,0,0), and everything else falls in between.

Note that in my case, performance is not a big deal; I'm doing all these calculations one pixel at a time which, as you might image, is suboptimal. Mostly a straightforward operation:

public static Color Average(Image image)
{
    using (Bitmap bitmap = new Bitmap(image))
    {
        int red, green, blue;
        long redRunningSum = 0, greenRunningSum = 0, blueRunningSum = 0;
        long numPixels = bitmap.Width * bitmap.Height;

        foreach (Color pixelColor in ImageHelper.GetPixelsFor(bitmap))
        {
            redRunningSum += pixelColor.R;
            blueRunningSum += pixelColor.B;
            greenRunningSum += pixelColor.G;
        }

        red = (int)(redRunningSum / numPixels);
        green = (int)(greenRunningSum / numPixels);
        blue = (int)(blueRunningSum / numPixels);

        return Color.FromArgb(red, green, blue);
    }
}

Ok, so why do we care—it's a function, right? Well, okay, yes—but here's a PowerShell function you may also find interesting:

function Average-Images ($filenames)
{
    [void][reflection.assembly]::Loadfile("C:\a\sandbox\ImgTest\bin\Debug\ImgTest.dll")
    $i = 1
    $total = $filenames.count
    $results = @()
    foreach ($filename in $filenames)
    {
        write-host "$i - $($i*100/$total)%- $($filename)"
        $i++
        $img = [System.Drawing.Image]::FromFile($filename)
        $o = new-object PSObject
        $avg = [ImgTest.ImageHelper]::Average($img)
        add-member -inp $o -membertype "NoteProperty" -name "Filename" -value $filename
        add-member -inp $o -membertype "NoteProperty" -name "Image" -value $img
        add-member -inp $o -membertype "NoteProperty" -name "Red" -value $avg.R
        add-member -inp $o -membertype "NoteProperty" -name "Green" -value $avg.G
        add-member -inp $o -membertype "NoteProperty" -name "Blue" -value $avg.B
        $results += $o
    }
    $results
}

So. This is getting interesting. What the "Average-Images" function above does is create a custom object with some useful properties: we've got the original filename, we've got a still-breathing reference to the System.Drawing.Image object, and we're storing the "average pixel's" red, green, blue values as individual properties. The resulting objects look something like this:
image

Maybe it's still not interesting for you. That's fine, 'cause this party's* just getting started!
*despite what I've just written, this is not a party

I have one more piece of "infrastructure" to explain, before we can get cooking: I've created a PowerShell function called "Make-Html," which creates a permanent HTML file listing all the images I want to see, in the order I want to see them. As an added bonus, the function immediately launches the newly-created file in my browser. Here's the code:

$startDir = "C:\a\ps1\scrape\"
function Make-Html ($fullfilenames, $resultingFilename)
{
    $files = $fullFilenames | % { $_.split("\")[-1] }
    $tags = $files | % { "<div style=""float:left;""><img src=""$_""/></div>" }
    $html = @"
<html><head><title>$($resultingFilename)</title>
</head><body>
$($tags)
</body></html>
"@

    $html > "$($startDir)$($resultingFilename).html"
    ii "$($startDir)$($resultingFilename).html"
}

Ok, I know, we're still not doing anything.

Let's warm up

Okay, as I say to everyone, the real power of PowerShell is its object piping. PowerShell pipes objects, not text; this is something best seen, not heard, and hopefully we'll see a little something today. The objects we'll be slinging through the pipeline today are, as mentioned above, custom objects that have a Filename, an Image, and the RGB values representing the image's average (mean?) color.

So, let's count how many items we have:
image

Awesome. Let's count how many items we have that are more red than any other color:
image

Hmm, that was unexpected, 359 red-dominant images out of 503, that's proportionally huge. I'll point out that I did some extra fanciness to get this count to evaluate on one line, but usually (i.e. when I'm not posting to my blog) I'll work my way in parts, not all at once. So the same thing, split out, would be:
image

That's more realistic.

Okay, one more thing before we go. Finding out most of my pictures are red-dominant has me wondering: what about the other two? Let's work with the objects a little* to massage the answer out of them:
*a lot; ugly function that pulls out the dominant color not shown
image 

Weird.

Skipping ahead to the end

This is the pattern: we'll ask a burning question, we'll form this question as a PowerShell pipeline, and we'll see the results.

Question: can we see the images in order of "redness"?

Pipeline:

$a | sort red | % { $_.filename }

Results:

Least red:

20080707024010
200549766 

Most red:

20080524165059
439193020

Summary: okay, that makes sense. We used a naive algorithm that simply counted the red value, meaning that a pure black image or a pure blue image would have the "least redness" and a pure white image would have as much "redness" as a pure red image. Hmm, we can fix this. Onwards!



Question: Okay, so we're looking for redness. Let's call this proportional redness. Hmm, here we go:

Pipeline:

$relativelyRed = $a | select filename, @{Name="redness"; expression={$_.red / ($_.red+$_.green+$_.blue) }}
$relativelyRed | sort redness | % { $_.filename }

Results:

Least red:

883437048
20080327175323

Most red:

899605173
20080418093945
20080524164842

Summary: now that's more like it. Our earlier naive results were instructive, but this is more what I was looking for.



Question: okay, so let's stop messing with redness. Instead, let's find out what images have the most variance between the colors. We're less interested in the white-gray-gray-gray-black spectrum, and are looking for more colorful images. Let's do this:

Pipeline:

$variance = $a | select filename, @{Name="Variance"; Expression={$avg = ($_.red+$_.green+$_.blue)/3; $var = [math]::Abs($_.red-$avg) + [math]::abs($_.green-$avg)+ [math]::abs($_.blue-$avg); $var} }
make-html -fullfilenames ($variance | sort variance | % { $_.filename }) -resultingFilename "variance"

Results:

Most balanced:

783914459
281592264
741444854

Most variance:

20080831161327
20080701085401
787193910
307907780

Summary: most interesting, besides a grouping of the "grayish" and "black and white" images all together, is the smattering of images that have color, but are so perfectly balanced they're nestled right in there with the pure black-and-white images. Neat.

Final bits

This post is already too long. There's not too much else to say, besides a) stuff is awesome, and b) with the aid of either PowerShell functions or .NET library calls, you can do some complex things. If you only remember one thing from this post, try and pick up the impression I'm trying to leave. This is how I see PowerShell: it's an experimental playground where I morph a thought, an idea, slowly into something workable, and in each step along the way, I'm getting feedback and refining, and in the end, I've satisfied my curiousity. Maybe it's something as useless as basic image analysis using System.Drawing.

Incidentally, if you want to see how the professionals do this kind of thing, check out Multicolr - an color search engine indexing 10 million Flickr pictures, which makes the stuff I did above kind of pitiful looking :) When I checked last, the Multicolr site was slow, otherwise it's neat; check it out.

Categories: Awesomeness | PowerShell
Technorati:  | 
Tuesday, October 28, 2008 1:52:14 AM UTC  #     |  Comments [0]  |  Trackback
Tuesday, October 21, 2008 11:58:07 AM UTC #

HOWDY!

This is a quick announcement to let you know that my site now runs on ASP.NET MVC. A few things have been updated:

(strike that) dasBlog 2.1 running on ASP.NET MVC Preview 5

dasBlog 2.2 running on ASP.NET MVC Beta

First thing I should point out is that I'm running under IIS7 Integrated mode on shared hosting. If you're attempting this, be sure you're running on IIS 7 in Integrated mode. If you're trying to test this out on your own machine, this means you must be running Vista or Server 2008, must create a fresh web site in IIS and make sure the app pool is running on Integrated mode. Let me be clear: you can't properly test on the Cassini web server running your Visual Studio project.

ALSO: Now that ASP.NET MVC Beta adds itself to the GAC, for a while (until you host loads the dll's to its server's GAC), you'll have to make local copies of each ASP.NET MVC dll. "Copy Local" a property under each assembly Reference—set it to True for each one of them.

Ok. There are three things you have to do to get dasBlog working underneath an ASP.NET MVC app.

First, in your MVC app, set Routing to ignore your blog's folder. Mine is called "/blog". Here's what it looks like (I think I stole this from a Phil Haack blog post, so if it looks familiar, it is):

code setting routes to ignore blog dir 

Second, and this won't be an option for all of you—I removed all the System.Web.Extensions (AKA ASP.NET AJAX, AKA "Atlas") from my root MVC app. This fixed the problem I was experiencing with my ASMX-powered RSS feed, which Atlas usurps by default (thanks Ben for the tip, that did the trick).

Third, we need to do some heavy work on the dasBlog web.config. First I'll say, thanks to Paulb on the dasBlog team for providing the starter IIS7 web.config. Big ups to changeset 14700.

Instead of attempting to explain in detail any of the nasty things I've done to make the dasBlog 2.2 web.config work under the most recent MVC drop, I'll just post my web.config directly for viewing. I don't recommend what I've done for others; instead I'll say that I got my web.config minimally working underneath a small MVC-based site.

If you're reading this blog post because no one else has provided a better explanation, then maybe perusing my web.config will help.

Without further ado, I present you: web.config of my dasBlog application running underneath an ASP.NET MVC site.

KNOWN ISSUE: http://www.pseale.com/blog (without the trailing slash) bombs out with an error. http://www.pseale.com/blog/ works fine. I assume it has something to do with the blowery.web component, something that I have no desire to fix; I'll work around the problem with a Routing fix/hack. Anyway, lesson learned: BEWARE TRAILING SLASHES!

UPDATE: apparently the blowery.web compression is somehow interfering with delivery of my CSS files. I say apparently because I didn't attempt to troubleshoot this, I just disabled the HttpModule…with extreme prejudice! As much extreme prejudice as one can muster against an HttpModule, anyway.
Categories: ASP.NET MVC | Awesomeness
Technorati:  | 
Tuesday, October 21, 2008 11:58:07 AM UTC  #     |  Comments [0]  |  Trackback
Tuesday, October 14, 2008 3:31:12 AM UTC #

 huge massive collage

Recently I've been trawling THE INTERNET for retina-dissolving or otherwise awesome images, and have programmatically collected/mushed them into the nuttiness above. More to follow soon, unless I'm lazy. So, uh, probably more to follow…eventually.

EDIT: reposted with an image that is NOT 3MB. Yes, the original image was 3MB, a catastrophically large file. I'm like the guy who sends a holiday greeting PowerPoint over email that brings down the mail server for two days. Thankfully no one subscribes to my blog, otherwise that could have created "heap big bandwidth bill." I blame Windows Live Writer and Paint.NET, daring me to paste directly from one program to the other. For shame, Paint.NET. For shame.

Categories: Awesomeness
Technorati:
Tuesday, October 14, 2008 3:31:12 AM UTC  #     |  Comments [0]  |  Trackback
Tuesday, September 23, 2008 3:10:01 AM UTC #

Summary first, because I just re-read this and it's ridiculous long

If you've subscribed to my blog exclusively for the SharePoint bits, sorry; now is the time to unsubscribe.

That goes for both of you/half my subscriber base :)

I've become increasingly frustrated with SharePoint (I'll explain why in, um, detailed fashion), and instead of souring like a lemon, I'm just going to refocus. This means I'm dropping out of the SharePoint blogosphere to focus on long-term fundamentals; knowledge that won't expire when SharePoint 14 hits beta. I may jump back on for SharePoint 14, but it all depends.

UPDATED 2008-10-18: fixed grammatical and factual errors. By factual errors, I mean that time when I attributed something to Chris O'Brien's blog, when oopsies! it wasn't him at all.

Introduction

I've become increasingly frustrated with SharePoint recently (again, I know), but what's been bugging me more lately is the fact that I'm solving all the wrong technical challenges. I think I have a (deeply suppressed) aesthetic sense, that every so often, rears its ugly head. Or flares out from my neck like a humongous goiter. Goiters are a serious problem—hey!—used iodized salt, it's that easy.

I get agitated at times staring at (undocumented) CAML, or anytime I work with InfoPath, or remembering when to surround hardcoded GUIDs with curly braces (and when not), or knowing when to dispose SharePoint-created objects, or remembering which Workflow activities only work in SharePoint Designer and not Visual Studio, or working around concurrency bugs, or troubleshooting failed Solution deployments. And so on, pick your topic; these are real issues by the way.

So what's the point of this post again?

I want to send the message out there to everyone working with SharePoint, to look beyond your immediate technical challenge, and think. Think beyond your immediate issue, beyond with what you're wrestling at this particular moment, beyond your immediate (sometimes overwhelming) technical challenge with me. Are you ready? Looking at the size of this post, maybe not!

Let's DO THIS.

Are you an expert at SharePoint development?

I recently watched Dave Thomas give a talk about developing expertise. It's interesting, go watch it if you have time; he's not making it all up on the spot, he relies on some kind of research. In the talk he does something I like: he categorizes everyone (using the Dreyfus model) somewhere along the expertise scale: Novice, Advanced Beginner, Competent, Proficient, Expert. And gives definitions for all five categories, and gives helpful tips for how to work with people of varying skills. It's not all fluff, go watch it.

Bringing this back to SharePoint: after trolling the entire SharePoint blogosphere for quite a while now, I've come to the conclusion that there are no expert SharePoint developers. I'd go as far as to say that there are very few proficient SharePoint developers, and you probably know all their names (hint: look for "MVP" in title and/or multiple Bentleys in the parking lot).

The rest of us are just struggling. The "everyone's struggling" theme really sunk in recently when I browsed the source code for SharePoint-tagged CodePlex projects. All of them (save one) disposed their objects improperly. Including mine, to be fair, I'm not hating on your free, labor of love project, I'm making a point. The point isn't to hate on your baby, the point is to say that no one is doing SharePoint development properly. Look on CodePlex; you'll see what I mean.

Let that sink in. No one is doing SharePoint development properly. And hey, your team may have tackled all the object disposal issues, but maybe instead, you're ignoring large portions of the framework and (unknowingly) rewriting large portions of it. Maybe you don't bother packing things in Features and Solutions; maybe you spend too much time packing things in Features and Solutions. Maybe you're great at writing Site Definition CAML but haven't gotten the memo that putting everything in your site definition is a bad practice (or the other memo telling you that custom Site Definitions don't upgrade to v14). Maybe you're unknowingly triggering framework bugs that ruin your customers' trust in your solutions. Maybe you write unmaintainable code.

Maybe you don't understand your customer's core problem!

Maybe, in your metaphorical dwarven greed, you've delved too deep into the framework, and unknowingly stirred the framework Balrog. And you don't want to wake the framework Balrog, let me tell you.

I don't know about you, but I'm there—I'm struggling.

Takeaway: just try to be competent

Dave Thomas says in his expertise talk that advanced beginners think they're much further along than they are, and those who are proficient or experts think they're beginners. Let me tell you: as far as SharePoint development skills go, I'm an advanced beginner, bordering on competent. And I mean it—knowing that he says "beginners tend to think they're experts, and experts think they're worse than they are"—with all that said and digested, I still think I'm a beginner (advanced beginner, I'm not a total scrub :) ).

So, and this applies to those of you who are still new to the SharePoint world and/or isolated—it's okay to admit that you're not an expert. If you need an ego boost, go look at CodePlex—you'll certainly learn a great many things from others' code, but you'll also realize that hey, these people don't have it together either!

Becoming a competent SharePoint developer

What I've also begun to realize, is that the more I learn about SharePoint, the less I want to apply it to different scenarios. Where before I used to say "SharePoint Workflow is supposed to be good at solving that problem," now I say "SharePoint Workflow is painful, and for long-term maintainability I'd recommend you manually code up whatever you need, elsewhere." Whereas I used to say "InfoPath is useful for simpler scenarios," now I further limit InfoPath to "end-user tool only; don't you dare use InfoPath's code-behind." I say these with specific scenarios in mind, I have biases, your mileage may vary, all things within reason, etc, but the point I'm making stands—I'm recommending SharePoint less.

Dave Thomas says, again, that as an advanced beginner you believe that nothing works. Unfortunately, every time I encounter a new piece of the SharePoint framework, I'm an advanced beginner. I don't have the opportunity of being the CQWP guy, every day. Today I'm that guy, tomorrow I'm the InfoPath guy, day after I'm the admin, day after I'm the help desk. I'm that guy.

And hey, I've been an advanced beginner before. For example, I distinctly remember the first time I tried to do Active Directory scripting with PowerShell. It was painful. But gritting my teeth and working through the pain, I became comfortable with it. And, now that I know my way around, I'm able to do some cool (simple) things with PowerShell and Active Directory.

This is a common pattern—I've been an advanced beginner elsewhere, worked through the pain, and by the end, I was comfortable and was feeling more confident.

What I'm trying to articulate in these long rambling paragraphs, is that as I learn more about SharePoint via experience, I become comfortable with pieces of the framework and trust the framework less. As I learn more, I trust SharePoint less. Today I'm totally comfortable in telling you that InfoPath is absolutely great for simple data entry, for simple review scenarios, but nothing else*. And this isn't just InfoPath. As I work my way around the framework, I am becoming comfortable with individual pieces, and as I do so, I am trusting each piece less.

And let me set the record straight. I'm less interested in whether a particular technology is Turing-complete—whether it can theoretically solve any problem—I'm more interested in whether using that technology is a good idea in the first place. And as I learn more about SharePoint, the world of good ideas seems to shrink.
*note for InfoPath nitpickers: yes, it's useful for other things, but yes, it's also easier for me to say "good for nothing else" than rattle off 15 edge cases.

Do you want to become proficient?

I think what is bugging me most is that I don't want to be a SharePoint apologizer. Not apologist, apologizer.

Oh, sorry, that doesn't work. Sorry, yeah, there's a bug. No, yeah, you heard it was great for ECM; well, yeah, it's cheaper, but we'll have to customize a lot. Oh, yeah, that's undocumented. Oh, no, we hit the list size limit early. Yeah, no, SharePoint Designer is unmaintainable, don't build solutions with it. Oh yeah, factor in cost of upgrades on every SharePoint project.

Last week we found out "the hard way" that SharePoint can't handle 12000 documents in a single folder, no metadata, no versioning, nothing fancy. Performance whitepaper aside, 12000 documents shouldn't be a problem, I don't want to hear about it—this is a bug. And meanwhile, from the other end I'm attempting to fend off a total migration of terabytes of network file shares to SharePoint, because "this should work, right?"

I don't want to progress with SharePoint, if my energy is going to be spent tackling the wrong challenges.

Add in the cost of learning

Something that I'm maybe not emphasizing well enough is the point that in theory, all things are possible in SharePoint. And if the cost of becoming a SharePoint expert was zero, SharePoint development would be no question, worlds better than coding by hand. No contest, no question, better.

But learning isn't free.

SharePoint gold rush

Dux Sy refers to a SharePoint gold rush. It's real. It's real in part because the time cost of learning SharePoint is so high. Chris O'Brien (I can't find the entry on his blog) Shane Young states that you should be wary of hiring developers if less than 5 of their last 10 projects are SharePoint projects. It's expensive to find people with that kind of SharePoint experience. Thus, high prices, thus, gold rush.

This equation works for all Enterprise solutions; when I talk about how SharePoint is aggravating my inner engineering brain, trust me, I've worked with other Enterprise systems, and they're worse. SharePoint's a great "Enterprise" product—believe it or not, Microsoft is quite open compared to other vendors, who require all independent consultants be licensed by the vendor, or who provide no public documentation at all—all these extra hurdles artificially inflating consulting prices. Microsoft thankfully doesn't do these things (at least that I notice). So, it could be worse.

No more SharePoint on my blog

I've posted exclusively SharePoint content for a while now, and as I do so, I notice my attitude continues to trend negative. It's my doom-and-gloom engineering brain, it can't just let it go. So, instead of ranting further, I'll just, hmm, let it go. No more SharePoint 2007-related topics on my blog, even if a potential topic is brilliant (WHICH IT INEVITABLY WOULD BE!). No more SharePoint content unless I just can't hold it in.

If you've subscribed to my blog exclusively for the SharePoint bits, sorry; now is the time to unsubscribe.

I'm also officially done learning SharePoint 2007 development, permanently—no more off-hours learning, no more digging through my humongous SharePoint blogroll. When SharePoint 14 is announced, I'll evaluate it to see if they've fixed anything—to see if the situation's improved any. If so, great! Maybe SharePoint 14 will realize the potential of what some are calling "the first real application development platform from Microsoft." There are some awesome business problems that SharePoint already attempts to solve—that with just a little extra help, SharePoint could be a powerful solution. It could be dominant, even.

But if SharePoint 14 is more of the same; if they announce SharePoint Designer Designer 2009, and we're all given the "look what you can do without coding!" demos, and the BDC is still 14 pages of XML without proper tooling, and pieces of the framework are "secretly known" to not work at launch (like the PRIME API), and SharePoint still produces noncompliant HTML out of the box, and I'm still handwriting Feature manifests, and I'm still handwriting CAML, and I'm staring at a doubly-XML-encoded internal field name passed as an argument to a custom XSL function emitting HTML and all this is wrapped in a XML-encoded WebPart tag, and a new SPDataGridView is released and it adds 50 more undocumented methods and properties, and we need to rewrite all our SharePoint 2007 customizations just to make them work with v14…well, we'll see. If MSDN rolls out a SharePoint 14 resource center and it has 3 articles and 50000 useless Sandcastle-generated stub pages—gold rush or no—it may be time to bail.

So what are you going to focus on, Peter?

I have three words for you.

FUN.
DUH.
MENTALS!

Project management (not getting a PMI cert; instead, the meat of project management). Proper object-oriented design. Programming languages (plural). HTML/CSS/JavaScript (they're not going anywhere).

Personal projects!

Programming for fun—something that may even inspire me!

And hey, maybe SharePoint 14 will be a pleasure to work with; maybe I'll jump on that bandwagon…I'm the guy who owns sharepoint14.com, after all.

Categories: SharePoint
Technorati:
Tuesday, September 23, 2008 3:10:01 AM UTC  #     |  Comments [3]  |  Trackback
Monday, September 22, 2008 8:00:22 AM UTC #

Estimating is difficult to begin with, but add on

  • a new technology stack with which you're unfamiliar,
  • sometimes unreliable and often undocumented API (I can back this up with examples, just take my word for it),
  • tight integration/reliance on Active Directory, SQL Server, IIS, Exchange, Office, and Internet Explorer, all of which may fail in difficult-to-debug ways;

Given all this, how much risk are you taking on if you provide a tight estimate? If you haven't tackled three or more Visual Studio Workflow projects, for example, how do you even go about getting a ballpark estimate on your first one?

On a recent project I put a 10x difference between my lowest and highest estimate for an SAP integration task, and everyone complained to me about how "there's too much variance." Well, what should I put there, I've never tried it before!

This isn't a passive-aggressive way of trying to win a work argument via my blog. If I start doing that, dude, let me know, I don't want to be that guy.

But it is a cry for help. How are we supposed to estimate SharePoint development tasks? If you're not an experienced SharePoint team, and by "experienced" I mean experienced in building the exact same solution, using the exact same method calls on the exact same SharePoint objects—if you're not truly experienced, then how do you even attempt estimating?

When you may be blocked anywhere between zero to ten times on a task, and each blockage may take up to a full week (or more) to resolve?

When your project approach hits a dead end? A brick wall?

In traditional build-it-from-the-ground-up systems, you can estimate the complexity of your requirements and envision a rough idea of what your solution will look like, and compare the complexity of your new task with similar tasks you've done in the past. This works for traditional development, so long as you double your estimate and increase it by an order of magnitude :). The idea is, when you're building it from the ground up, estimating is "as simple as*" estimating your effort based on the complexity of the problem.
* saying estimating is "as simple as" anything is an implied joke; you may laugh now

But if your task says "write a custom field that pulls data from SAP," or if someone says "hey, let's build this web part with Silverlight!" …how do you put down an estimate? When the task, performed by an experienced expert (see above for my definition of experienced) takes an hour, and in reality the bulk of your time is spent discovering how to do the one hour task?

What do you do when your honest estimate is, "this will take between 40 and 400 hours?"

I don't have the answer

I'm just throwing this out there because no one even talks about it. So here it is. When you're on a project and someone asks you for an estimate, and you answer "4 hours to 4000 man-months", and they laugh, hey—you're not alone. I can't figure it out either.

UPDATED 2008-10-21: I made mostly grammar fixes—so if you notice some changes, no, you're not going subtly crazy, this post changed a little.

Categories: SharePoint
Technorati:
Monday, September 22, 2008 8:00:22 AM UTC  #     |  Comments [2]  |  Trackback
Monday, September 22, 2008 8:00:22 AM UTC #

A while ago I came across a paper written by Niklaus Wirth. Well, okay, I don't read "papers", but I do read programming.reddit.com, and so came across some guy who does read papers, whose story made it to the reddit front page. I'll just link to him.

So here's how this goes: I'm only going to quote a small section of the original paper, then ask, "does this sound familiar to you in any way?"

Okay, here goes. Niklaus Wirth:

By contrast, modern languages are constantly growing. Their size and complexity is simply beyond anything that might serve as a logical foundation. In fact, they elude human grasp. Manuals have reached dimensions that effectively discourage any search for enlightenment. As a consequence, programming is not learnt from rules and logical derivations, but rather by trial and error. The glory of interactivity helps.

…so, ring any bells?

Categories: SharePoint
Technorati:
Monday, September 22, 2008 8:00:22 AM UTC  #     |  Comments [1]  |  Trackback
Wednesday, September 17, 2008 8:00:30 AM UTC #

I've been fascinated with learning as much as I can about SharePoint 14, also known as "the next version of SharePoint." You can see the list of everything I can find publicly here: http://www.pseale.com/blog/SharePoint14EverythingWeKnow.aspx (nothing much has changed since I wrote that post).

One of the advantages of picking up these little tidbits (as well as reading every SharePoint blog known to mankind) is that you can make better guesses.

So, what follows are my educated guesses as to what technologies we'll be adding to the SharePoint arena, with the idea that you can brush up on some of them in preparation. Or just get depressed. I'll help speed the process, either way.

Technologies we'll see in v14

PowerShell

I've seen a hint dropped (by a MS employee) that PowerShell will be part of the next SharePoint framework. I'm guessing admin-style cmdlets, maybe better wrappers than using stsadm. I've become accustomed to using stsadm, but could definitely use some PowerShell shortcuts, especially if they could balloon the number of things PowerShell exposes. There's a lot of potential for using PowerShell as an admin interface, way more than even Exchange 2007 is realizing. And all this on top of everything PowerShell gives you today.

Anyway, learn PowerShell! It's going to be the easiest thing to learn, by far, and as I tell everyone, PowerShell is one of the few technologies that has saved me time, even including the time spent to learn it.

Windows Communication Foundation - WCF

It's inevitable that SharePoint will expose WCF services, and even if SharePoint doesn't, then we'll still eventually be writing our services in WCF (as opposed to ASMX web methods). So, learn the ABC's of WCF. Sahil Malik covers WCF for SharePoint 2007 on his blog, so maybe that's a good place for you to start.

We can hope for WCF services that replace the SharePoint built-in web services of today, though I honestly don't know how they'd improve. Maybe they'd be able to generate list-specific services? I.e. instead of a big "GetListItems" that takes the equivalent of a SQL SELECT query, they'll have something more context-specific? We can hope.

Silverlight 2.0

I'm not sure what form this will take; at minimum we'll have Silverlight Web Part templates. We can also maybe get some "all-Silverlight" site templates, where you visit the site and you don't see a single bit of HTML. As far as I'm concerned, Silverlight looks like a more difficult way to do the same thing we're already doing, but hey, that's me, I'm cranky. I'm going to skip this whole Silverlight thing until someone proves that it's easier to work with Silverlight than the equivalent solution using HTML/CSS/JavaScript; I'll re-evaluate periodically. I'm way too overwhelmed with learning to take Silverlight seriously, so don't expect me to jump on this bandwagon anytime soon.

It's also possible InfoPath will use Silverlight; think about the possibilities (but as always, don't get carried away :) ).

Also, if you're learning Silverlight, then you'll be learning WCF, gotta talk to the server from your Silverlight client somehow.

Claims-based authentication

This is a big shift and, while it may not happen for SharePoint 14, it is probably worth learning about anyway. Here's the NetworkWorld article from 2007 discussing the possibility.

.NET 3.5, IIS 7, Windows Server 2008

I'm including all these for completeness' sake; duh.

Stuff we haven't heard about yet

This section is also included for completeness. While I don't think v14 will be as big of a shift as 2003->2007 was, what do I know? Maybe the entire Dynamics platform will mash itself inside SharePoint; you can only hope (dread) the possibilities. I'm just saying here that no, I don't know what else we're going to get. I can't imagine what Access Web Access will look like. I don't know how Groove is going to work in the new version (are we going to get offline support out-of-the-box? I don't know). I don't know what the SQL-table-backed-lists will do and how they'll work. I don't know if they'll revamp the BDC. There's lots I don't know.

New slices in the SharePoint pie

Master Data Management (MDM)

This will be big. Read up on MDM. You're not going to be an MDM expert, but at least you'll know that it's not as easy as running UNION queries on disparate data sources. Hopefully that doesn't go into the marketing packet.

FAST search (Enterprise Search revamp)

This will change SharePoint's search engine, maybe not in time for SharePoint 14, but maybe so. Microsoft has proven they are able to do out-of-band improvements on their Search platform (MS Search Server), so even if this doesn't happen in time for RTM, you won't have to wait until v15.

Here's a discussion of the FAST Search acquisition on CMSWatch; you can read elsewhere (MS Enterprise Search team blog) about the acquisition, and of course you can check out FAST's product itself, as it exists in its non-integrated form.

Do you have time to learn all this?

If there's an argument to be made for specialization inside of SharePoint, combining this with the existing SharePoint 2007 architect skillset should do it. Don't even try to stay on top of all this; you can't.

Categories: SharePoint
Technorati:
Wednesday, September 17, 2008 8:00:30 AM UTC  #     |  Comments [1]  |  Trackback
Wednesday, September 10, 2008 2:45:24 AM UTC #

In my learning journey from earlier this week, I forgot to mention something:

Don't dispose SPWeb or SPSite objects you get from the "properties.Feature.Parent" property. This rule doesn't come from me—I got this information from a reliable source.

So, here's a little visual guide:

code sample with using block - NO

 

image

From my brief survey of CodePlex projects, it looks like most people were following this rule anyway.

Categories: SharePoint
Technorati:
Wednesday, September 10, 2008 2:45:24 AM UTC  #     |  Comments [3]  |  Trackback
Tuesday, September 09, 2008 11:02:20 AM UTC #

Read about Patrick Tisseghem, sad

Categories: SharePoint
Technorati:
Tuesday, September 09, 2008 11:02:20 AM UTC  #     |  Comments [0]  |  Trackback
Tuesday, September 09, 2008 10:29:40 AM UTC #

If any of you out there are looking to find reasons why SharePoint is a "challenging" developer environment, you need look no further than explore the guidance on when to dispose SPWeb and SPSite objects. I was reading Chris O'Brien's blog (which is a veritable font of knowledge on SP dev topics) and found this page, discussing his generic approach to disposing objects, and figured I'd better post this so I can just get it out. Keep in mind folks, that every single SharePoint developer in the world must deal with this issue.

To introduce the problem: Your friendly SharePoint objects SPList and SPWeb will on occasion interact with a COM component. Each pop, for each reference, they hold between 1MB and 2MB of memory. That adds up quick.

So far we're okay, because .NET has a facility for disposing these unmanaged resources (among other things)—through the IDisposable interface. This is why we tell everyone to wrap their code in using blocks—it's to make sure that the unmanaged resources (like the COM components I mention above) are properly released. If you're writing code in SharePoint and you're don't know what a using block is, go read up on it. If you're ignorant of this, it isn't the end of the world for you, but it's close.

Where were we again? Oh yes—SPLists and SPWebs hold unmanaged resources and must be disposed. The "duh" solution is of course, to wrap everything in a using block.

Unfortunately, disposing in SharePoint ain't easy

The first problem you'll run into is when you try and use SPContext.Current.Web - a static getter method. Do you dispose the SPWeb object here, or not? Note that if you dispose an object that's in use elsewhere, you'll cause new problems! Problems you didn't forsee!

This is starting to feel like whack-a-mole. Whack the unmanaged resource mole, up pops the "you whacked the wrong mole" mole.

Whack the "you whacked the wrong mole" mole

So now we know, okay, dispose SPWeb and SPSite objects, but don't dispose the SPContext.Current.Web object. Okay, two things to remember, I can handle that. Unfortunately, we're not done—we're not even close to done. We still have to deal with the "SPList.Web" reference mole, "SPSite.RootWeb" reference mole, the "enumerating through a collection" mole, the "I didn't use the unmanaged resources, this time, and thus don't really need to dispose" mole, and so on.

Disposal strategy Whack-a-mole

Disposal strategy whack-a-mole There are a bunch of resources you can read on this topic, including:

I'm still playing whack-a-mole, but I'm holding steady at the "apathetic about which mole to whack because there are too many moles to keep track of" mole. Oops, sorry, "apathetic about which mole to whack because there are too many moles of which to keep track—there, now I'm not ending my sentence with a preposition" mole.

I'm probably stretching the whack-a-mole reference too far

If I've lost you in the craziness above, let me just summarize by saying: a) object disposal in SharePoint isn't simple, b) I've given up looking for the "perfect solution".

Let's tackle my less-than-perfect solution for object disposal next.

Peter's (newer—thanks Keith) imperfect strategy

Let me first say that I wrote up "my current technique" in this post and secretly published it to my blog. Unfortunately (or fortunately) "secretly publish" doesn't work as well as it should and I got comments. My original approach, which was my firm stance as of Sunday, has changed quite a bit, it's been a full 24 hours. I've taken a little learning journey in the comments below, and in a post on the MSDN forums, where I got an authoritative answer within an hour. Nice!

So, anyway. My newer strategy is to basically copy either Chris O'Brien's or Keith Dahlby's approach, with the one extra little tidbit thrown in: if I'm unsure whether or not to dispose an SPWeb object, I will gather the minimal information necessary from this SPWeb object (e.g. RelativeUrl, Id property), and spawn a second SPWeb object, which I am safe to dispose.

Here's the full algorithm that I use to guarantee I'm safe:

  • Follow published guidance to figure out whether the method call/property getter I'm using will produce a safely-disposable SPWeb or not. This applies really to any IDisposable SharePoint object, including SPSite, PublishingWeb(?), Area(?), and objects of which I've never heard. For this example, SPWeb.
    • If definitely yes,
      • Great! Enclose in a using block.
    • If we're unsure for any reason,
      • Use the SPWeb object we're given, and somehow, with the lightest footprint possible, create ourselves a second SPWeb object, that we're guaranteed we can dispose!
      • We can use this "spWeb2" object and proceed along our merry way, disposing it with glee!
    • If definitely no,
      • Great! Don't dispose it!

Tear it up

Feel free to tear this approach up (assuming I or someone else hasn't already done so). I can take it.

Categories: SharePoint
Technorati:
Tuesday, September 09, 2008 10:29:40 AM UTC  #     |  Comments [14]  |  Trackback
Tuesday, September 09, 2008 8:00:17 AM UTC #

I recently read Matt Blodgett's post called SharePoint is the Future of Microsoft-centric Application Development, which is interesting because there's a grain of truth in what he says (not more than a grain though :) ). I want to focus today on the following quote:

[…referring to SharePoint projects] Clients are amazed when they see 80% of their app done in a week. What they don't see until later is the weeks/months of excruciating work it then takes us to crowbar the remaining 20% into an ill suited platform.

Ok. I'm only quoting Matt above because his post was the closest at hand when I need to quote someone—I hear this everywhere (and have probably said it myself several times before). It's completely correct; you want to try and solve the customer's core problem, something SharePoint's out-of-the-box features are good at doing quickly.

But, I need to elaborate. Something I'm not sure everyone is getting, is the corollary:

Lesson: You can stop after the easy part!

You can stop at 80%! This sounds obvious to me, but maybe someone out there hasn't had their eureka moment. "Now wait a minute," I hear you telling me, "we need all of this to work, not just the easy parts!" Okay, let me tell you a story.

Story time!

Earlier this year, I was asked to estimate how long it would take to build an employee vacation scheduling solution in SharePoint. As I dug into the problem, the complexity jumped out at me. We were going to pull some data from the ERP system, run a gauntlet of vacation prioritization, and even include a period of "open enrollment" wherein employees' requests would be put in a prioritized queue. And write something back to the ERP system. And supply complex reports. And so on; it was clearly not something we'd be able to solve with out-of-the-box features and would take a while.

After asking the client about cutting bits from the app, they explained that they couldn't cut features; we'd have to do it all.

So, we had a relatively complex app to build, and limited leeway. What were we to do?

In the end, the client and we agreed on not implementing this as a SharePoint solution. We parted ways, so to speak.

Aside: this is a good example showing why SharePoint is awesome for simple needs: the business users themselves built the SharePoint solution, and without any IT involvement they were already getting value out of the product.

Now, you may ask yourself, where was the "80%, then stop" in this story? I did say, after all, that they didn't pick SharePoint for the app, right? Right.

What I didn't tell you is that SharePoint was already running their vacation scheduling; it was doing the 80% of what they needed, and they came to us asking for the remaining 20%. Because SharePoint was not the most efficient way to solve this complex problem, and because there were no outside extra benefits to using SharePoint, there was no point in implementing the solution in SharePoint.

Lesson learned: wait, what was the lesson again?

Ok, here goes:

Lesson: You don't have to use SharePoint!

You can develop apps outside of SharePoint! I'm sorry I typed this up; it's too obvious. Let's take a more helpful approach, something you can use:

Lesson: Know 'why' you're choosing SharePoint as your platform.

Even if you need to run your app in SharePoint, so to speak, what specifically do you need to run in SharePoint itself? Do you need to store your data in custom lists? Do you need to run all on the same physical web server? …now are you sure about that?

I was inspired when I saw kroger.com, which is a public SharePoint site by the way, and how it handles integration—while the look-and-feel is all the same, it's clear that they're only using SharePoint for its publishing features, and "going outside" for any of their complex needs. They don't even try to get everything onto the www.kroger.com domain; if you look carefully you'll see you're being redirected to different servers. Which is fine. If simply "allowing us to run multiple domains" cuts costs by 80%…

Personal bias

I have not worked on any sort of ECM or huge portal project. If I had, I might have had a different opinion; in those cases, you may "need" to have everything run in SharePoint; maybe the data's stored in SharePoint document libraries, or maybe you need need everything to run natively on your portal. But as I mentioned above—if you don't know why you need it to run in SharePoint—then maybe you don't need it at all!

Categories: SharePoint
Technorati:
Tuesday, September 09, 2008 8:00:17 AM UTC  #     |  Comments [0]  |  Trackback
Sunday, September 07, 2008 4:44:06 AM UTC #

In a previous post, called Thinking Creatively, I asserted that in SharePoint, "we are forced to think creatively" in crafting solutions. Like when someone asks you to create a custom web part on the intranet home page to do employee search in SharePoint, you are supposed to say "hey, aren't you really asking for People Search?" And the idea is that you would then work with your customer to find the real solution to their problem, not just blindly follow directions. Maybe People Search works for them, maybe you end up writing a custom web part or configuring SharePoint's search. You solve the real problem.

Well, I was wrong.

If you remember to do so, you'll think "out of the box" in  "dynamic way" and "harness the synergies" et al, as mentioned in the scenario above. But if you forget, if you slip up, guess what?

Or what happens if your client is belligerent and wants it done their way? FYI for everyone who knows me, I'm not saying this is my client :), but have instead heard secondhand about these situations.

Bad times.

In Summary

Remember to argue with your customer! This is a fundamental aspect of any project, whether it's SharePoint or not—it just happens to sting more (a lot more) in SharePoint when you're forced to follow strict requirements.

steel folding chair - fold, apply to back of belligerent customerI'm not saying you should add a "fistfight" bullet point to your next customer meeting agenda—or maybe that's not such a bad idea after all! Treat your meeting like a boxing match: instead of doing bullet points, say "ROUND 1: do we really need to brand SharePoint?" and "ROUND 2: Can we change the way this app "runs in SharePoint"?" Set the Outlook meeting location to be "THE OCTAGON". Bring a metal folding chair and lean it next to the door, in case someone needs some extra "chair therapy" across the back. Go wild, it's your meeting.

Categories: SharePoint
Technorati:
Sunday, September 07, 2008 4:44:06 AM UTC  #     |  Comments [0]  |  Trackback
Thursday, August 21, 2008 8:00:39 AM UTC #

Announcing: Houston Techfest 2008 – 09/13/2008 at U of H

image

The second annual Houston Techfest takes place on Saturday, September 13th, at the U of H main campus. This year the Techfest has expanded to over fifty sessions. Make the time to attend!

This is a free, community-driven event that (this year anyway) features mostly Java-related or .NET-related content, with a smattering of just about everything else.

This is your only chance to attend such a wide variety of in-depth sessions, in one place, without getting on a plane and flying somewhere. If you’re bored by flashy tech demos, attend the Methodology, Security, and ALT.NET (AKA Continuous Improvement) tracks. On the other hand, if you love flashy tech demos, we’ve got those too! Lots of them! I'm also happy to say that most of the sessions cover advanced topics, so if you're an information nut like me, you'll find something new at the Techfest. And it’s not all business either; there'll be fun sessions on XNA, Deep Zoom, and Robotics Studio. Don't forget, the price is right!

Houston Techfest 2008 Topics List

A Deep Dive in the ADO.NET Entity Framework Getting started with Linq Keynote: Having fun in building Web Applications using Ruby/JRuby/Rails LINQ to SQL and Gotchas manageability, operation and monitoring of .NET applications. Using the new Features in C# 3.0 ASP.NET AJAX and the Future of Web Development Creating Services which Rock DotNetNuke Dynamic Data A look into the Ajax Frameworks A Look into Windows Workflow Foundation in .NET Framework 3.5 ASP.NET 4.0 (Ajax Templeting, MVC Dynamic Data, MVC Ajax, etc) Developing with .Net and Oracle Technology Parallel Computing with .NET : Design Patterns in .Net Getting Started with NHibernate Intro to Test-Driven Development Mocks and Stubs TDD, DI, and SoC with ASP.NET MVC Improving Application Performance using Team Suite Oracle SQL Tricks and Traps Oracle URM (Universal Records Management) and Microsoft Sharepoint Robotics Studio – Interfacing with the real world. XNA and Game Studio Building a blog with ASP.NET MVC Cross-Platform .NET: Mono and Moonlight Parallelizing Mature Algorithms using OpenMP Virtual Worlds and Virtual World Evangelism: From Here to Eternity Java FX Scene Graphs Java Solutions to Capacity Issues Concurrent Programming Topics in Java Google Web Toolkit Instrumenting your code to reduce support headaches Bandwidth and performance considerations in Ajax/RIA/polling applications Eclipse RCP Managing Software Complexity Migrating to Maven 2 Demystified The Point of Exceptions Building SOA Applications using BPEL, Open ESB, JBI, GlassFish and JavaFX Script is a compiled, declarative scripting language that runs on New in Spring 2.5 and the world of Spring OSGi, Spring Dynamic Modules, and SpringSource Application Platform The Productive Polyglot Programmer Adopting Process One Bite at a Time Behavior Driven Design: OO Priniciples & the Cure for Badly Designed Applications Principles of Object Oriented Design Scrum-tastic Development with Visual Studio Team System and Light Weight Scrum Making Your Test Lab Obsolete with Virtualization Securing and Protecting Applications and Services Static Analysis Techniques for Testing Application Security The OWASP Top 10 WS-Federation 5 Things I Learned from Lean that Could Have Saved My Last Agile project Intro to Silverlight 2.0 Silverlight Deep Zoom WPF and Silverlight Data Binding WPF and Silverlight Styles and Templating

  ..oO( Full Houston Techfest 2008 Agenda )Oo.. 

==> To attend, you must register! <==

  1. Register as a user on the Techfest site. Here is a direct link to the registration page.
  2. Without closing the browser (and without losing your session) visit the Agenda page and select each session you'd like to attend.

Links

Finally, Lando

I don't know how, or why, but what I do know that I promised Lando, and so I must deliver. So, without further ado:

Lando.
Categories: Awesomeness
Technorati:
Thursday, August 21, 2008 8:00:39 AM UTC  #     |  Comments [0]  |  Trackback
Wednesday, August 20, 2008 8:00:12 AM UTC #

First off, I'll point out I'm not an SVN expert, nor am I a CodePlex expert. I've just figured out how to do the basics, and found that the process was way too complicated. It's like you need a diagram to figure out how to make it work! What I've created below is that diagram: here's how to do a checkout of your CodePlex project from SVNBridge!

Step 0: I assume you have installed SVNBridge and a SVN client (e.g. TortoiseSVN)

If not, make that happen first.

Step 1: Figure out where your CodePlex project is hosted

CodePlex - click on the Source Code tab; memorize your project name and Server URL.

Step 2: Figure out where your SVNBridge proxy is running

image

(NOTE: do not mess with the SVNBridge "Proxy settings" unless you're the one person in the world still running behind an authenticated HTTP proxy. You're not, so don't mess with it)