0 comments suggest edit

Here in the good ole U.S. and A, soccer doesn’t yet have the huge following or celebrity status that it does overseas. On one level, this is a good thing, as it means getting tickets for a game the day before is never too big a challenge.  On the downside, the quality of the game is often lacking especially when compared to watching a team like FC Barcelona.

However that may change in the future as it is one of the largest, if not largest, sports among kids today.  So while soccer players (excuse me, footballers) in the US don’t have the celebrity status of a Basketball player, there are plenty of fans interested in knowing what it’s like to be a professional player.

My buddies Donny and Cory (past soccer teammates) figured the same thing so they came up with an idea for a show that would highlight pro soccer players in the U.S. (and probably beyond at some point).  The show would basically be a sort of Day In The Life type of format.  I’ve been hearing Donny go on and on about this show for a while now, and it’s great to see it really happening.

Check out this promo video for the show called Beyond the Pitch.  My only contribution to this was to say I thought it was a brilliant idea. Something I’d definitely watch.  This video is a short cut from a pilot they filmed with Kevin Hartman. It’s used to sell the show and may never actually air as an episode.  Keep that in mind, as the final product will probably be even more polished.

0 comments suggest edit

K. Scott Allen, famous for his OdeToCode blog signed on to be the fourth co-author. His expertise and writing ability will help to compensate for our lack of such things.

A little while ago I wrote an email to the subtext-devs mailing list mentioning that I will be cutting back my day-to-day involvement in Subtext until around spring/summer of the new year.  I will still be involved, of course, but I cannot spend as much time writing code as I have been in the past.

However, my Subtext recruiting post was quite successful and many new developers have joined in to keep Subtext humming along. Not only that, developers who have long been involved with Subtext have also picked up the slack with major contributions.  For that, I am appreciative to see things moving forward toward the best release of Subtext yet sometime in the new year.

So what exactly is keeping me so busy? 

I will be writing a Cook Book style book on ASP.NET 2.0 with my co-authors Jon Galloway and Jeff “CodingHorror” Atwood.  The three of us have long talked about writing a book together, and this opportunity from SitePoint came along at the right time.  We just signed the contract recently and already I am panicking about the various deadlines. Wink

It’s good to get the panic and self-doubts over with early (everyone will hate the book…no worse, they’ll be indifferent to the book and hate me, spitting on me at Mix 09 when I finally release the book years late for rotting their brains just reading a synposis) so I can get to the business of writing a fantastic book.

I’ve contributed a couple of sections to a book before (Windows Developer Power Tools), but that was nothing compared to co-authoring and writing a full third of a book.  I will be looking to my capable co-authors to make me look good.

So you may notice the frequency of blogging drop off for a bit, but I plan to pick it up a bit as I write the book, focusing on little pieces that relate to the book.  Wish us luck!

0 comments suggest edit

Silver Bullet: From
http://www.tejasthumpcycles.com/Parts/LeversGripsctrls/Silver_Bullet/Silver_Bullet_Shift_Brake.jpg In a recent post I talked about how good design attempts to minimize the impact of changes to a system, often through Design Patterns.

When used appropriately, Design Patterns are a great tool for building a great design, but there is an important caveat to keep in mind anytime you apply a pattern. A Design Pattern might minimize the impact of one kind of change at the expense of amplifying another type of change.

What do I mean by this? One common pattern is the Abstract Factory pattern which is often manifested in .NET code via the Provider Model pattern. The Provider Model abstracts access to an underlying resource by providing a fixed API to the resource. This does a bang up job of insulating the consumer of the provider when changing the underlying resource.

The MembershipProvider is one such implementation of the provider model pattern. The consumer of the MembershipProvider API doesn’t need to change if the SqlMembershipProvider is swapped in favor of the ActiveDirectoryMembershipProvider. This is one way that the provider pattern attempts to minimize the impact of changes. It insulates against changes to the underlying data store.

However there is a hidden tradeoff with this pattern. Suppose the API itself changes often. Then, the impact of a single API change is multiplied across every concrete implementation of the provider. In the case of the MembershipProvider, this is pretty much a non-issue because the likelihood of changing the API is very small.

But the same cannot be said of the data access layer for software such as a blog (or similar software). A common approach is to implement a BlogDataProvider to encapsulate all data access so that the blog software can make use of multiple databases. The basic line of thought is that we can simply implement a concrete provider for each database we wish to support. So we might implement a SqlBlogDataProvider, a MySqlBlogDataProvider, a FireBirdBlogDataProvider, and so on.

This sounds great in theory, but it breaks down in practice because unlike the API to the MembershipProvider, the API for a BlogDatabaseProvider is going to change quite often. Pretty much every new feature one can think of often needs a backing data store.

Everytime we add a new column to a table to support a feature, the impact of that change is multiplied by the number of providers we support. I discussed this in the past in my post entitled Where the Provider Model Falls Short.

Every Design Pattern comes with inherent tradeoffs that we must be aware of. There is no silver bullet.

The key here when looking to apply patterns is to not follow a script for applying patterns blindly. Look at what changes often (in this case the database schema) and figure out how to minimize the impact of that change. In the above scenario, one option is to simply punt the work of supporting multiple databases to someone else in a more generic fashion.

For example, using something like NHibernate or Subsonic in this situation might mean that a schema change only requires changing one bit of code. Then NHibernate or Subsonic is responsible for making sure that the code works against its list of supported databases.

One might object to these approaches because they feel these approaches cannot possibly query every database they support as efficiently as database specific SQL as one would do in a database specific provider. But I think the 80/20 rule applies here. Let the dynamic query engine get you 80% of the way, and use a provider just for the areas that need it.

So again, this is not an indictment of the provider model. The provider model is extremely useful when used appropriately. As I mentioned, the Membership Provider is a great example. But if you really need to support multiple databases AND your database schema is succeptible to a lot of churn, then another pattern may be in order.

0 comments suggest edit

This one is probably old news to many of you, but I just recently ran across it. Every time I want to add a new control to a new page, I get annoyed because I have to remember that annoying syntax for registering a control.

Let’s see…how does it go again? Do I have to add a TagName attribute? No, that’s for user controls. Hmmm, forget it, I’ll just dynamically add it! Well in the interest of reducing future angst, here are two examples of the syntax, one for a custom control and one for a user control.

<%@ Register TagPrefix="st" Namespace="Subtext.Web.Controls" 
  Assembly="Subtext.Web.Controls" %>
<%@ Register TagName="SomeControl" TagPrefix="st" 
  Src="~/Controls/SomeControl.ascx" %>

The first one registers the tag prefix st with the Subtext.Web.Controls namespace in the Subtext.Web.Controls assembly. The second one registers the tag name SomeControl with the user control SomeControl.ascx

Add this to the top of your page or user control and you can reference a control from this assembly like so:

<st:HelpToolTip id="blah" runat="server" HelpText="Blah!" />
<st:SomeControl id="foo" runat="server" />

A most helpful tooltip!

Fortunately, starting with ASP.NET 2.0, we can register a tag prefix within the Web.config file. This basically makes all the controls within that namespace and assembly available to all pages without having to add that ugly Register declaration.

<system.web>
    <pages>
      <controls>
        <add assembly="Subtext.Web.Controls"
                namespace="Subtext.Web.Controls"
                tagPrefix="st" />
        <add src="~/Controls/SomeControl.ascx"
                tagName="SomeControl"
                tagPrefix="st" />
      </controls>
    </pages>
</system.web>

Thanks to the ASP.NET 2.0 MVP Hacks book for this one.

0 comments suggest edit

Blue Skies from
Stock.xchng We’ve all been there.  Your project stakeholder stands in your doorway with a coffee mug in hand and asks for one more teeny tiny change.

Yeeeaaah. It’d be great if you could just change the display to include the user’s middle name.  That’s pretty easy, right?

No problem!  Let’s see.  I’ll just need to modify the database schema to add the column, update several stored procedures to reflect the schema change, add a new property to the User class, update the data access code to reflect the new property, and finally update the various user controls that render or take in input for this information.

That’s quite a number of changes to the codebase for one measly little change.

The goal of good software design is to minimize the impact of changes in the code.  Many of you might be having the same reaction to this that you would if I just told you the sky is blue.  Well no duh!  Even so, I think this bears repeating again and again, because this principle is violated in subtle ways, which I will discuss in a follow-on post.

This is one reason that duplicate code is considered such an odoriferous code smell.  When a snippet of code is repeated, a change to the code affects every location in which that snippet is located.

Many Design Patterns focus on minimizing the impact of changes by attempting to look at what varies in a system and encapsulate it

For example, suppose you develop a class that monitors the power level of your Universal Power Supply (UPS) device.  When a power level change occurs, several UI widgets need to be updated.

A naïve implementation might have the UPS class keep a reference to each widget that needs to be updated and directly makes a call to various methods or properties of each widget to update the widget’s state.

The downside of this approach becomes apparent when you need to add a new widget or change a widget.  You now need to update the UPS class because of changes to the UI.  The UPS class is not insulated to changes in the UI

The Observer pattern addresses this issue by changing the direction of the dependency so that the UPS class (the observed) does not have direct knowledge of the UI widgets (the observers).  The widgets all implement a comment observer interface and the UPS class only needs to know about that one interface.  Add a new widget and the code for the class does not need to be updated.  Now the UPS class is insulated from changes to the UI.

Another example of code that is not resilient to change is a class with several methods that contain a similar switch statement.  Going back to the example of the UPS class, suppose the class has several operations it must do every few seconds.  But how it implements each operation is dependent on the current power state.

A naïve implementation might have a switch statement in each method that contains a case for each possible power state.  The problem with this approach is that when we need to add a new power state or edit how an existing state behaves, we have to update multiple existing methods.  The State pattern addresses this problem by encapsulating the behavior of a state in a class.  Thus each power state would be encapsulated in a class and the UPS class would simply delegate calls to its member state instance.

So where is the downside in all this? Seems like these patterns provide a win-win situation for us.  Well in these contrived examples it sure does, but not in every situation.  When used improperly, a pattern in one scenario can actually increase the impact of change in another.  Stay tuned.

0 comments suggest edit

Subtext Logo I put up a short three question survey on the Subtext website.  If you are a subtext user or thinking about using Subtext, please take a moment and fill it out. It’ll only take a second.

For the first question, if you choose Other, please be kind and comment on this post what that other hosting provider is. Thanks!

The third question bears a bit of explanation.  If you use the web admin to enter a blog post, the Advanced Options allow you to enter a short excerpt for the blog post.  My hunch is that nobody uses it.

This excerpt is displayed when listing posts within a category.  I think we might be better served by having some means to automatically generate an excerpt OR to allow users to mark up their blog posts when using a 3rd party tool so that we can extract an excerpt.

After I get in some results to this survey, I’ll talk about that some more.  Over time I may add some more questions.  So please, if you have a moment, take the survey.

0 comments suggest edit

Telligent, the hyper-caffeinated people behind Community Server, have just released their latest online service, blogmailr.  This service allows you to post to your blog via email.

Leading up to the unveiling, the Telligenti have been a bit coy about keeping this product shrouded in secrecy.  But with a name like blogmailr, removing the last “e” isn’t quite obfuscating enough to prevent anyone from guessing. ;)

We’ve been working on a mail-to-weblog feature for Subtext, but if you can’t wait for that, you can always give blogmailr a try.  I gave it a quick try and it does indeed work with Subtext. One nice feature of the service is that they support Really Simple Discovery (RSD), popularized by Windows Live Writer, so it is easy to configure.

If you are a fanatic about clean valid semantic markup, you should consider sending your email using plain text.  All the markup gunk that Outlook puts in for rich text emails will make your validator’s head spin.  After posting this very blog post with BlogMailr, I went in and cleaned up the markup.  I’m just anal that way.

If this service takes off, beware of spammers attempting to email random blocks of *@blogmailr.com email addresses.  That would be a particularly effective SPAM attack if they were able to post to your blog via email.

Fortunately, the service generates a random email address used to post to your blog.  It also allows you to specify which email addresses it will accept as a from address.  So a spammer would have to spoof your allowed address and guess your blogmailr address.  Not easily accomplished.

One downside of this approach is it may be difficult for users to remember the generated blogmailr email address. 

Published with BlogMailr

0 comments suggest edit

Rob Conery just announced the 2.0 release of the Commerce Starter Kit. If you are planning to build a commerce site, it is well worth checking out as it is a full featured modular application built on top of ASP.NET 2.0 and Subsonic.

I know Rob and his team worked hard to get this release ready and Rob especially has poured his heart and soul into the project, building a thriving community around it in that time.  Congratulations to everyone involved!

This good news is tempered by the news that Rob’s father passed away recently.  The announcement of the CSK release includes a heartfelt dedication to his father. I wish you and your family well Rob.

0 comments suggest edit

Source:
http://www.solarviews.com/raw/earth/earthx.jpg Total world domination has always been a small goal of mine. It’s not that I have an unquenchable thirst for power, it just sounds like a challenging goal and I love challenges.

It’s why I got into software development really. I figure he who controls the computers, can control the world.

But lately, all this involvement in running a company and an open source project leaves me very little time for plotting.  I realized I need help.  I need a minion. Someone to help me carry on my work.  Another Haacker.  So my wife and I hatched a plan and the incubation process has begun.

Sometime in June, the incubation period ends and phase 2 will begin as we add another member to our domination plans.  A baby Haack.

Initially, this new Haacker will actually slow our progress in achieving world domination as we put him or her through an orientation period.  It will take some time to get up to speed on essential skills such as speech, motor coordination, and control over bowel movements - which we’ve dubbed milestone 1.

But soon enough, our progress will increase as the newest member of our plot infiltrates the school system sowing the seeds of revolution. 

Yep, good times are ahead.

code, open source 0 comments suggest edit

I have a few great openings available that I have to share with you.  These are really great positions working with really interesting and smart people all over the world. 

Some of the outstanding benefits include:

  • Work from home.
  • Work for a great project lead (me!).
  • Work with an international team of really great developers.
  • Work on a product used by thousands of people and seen by many more.
  • Work tasks are pretty much self-directed.  Nobody is looking over your shoulder.
  • Set your own schedule and work at your own pace.
  • Interesting cutting-edge ASP.NET work. 
  • Gain great experience working on a product and increase your marketable skills.

Some of the interesting projects include:

  • Building a next-gen plugin architecture.
  • Localization and Internationalization.
  • Advanced Skinning architecture.
  • General application architecture and API improvement.
  • Streamlined UI design using AJAX.
  • Advanced Bayesian statistical analysis coding.
  • Windows CardSpaces and Infocard.

For such a great opportunity, I must warn you about a few of the downsides.

  • No health care
  • No Pay

I have a gut feeling that second downside is going to be a bit of a deal breaker for a lot of people.  But did I mention you can work as many or as few hours as you wish?

As you probably figured out already, I am attempting to recruit people to contribute to the Subtext Project.  I have to cut down the number of hours I put into the project for the rest of the year and into the first couple months of the next year for a couple reasons I will mention later.  I’ll still be heavily involved, but won’t be able to contribute as much code as I have been.

Why Accept No Pay For Work?

I’ve written on this a bit before.

In truth, there are many reasons people work on open source software, and they are not all the same. Many just find it fun to work on something more interesting than the boring data-in data-out systems they build at work. Some want to have a hand in building a better mousetrap. Many enjoy participating in a community and perhaps gaining a bit of recognition among their peers.

However there is another angle I want to promote.  It can help you get a better job.  On one hand, it helps you get experience in skillsets you might not otherwise exercise at your current job.

37signals, that über hot company right now, see Open Source contributions as a great way to judge a potential candidate.

Open source is a gift to those who need to hire technical people. With open source, you can track someone’s work and contributions — good and bad — over a lengthy period of time.

That means you can judge people by their actions instead of just their words. You can make a decision based on the things that really matter:

In fact, they only hire people they know through open source. Most companies aren’t that extreme, but trust me, it’s a serious turn on to a potential employer.

Hmmm… I’m Intrigued. What Do You Need?

Great!  Glad you asked!

We have a great team as it stands, but we can always use more help in any and every area.  Everyone is welcome to contribute to anything. Even so, I would like to have a few people step up and become responsible for a few areas.  That person doesn’t necessarily have to do the work in the respective area, but just take ownership of getting people to contribute and get it down.  Basically I want to decompose Subtext into multiple smaller projects. Here are some of our needs: 

Documentation Guru:We need someone to be in charge of documentation.  This would include making sure our project website is up to date.  It can also include generating NDoc documentation and posting it on our site, etc…  In fact, it’d be nice to have our project website redesigned to be a better resource for Subtext users.

Build and Deployment Master: Right now, this has been handled by a combination of Me, Steve Harman, and Simone (Simo) Chiaretta.  Unless Simo wants this title, I think it’d be nice to have one person be responsible for maintaining our Continuous Integration and built scripts as well as our final deployments.

QA Manager and Testers: We need more people to help out with QA before we release builds, but one person to manage this process. I have someone in mind for this, but I thought I’d put it out there since we could use more help in this area.  This would include helping us increase our unit test coverage and start getting WATIR tests going.  After the last error plagued release (my fault), I want to get more serious in this area.

Developers, Developers, Developers: And of course, we need more developers!  We have several ongoing mini-projects we could use help in.  Simo is chugging away on our new plugin framework, but I know he’d appreciate some help as well as someone to start writing some initial plugins to deploy with Subtext.

I have a new skinning architecture I want to get in place, but I won’t have the time to implement it, though I can describe it to anyone who will listen in great detail.

Robb Allen is working on our new membership provider.  I’m sure he’d love to have some help finishing the integration with Subtext.

And there are many more minor tasks that we’d like to get done such as general bug fixes, feature requests, code refactorings.  I’d like to clean up some of our data access architecture to streamline it a bit. Maybe even evaluate using Subsonic.

Wrap Up

To be clear, any and all contributions are worthy and helpful.  I may be ambitious asking for volunteers to take on these specific management roles, but it’s worth a try.

However, if you have some time to contribute, but don’t want to take on a management role, don’t let this dissuade you.  For example, if you don’t have time to help manage the QA process, but can do testing for a bit here and there when we are preparing a release, please jump on in! 

If you are interested in joining in the efforts, start by subscribing to thesubtext-devs mailing list and we’ll get you going.

0 comments suggest edit

A while ago I mentioned that my company, in collaboration with Shepard Associates built two websites for a medical device company using DotNetNuke (aka DNN).

Well we just learned that the client’s websites we built won three WebAwards from the Web Marketing Association. Cool!

I will admit, I don’t know much about the association or their awards.  It just feels good to see our hard work (by our I mean everyone involved including the client and Shepard) recognized.  Especially considering the torturous work it took to coerce, fight, and bend DNN to obey our will in order to implement these sites.

0 comments suggest edit

I love Halloween because it makes for great parties. What makes a party great? Costumes! This past weekend I drove up from Los Angeles to San Jose to stay with my friend Kyle and his wife Cara. That evening we drove up to San Francisco to attend a house party in a large four story house in the hills. It was about the perfect size for the 100+ people in attendance, and they hade a few top-notch local DJs spinning.

Unfortunately, I didn’t bring my camera so I had to rely on “donated pics”. I usually am a total shutterfly. Of course, not having my camera gave me more time to enjoy the party. Click on a pic for a larger version.

Hunter S. Thompson and Noam
Chomsky Group of people outside the
house

My buddy Kyle went as Noam Chomsky, which was a hit of a costume, as simple as it was. It’s rather freaky to see a black and white 2-D face on a normal body. The face looked almost disembodied. The first pic with Hunter S. Thompson just cracks me up. What a literary powerhouse! I went as the thoroughly unimaginative “Kung-Fu guy”. The necklace I’m wearing is made up of miniature skulls of my enemies. Yes, I fight those crazy Lilliputians.

The DEA agent was probably one of my favorite costumes, just for the chill he sent down the spine of some partygoers.

Steve Irwin, the Crocodile
HunterCartman
and
Snack

As expected, someone with showed up in a Crocodile Hunter costume, though I don’t understand the red wig. We also had Cartman and his favorite snack in attendance.

Inside the
party The
Governator

Finally, the governator showed up, but he was inappropriately dressed. I had to black out that portion of his costume. Let’s just say, it took a pretty big circle to black that portion out. Good going Guv’nor!

BeakerCount
Pimpula and
Cheerleader

The beaker costume above was one of my favorites.  She and her boyfriend both were beakers. Apparently the sight of them making out was disturbing.  That’s my friend Jason aka Count Pimpula on the right with his girl Rocel.

0 comments suggest edit

Jeff Atwood points out several problems with using blacklists (specifically Akismet) to prevent comment spam.  He makes the following point:

The core problem is relying on a single method of defense against spam.

Absolutely.  Subtext employs several measures against comment spam, mostly of a heuristic nature.  The latest release adds Akismet support as well as Visible and Invisible CAPTCHA.

The funny thing about CAPTCHA and especially Invisible CAPTCHA is the number of people who claim it won’t work and is broken. As Jeff points out, this may be true among researchers, but it is not the case in the wild.  However let me back up his post with some numbers.

For the past four days, I have not emptied my blog spam folder, just to see what gets put in there.  So far, in that time, my blog has received 1441 comments, trackbacks, etc…  Of those, 1407 have been flagged as spam by Akismet or marked as spam by me.  Of those, only one was a comment.  The rest were trackbacks/pingbacks.

So as far as I am concerned, Invisible CAPTCHA is working well so far.  And it has the benefit of being usable, assuming you can do simple math.

So assuming that CAPTCHA, for now, is the best approach to fighting comment spam, we need to deal with its critical weakness.

The real problem is how do we enable CAPTCHA for trackbacks?

I wrote about this problem before when I discussed my qualms about CAPTCHA.

The reason I didn’t mention CAPTCHA is that it would be ineffective for me.  Much of my spam comes in via automated means such as a trackback/pingback .  The whole point of a trackback is to allow another computer to post a comment on my site.  So telling a computer apart from a human in that situation is pointless.

I mentioned this to Atwood who pointed out that trackbacks and pingbacks are indeed automated, but they are left on behalf of a user.  This is true.  When I write a blog post, Subtext will look at all the links in my post and attempt to trackback each one for me.

Unfortunately, the trackback and pingback APIs have no facility for dealing with CAPTCHA. Unless there were a community effort to revise these specs (I would be happy to join in), CAPTCHA for trackbacks and pingbacks are not gonna happen.

Even with such a community effort, implementing CAPTCHA for trackbacks is going to be a lot of work for blog implementers.  In part, this is indicative of a usability issue with CAPTCHA based approaches.  CAPTCHA requires human intervention.  This makes integrating CAPTCHA with something like trackbacks hard work, whereas if someone comes up with a better automated filter, integrating that is easy.

So for the time being, we have two choices.

  1. Abandon Trackbacks/Pingbacks
  2. Find better ways to filter trackbacks and pingbacks.

I know many have decided to simply abandon trackbacks.  I understand this choice, but I personally am not ready to throw in the towel just yet.  Trackbacks can and do add a lot of value to discussions that occur via blogs.  So far, Akismet has allowed me to reclaim trackbacks.

What is the next step? Well I agree with Jeff:

Akismet is a fine addition to our anti-spamming toolkit. But that doesn’t mean it’s a good idea to outsource your entire anti-spam effort to a single website, either. Anti-spam security starts at home. For best results, use defense in depth and combine local anti-spam measures, such as CAPTCHA, with Akismet as a backup.

Though I think we need to start working on some better non-CAPTCHA filters to combine with Akismet.

0 comments suggest edit

Steve Harman points out another bug in the upgrade process.  I feel really terrible that this one slipped through, though as far as I can tell so far, it may be mostly cosmetic in its effect.  It apparently converts some comments to trackbacks.  While this is not desirable behavior, since we show both comments and trackbacks in the comment section, it might not have a huge negative effect.

Unfortunately, I am in San Jose right now, so I can’t update the release with a fix yet. Hopefully Steve can handle it. Smile

0 comments suggest edit

In the essay entitled Hold the Mayo, 37signals points out the obvious fact that most surveys ask users what features they want added to a product.  They rarely ask what features they want removed.

I have in the past asked users for permission to remove features, but I’ve never taken the extra step of asking users, which features would they like removed.  So here I go. 

Which feature(s) would you like to see removed from Subtext?

I think a natural response I will receive is the question, Why would you ever want to remove a feature?

Features have many hidden costs.  Even relatively simple features.  I am going to tell a short story about one such occurrence that happened in Subtext.  I won’t name names and this is not meant to call anyone out for public embarrasment or chastisement.  I have probably been more guilty of this than anyone.

Not too long ago, someone checked in a control into Subtext that displays recent comments, just as we were close to preparing a release.  I was a little miffed at the time because I was not expecting anyone to add features at the time.

However this was a pet feature and some of the devs really wanted it in the system.  Besides, it’s such a small feature, what could go wrong?  So I let it in not wanting to be a hard-ass about it.

The recent comments control is a pretty simple control in concept.  When added to the main skin template, it simply displays recent comments left on various blog posts.  Sounds simple, no?

However, as with any feature, the devil is in the details.  Several problems immediately became apparent as we tested the release, and one problem affected me in a later release.

  1. The control let you truncate comments after a certain number of characters.  However it didn’t strip HTML out, so if it truncated a comment in the middle of a tag, it would completely mess up the whole page.
  2. The control bypassed our provider model and made stored proc calls directly.
  3. The control displayed all feedback for a blog, even ones that were left via the Contact Page, thus potentially displaying private messages.
  4. Recently, I tried to append a little HTML comment after messages that had been processed by Akismet to make it easy to see that Akismet was indeed working by viewing source.  Comments aren’t being stripped by the Recent Comments control, so the site was broken in a way that I had not anticipated. It took a long time before I realized what was happening.

So for a relatively small feature, a lot of development time and effort was used up in supporting it.  I am glad we have the feature now, I really like it and plan to add it to my own blog at some point.

But the main point still stands, every feature is like an iceberg. When scoping it out in your head, you typically only think of the top part that sticks out above the water.  However, the real effort is in the part under water that supports the whole thing.

Iceberg Photo from
http://shiftingbaselines.org/blog/archives/2005_02.html

So if there is a feature in your product that provides very little bang for the support buck, consider getting rid of it.

So again, Which feature(s) would you like to see removed from Subtext?

0 comments suggest edit

Getting
Real Now that 37signals have put their book Getting Real online for free, I’ve finally gotten around to start reading it. And so far, I **love it. I think there are a lot of great lessons, reminders, ideas in here that will help me make products I work on that much better.

I have a premonition, even before writing this, that a lot of people will tell me that the book is crap because they don’t believe in functional specifications and even Joel believes in functional specifications. As the authors point out in their Caveats, disclaimers, and other preemptive strikes page, their techniques don’t apply to everyone (though probably to more people than one would think). Also, their ideas are not an all or nothing affair. Gotta have your functional specs, then by all means keep doing it. Don’t throw out the baby with the bathwater.

Open Source projects are probably in the best position to make use of their guidelines, though I am sure many more projects would be made much better by getting real. Subtext will most certainly gain from many of these approaches. My hope is to use Subtext as a testing ground for the principles in Getting Real, and then using its success to show my clients that they don’t need to be so rigid about product development. We’ll see.

As you might guess, many of my upcoming blog posts will focus on some of these topics.

0 comments suggest edit

Wallet Well if you’re the punk malcontent who found my wallet yesterday, you go on a shopping spree…at Rite Aid, Vons, and Ralphs (a convenience store and two grocery stores). 

Really, if you’re going to try and spend my hard-earned credit, at least go buy something decent like a stereo system.  There’s a Best Buy just down the street that isn’t much further away than the local Vons.

I mean who spends $103 at a Rite-Aid?!  Who!?  I really mean it. Who? I’d like to know because I want my wallet back.  And to the store clerks there, doesn’t it even slightly ring the suspicion bell in your head when someone tries to buy $103 worth of anything at Rite-Aid?  I didn’t even know you could buy that much stuff at a Rite-Aid. I figured buying out everything in the store would lighten your wallet by about $70, tops.  Maybe he bought the cash register too.

Did you even look at the guy and compare his picture to the Id, my Id, he presented?  There’s not a lot of hapas running around L.A. so I doubt he looked that much like me, assuming it was a “he”.

Anyways, yesterday on a short walk, I dropped my wallet.  A really comical mistake like you see in the cartoons. I put my wallet in my side cargo-short pocket, which unbeknownst to me, had a huge gaping hole in it.  I returned back to the area literally 10 to 15 minutes later, and it was gone.  And then the charges started showing up in my account as I frantically called to close my cards.

Anyways, that’s why I rushed out a new release of Subtext last night.  I figure follow something bad with something good.  Oh, and I bought a lottery ticket.  I know, the chances are pretty much nill. But what were the chances I’d put a wallet in a pocket with no bottom?  This is a chance for the world to get back to even terms with me. Wink

0 comments suggest edit

As I mentioned in my last post, someone reported a bug with deleting posts in the admin tool.  That posts also describes a quick and dirty workaround.

However, I fixed the bug and updated our current 1.9.2 release at SourceForge.  The existing URL to download the release is still valid.  The full version number for this release is 1.9.2.23.

To find out which version of Subtext you are running, just log into your admin and look in the bottom left corner.  You should see the version there.

Subtext
Version

If you downloaded Subtext 1.9.2 before I applied the update, then you will probably see version 1.9.2.19 in there.  If so, you have two options.  You can either apply the quick and dirty patch mentioned in my last post, or you can download the latest build and update the Subtext.Framework.dll file in the bin directory.

However, this latest update also includes some CSS fixes for the KeyWest skin in IE 7 designed (and fixed) by Robb Allen.  So if you are using that skin, you should download and apply this update.

0 comments suggest edit

Someone reported that they cannot delete posts in the just released Subtext 1.9.2. I am mortified that we do do not have a unit test for this function!  To our defense, we did start with 0% code coverage in unit tests and have now reached 37.9% and rising!

I have a quick fix if this problem affects you. I am also currently building a more permanent fix which I will release soon.

Run the following query in Query Analyzer (don’t forget to hit CTRL+SHIFT+M to replace the template parameters before executing this).

ALTER PROC 
    [<dbUser,varchar,dbo>].[subtext_DeletePost]
(
    @ID int
    , @BlogID int = NULL
)
AS

DELETE FROM [<dbUser,varchar,dbo>].[subtext_Links] 
WHERE PostID = @ID

DELETE FROM [<dbUser,varchar,dbo>].[subtext_EntryViewCount] 
WHERE EntryID = @ID

DELETE FROM [<dbUser,varchar,dbo>].[subtext_Referrals] 
WHERE EntryID = @ID

DELETE FROM [<dbUser,varchar,dbo>].[subtext_Feedback] 
WHERE EntryId = @ID

DELETE FROM [<dbUser,varchar,dbo>].[subtext_Content] 
WHERE [ID] = @ID

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

GRANT  EXECUTE  ON 
 [<dbUser,varchar,dbo>].[subtext_DeletePost]  
TO [public]
GO

Sorry for those that this affects. Like I said, we’ll have a bug fix out soon.