Spammers Are Vermin

by Jacob 19. July 2009 09:32

Cockroaches My apologies if you’ve tried to access my personal blogs recently. I’ve been inundated by comment spammers and it has been a tremendous pain in the buttocks getting them straightened out. For a while, I was getting only a half dozen or so a day. Short comments about what an amazing blog/post it was and that they’d definitely be back and/or bookmark/subscribe.

I could manually delete them without too much inconvenience for a while. Lately, though, there’s been a staggering increase in these weasels so I’ve adopted measures a little more… drastic.

A Comment Filter BlogEngine.Net Extension

I noticed that most of these spammers shared some distinctive characteristics. Many of them put down the same email address, for example. I also noticed that there were only three or four websites generally involved. Since the spam exists for the purpose of Google pagerank manipulation, the website is probably the important thing to note.

Now, I looked for a BE.Net extension that’d do this already. Unfortunately, most of the comment filters I found were tied into Akismet or some other blog filter service. That’s more overhead than I really want (in terms of configuration, registering, and complexity etc.). All I really need is something to check the email address, website, and maybe IP address against a known blacklist I can maintain myself. That shouldn’t be difficult, right?

Adventures in Comment Filtering

On the surface, these things weren’t that hard to accomplish. BlogEngine.Net has some quirks, though, that got in my way until I figured them out. For those interested, I’m going to explain them here. If you want to skip the gory details, head down to the next section. Or if you just want the extension, download it, pop it into the App_Data/Extensions folder and season to taste.

Finding the Right Event

My first impulse was to look at the Comment object for useful events to extend. Comment.Validating looked like a good candidate so I tried that one out. Unfortunately, that event never got hit on my blog. It took me a bit to realize that this is because I don’t actually validate comments. Validating comments is a setting where a comment doesn’t show up until it is approved. Since I only do blog maintenance once a day or so, I don’t want to prevent comments from showing up for that long. Validating comments would pretty much stop discussions in their tracks and I don’t want that.

Once I remembered that comments are managed on the Page object, things went much better. The Page.AddingComment event turned out to be the one I wanted.

ExtensionParameter Fun

This is the one that held me up the longest. ExtensionParameters can be assigned types that include things like “DropDown” and “ListBox”. That seemed like exactly the kind of thing I could use for my filters. You see, each filter will be of a limited number of valid types: “Website”, “Email”, “IP Address”, or “Length” (I added Length when I noticed that all these messages are really short and I might want to account for that in my filter).

Unfortunately, these ParamType values are a complete red herring for tabular data storage. I noticed that BE.Net wasn’t actually storing my selection when I tried to add filter entries. The thing is that BE.Net stores tabular values on each parameter in the DataStore and only maintains a link to them by the order in which they appear. So my parameters in the DataStore look like this once saved:

<Parameters>
  <Name>Filter</Name>
  <Label>Filter</Label>
  <MaxLength>100</MaxLength>
  <Required>true</Required>
  <KeyField>true</KeyField>
  <Values>http://www.sonicity.com/</Values>
  <Values>http://www.unlockprivateprofiles.com/</Values>
  <Values>http://www.lastminutejoy.de/</Values>
  <Values>http://www.mooladays.com/</Values>
  <Values>http://www.dbpclan.com/</Values>
  <Values>200</Values>
  <Values>email002545@hotmail.com</Values>
  <Values>http://www.ramshyam.com/</Values>
  <ParamType>String</ParamType>
  <SelectedValue/>
</Parameters>
<Parameters>
  <Name>FilterType</Name>
  <Label>Filter Type</Label>
  <MaxLength>100</MaxLength>
  <Required>true</Required>
  <KeyField>false</KeyField>
  <Values>Website</Values>
  <Values>Website</Values>
  <Values>Website</Values>
  <Values>Website</Values>
  <Values>Website</Values>
  <Values>Length</Values>
  <Values>Email</Values>
  <Values>Website</Values>
  <ParamType>String</ParamType>
  <SelectedValue/>
</Parameters>

It looks to me like list types (DropDown, ListBox, etc.) were mainly implemented with scalar settings in mind rather than tabular settings as this needs to be. This is unfortunate, but I can’t see an easy way to alter the architecture to enable list types easily. I could create my own custom admin page for the extension (and I still may) but that’s more work than I wanted to do to get this running.

The Extension

So my comment extension has been up and working for a day or two now and things have calmed down a lot. This is a good thing. I can’t say that it is extensively tested for the simple reason that I don’t get many legitimate comments on a regular basis.

Configuration is pretty simple as long as you don’t typo the Filter Type value. Each filter is its own entry in the tabular list on top.

CommentFilterConfiguration (Click image to enlarge)

Talking Back to Spammers

When I noticed that it still looks to the user like their comment is saved (because the comment is still part of the page object, it just isn’t saved to the DataStore), I had an inspiration. Since the comment is still displayed to the person who posted it (though not to anyone else), that’s an opportunity to make sure that someone running afoul of my length requirement doesn’t end up wondering what happened. Plus, it gives me a chance to tell spammers that they’ve been noticed (yeah, that’s of dubious value and I may rethink this, but for now, it just makes me feel better). If you enlarged the image above, you’ll see that there are templated values that will be used to replace the comment content. I can be as nasty as I want and the only ones who see it will be the spammers—though you’ll probably want to take it easy on those who stumble on your length filter (if any).

Spammers Should Die

A day or so after this filter went into effect I started to get new messages. These are clever little plays for sympathy saying things like “my comment got eaten but anyway… <regular spiel here>”. Or another “my blog is getting lots of comment spam, do know any way to help?” The website links were still classic spam sites so these weren’t real users looking for help. Cheeky little locusts, aren’t they? Seriously, someone with the right skills needs to hunt these bastards down and rearrange key organs into innovative new patterns.

Tags: , , , ,

Programming | Software

An Altova Mapforce Hack

by Jacob 17. October 2007 11:40

Mapforce Anyone who has been forced to deal with EDI X12 documents knows that they are a royal pain. Each document has tons of fields—enough for any reasonable use for any reasonable organization. Having so many defined fields is actually its biggest liability. It means that every organization that uses EDI X12 pretty much has to decide what fields are significant for them. That means, for example, that an 850 document is functionally different for Nordstroms than it is for, say, Wal-Mart.

As a result, there’s a significant market for people who can map EDI documents. Most of them are service vendors pushing both document translation and document delivery with the result (happy for them) of tying you tightly into their service—and revenue stream. Jerks.

Mapforce to the Rescue

Anyway, Altova has a different model because their business is still tied to producing software that makes it easy to manipulate XML documents. They’ve grown to the point where they do a lot more than simple XML and one of those areas of growth is the ability to understand EDI documents (both X12 and EDIFACT formats). This alone was worth it for us to spring for their professional "Mission Kit".

The cool thing about their Mapforce product is that once you’ve defined your mapping, it has an option to "Generate code" with one of the selections being C#.

Mapforce Mapping

This is extremely cool and actually works

A Minor Inconvenience

Now, this is pure magic as far as I’m concerned, so I’m certainly not going to gripe about the code generated by Altova. Much. There are a few things that niggle, though.

  1. The resulting project is created as a "Console" app, so it generates an .exe file.
  2. The worker class’s Run method accepts both source and destination parameters so you’ll hit the file system if you use it "as is". Since want to use this as a library .dll, I’d prefer not to hit the file system for the destination.
  3. If you customize the Run method, you’ll overwrite it if you have to make changes and regenerate the code.

As I said, minor. Still, it means that I have to manually edit code every time I (re)generate a project and every developer knows that if it isn’t automated, it’s a potential source for errors.

Making it Better

I don’t know about you, but little things like that sometimes bug me enough that I’ll try to do something about it. In this case, I found a work-around that is useful enough that I thought I’d share it (thus this post). Two things make this work-around possible.

  1. Mapforce doesn’t clear directories when it generates code.
  2. Mapforce uses templates to generate code.

So a little creative editing and this becomes a lot less error-prone. Here’s what I ended up doing.

  • The templates are located in \{mapforce install dir}\spl\cs\MapForce\
  • Edit the "Mapforce2005.csproj" file so that it’s a Library instead of Exe:
	<OutputType>Library</OutputType>
  • If you want to get fancy, add a compile reference for a partial class you’ll be adding (the highlighted Compile line):
    <ItemGroup>
        <Compile Include="AssemblyInfo.cs"/>
        <Compile Include="[=$application.Name]Console.cs"/>
[foreach $Mapping in $application.Mappings
    foreach $AlgorithmGroup in $Mapping.AlgorithmGroups
]        <Compile Include="[=$application.Name][=$AlgorithmGroup.Name].cs"/>
         <Compile Include="[=$application.Name][=$AlgorithmGroup.Name]Partial.cs"/>
[    next
    foreach $AlgorithmGroup in $Mapping.AllLocalFunctions
]        <Compile Include="[=$AlgorithmGroup.LocalFunctionNamespace]_[=$AlgorithmGroup.Name].cs"/>
[    next
next
]    </ItemGroup>
  • Edit the "AlgorithmGroup.cs" file so that the main generated class is partial:
public partial class [=$classname] 
  • After code is generated, you’ll need to open the solution and add the partial class file it is expecting. Once you’ve done this once, however, you shouldn’t need to redo this step if/when you make changes.

Since I only really want to override the "Run" method, I’ll copy that from the main class, change the return type to XmlDocument and replace the save logic. Since saving is in a try...catch bit at the end, this is easy to replace.

At that point, you can reference the generated .dll file in whatever project is having to read EDI files. Having Mapforce target a project-specific DataSet schema makes it easy to use the returned document, though you have to work the XmlDocument into the DataSet.

public EDI850Data ReadNordstrom850File(string FileName)
{
    NordstromX850MapToEDI850Data nordstromEDIProcessor = new NordstromX850MapToEDI850Data();
    XmlDocument targetDoc = nordstromEDIProcessor.Run(FileName);

    StringReader reader = new StringReader(targetDoc.OwnerDocument.OuterXml);
    EDI850Data ds = new EDI850Data();
    ds.ReadXml(reader);

    return ds;
}
 
Trying This at Home

This is my first pass at it, so bear that in mind if you plan on doing something similar. And I’d welcome any refinement or suggestions you might have. That said, initial indications for this solution are pretty good so by all means use this as a basis for your own experimentation.

Tags: , , , , ,

Programming | Software

Dependency Injection

by Jacob 7. August 2007 15:08

Dependency Injection is a design pattern used to abstract a provider from the class using it. Specifically, the calling class assumes responsibility for managing the provider instead of the class being called. Data access is a classic example of a provider that can be injected into classes that use it. If you decide to implement the DI pattern in a data access project, the most common method of doing so is to add an interface parameter on the constructor of each class that needs data access.

A C# Example

A class that accesses data might look like this (if it were programmed by chimpanzees. Or for an illustrative example.)

Original Orders

I’m using the provider factory to pull the connection details from the application configuration file but otherwise this is pretty standard. Getting the data would require creating the object and calling GetData.

CallOrders
Dependency Injection

Dependency Injection would have me change the base class so that I pass an interface into the constructor. In this case, I can probably choose whether I inject the DbProviderFactory or DbConnection, but since DbConnection already has a handy interface, that’s definitely the best way to go:

DIOrders

The benefit to this pattern is that the class is now disconnected from the data provider. The disadvantage is that now my calling code has to handle the provider.

DICaller

Dependency Injection Dissected

Functionally speaking there’s not really that big a difference between the original version and the one with the dependency injected. In all, the actual complexity of the code is a wash in my opinion.

Either way, I’m better off with an abstracted data provider (as handled in the factory classes). Either way, I need to make sure the project is consistent in how it creates the access providers (I’d probably create an internal utility class with a static method to pull down the connection, so don’t let the extra lines above distract you).

That said, dependency injection doesn’t scale well and creates opportunity for future versioning pain should you find you later need to add providers. What if, for example, I need two data connections instead of one for my class because some of my data is being pulled from a second data source. I would then need two parameters on my constructor. I could move the injection point to the methods instead of the constructor so that only the affected methods have the signature change (a not-uncommon DI method if only a small number of methods have the dependency), but generally that just pushes my problem down to where it affects more code.

And yeah, providers shouldn’t change often and there shouldn’t be more than one or two so this isn’t a huge concern. I just hate breaking encapsulation and even a small hit to your orthogonality can be significant if you find you ever have to change it.

Dependency Injection’s Natural Domain

The real reason that DI has become so popular lately, however, has nothing to do with orthogonality, encapsulation, or other "purely" architectural concerns. The real reason that so many developers are using DI is to facilitate Unit Testing using mock objects. Talk around it all you want to, but this is the factor that actually convinces bright developers to prefer DI over simpler implementations.

I do wish that people would admit that DI doesn’t have compelling applicability outside of Unit Testing, however. I’m reading articles and discussions lately that seem to take the superiority of DI for granted. And I’ve read mock object examples that seem a little bit condescending about dependency injection--as if your projects should already incorporate this technique. I wonder if this is a defensive reaction because the authors of the examples don’t want to have to justify making you fundamentally alter your coding habits and re-write all of your existing code just so that you can use their pet objects.

Superior .Net Mocking

All of this becomes particularly exasperating in the dead silence regarding TypeMock. I blogged about this product as soon as I found it because their claims are simply stunning. TypeMock claims to allow you to mock objects used by your classes without having to expose those internal objects at all.

I have completed a project using TypeMock for my Unit Testing and I can verify that they are correct.

No interface creation or injection required. No dependency injection at all. No change to how I want to create my objects. No orthogonality issues hidden like a time-bomb in my code, however tiny. TypeMock uses reflection to intercept pesky calls and has robust assert, parameter, return object and verify options. The ability to select which calls to mock and which to let the original objects handle is an outstanding unlooked-for bonus.

Best of all, TypeMock is free to use. Yeah, it’s easier to use their professional and/or enterprise products because there are improved ease-of-programming objects in those editions, but their community edition has all of the actual functionality and none of the cost.

What Gives?

So tell me; what gives? Why the resounding silence around this tool? If it works, why isn’t every .Net developer on the planet talking about it. If it doesn’t why aren’t they reviling TypeMock for taunting us so cruelly? I’m serious. Why isn’t this sucker taking the Unit Testing space by storm? And why am I still hearing about the virtues of a pattern whose sole perceptible benefit is allowing mock objects in Unit Tests?

Tags: , , , , , ,

Programming | Software

TypeMock Fanboi Update

by Jacob 21. June 2007 15:18

Fanboi Phil left a comment to yesterday's post saying that he'd heard good things about TypeMock, but that it wasn't free, so it's not useful in OSS situations. That got me wondering because I could have sworn that the Community Edition of TypeMock was free. Going over their website, it looks like that edition should be free, but they never come out and actually say so. The trouble is that there's a "30 day evaluation license" on the download page but that's not at all the same as being free.

A little digging reveals that the download of the TypeMock framework includes a demo mode that allows you to use all the Enterprise features, but for a single test only. Their price page doesn't list the Community edition at all. I just couldn't find whether the Community edition is truly, concretely free just from poking around. That information just isn't present. Since I was curious and all, I shipped them an email and asked outright, bringing up the OSS angle specifically.

In a pleasant surprise, I received an answer in just a couple of minutes. Here's the relevant portion:

The Community Edition is free to use! And you can use them on Open Source projects.

Good to know. I wish it were clearly stated on the website, but at least the impression I got wasn't misleading.

On a Related Note

The TypeMock front page has a link to Eli Lopian's blog (he's their CTO). I bring this up because one recent post demonstrates using TypeMock to test a form close event that throws up a confirm dialog. Now, I don't know about you, but a MessageBox.Show() call is practically untestable as far as I can see. Wrap it in an interface? Ugh. You'd want a broader UI communication interface and I cringe as I consider implementing such a thing.

Using TypeMock makes this relatively painless, however. His examples use objects only available in the Professional edition of TypeMock (the recorder objects), but the technique he uses is applicable in the community edition as well—just a little more complex. Nothing like what you'd have to do with dependency injection, though. The key is that using TypeMock, you can override any method of any type during your test. That's some mighty reflection Fu there.

Technorati tags: , , ,

Tags: , , ,

Programming | Software

On Being a Microsoft Shill

by Jacob 19. June 2007 11:22

When I go over the tools that I use for software development, it's not actually true (as a friend recently accused) that "if it isn't produced by Microsoft, Jacob won't use it." Still, while I don't hesitate to use tools not produced by Microsoft, there's no denying that the majority of what I use day-to-day has its origins in Redmond, Washington. The question Microsoft's detractors need to be asking themselves is why that might be the case.

It's Not the Hot and Cold Running Babes

Because here's the cold, hard truth: there's not a thing in it for me to continue using Microsoft products, let alone defending my use of those products, besides the utility of the products themselves. Indeed, as one with geek pretensions, there's a good deal of downside for me in admitting that I use Microsoft tools and like it. Like admitting I read romance novels among the English Lit crowd, it tends to produce one of those uncomfortable silences.

Microsoft isn't cool. It's strictly squaresville. Entire geek cultures have sprung up around hatred of Microsoft and in some circles mentioning the name isn't dissimilar to mentioning a certain Scottish play in the presence of Blackadder's thespians.

I suppose that I could cave to peer pressure and use the tools all the cool kids are talking about, but I've never cared that much about the opinion of others and I don't see the point in starting now. Particularly when Microsoft's software makes it so darned easy to do my job.

Bottom Line

Like any geek, I consider myself a rational person. I go out of my way to hear counter arguments to my current theories and I always try out new technologies when given a chance. My problem is the lack of seriousness in those taking Microsoft products on. I get more people trying to get me to feel stupid for using Microsoft than trying to convince me that something else is better.

Since I have a pretty high tolerance for feeling stupid, I'll keep using Microsoft products until someone bothers producing actual reasons for alternatives. Anybody taking on that job ought to at least attempt to understand why someone would use Microsoft in the first place and use that as a starting point. Appeals to authority, ad hominem attacks, reductio ad absurdum and other rhetorical tricks aren't going to play well in that endeavor.

Technorati tags: , , ,

Tags: , , ,

Programming | Software

Is Microsoft Evil?

by Jacob 4. June 2007 16:10

Face of Evil I've been considering this post for a while now, but have been afraid to actually write it. So here's the thing: I've noticed that most of those who talk about how evil Microsoft is don't bother supporting that assertion. They tend to assume the rightness of their position and hence the wrongness of whatever it is that Microsoft has done. Microsoft stifles technology! Microsoft is a monopoly! Microsoft engages in unfair business practices!

Do they really?

No Consumers Were Harmed in Making This Software

There's a couple of problems with the whole monopoly thing. For one, at least in the U.S., being or having a monopoly isn't itself illegal—using the position of a monopoly to harm consumers is the illegal part. Now, some courts, and popular opinion, assumes that the fact of a monopoly is, itself, harmful to consumers, but that has never been proven to my satisfaction. Indeed, many of those who testified against Microsoft in past years rested on this assumption by equating harm to them as harm to the consumer.

Here's a tip: the fact that a company cannot compete and goes out of business isn't really evidence that consumers were, in any way, harmed. Let's make this concrete with an example. The fact that Microsoft started giving Internet Explorer away for free and that doing so tanked their competitors in the browser market doesn't actually harm consumers. After all, consumers are now getting something for free that companies wanted to charge money for. If Microsoft began charging money for browsers after their competitors tanked, well, that'd be a different story. At that point, you'd have to ask if the new price for browsers was higher than it would have been with competitors still in business. The thing is, Microsoft didn't do so. Indeed, if those whining about Microsoft got their way, we'd be charged money for browsers today and that, in my opinion, is far more harmful to the consumer than Microsoft's decision that something should be free.

But here's the thing: Microsoft isn't even a monopoly. Seriously. Let's take the primary definition of a monopoly from reference.com.

mo·nop·o·ly      /məˈnɒpəli/ [muh-nop-uh-lee]
–noun, plural -lies.

1. exclusive control of a commodity or service in a particular market, or a control that makes possible the manipulation of prices.

See that. The key to having a monopoly is having exclusive control or enough control that makes possible the manipulation of prices. It's obvious that Microsoft doesn't have exclusive control, but the fact of the matter is that Microsoft doesn't have the power to manipulate prices, either. While Microsoft can determine the prices they charge for their own products, doing so does nothing to control the prices of anybody else's product.

That's because software is inherently uncontrollable.

The reason for this is because you cannot control the supply of software in any compulsory way. Unlike any other product, software can be reproduced at will by anybody who owns the rights to the program (and by many who don't). You could gain a monopoly over practically any other product if you can somehow control the supply of a key component. Software doesn't have a key component crucial for its replication. If every owner of Microsoft Vista wanted to migrate to OS X tomorrow, there's nothing that Microsoft could do to hamper Apple from creating as many copies of OS X as they wanted to create and charging whatever price Apple wanted to charge (including no price at all) for those copies.

Note that I'm relying on the distinction that controlling the price for a product is not the same as controlling how much you can charge successfully. Microsoft gave IE away for free. That rather hampered people being able to charge money for comparable software. It did not alter the ability of those companies to charge whatever price they wanted to for competing browsers. You cannot actually be said to be capable of manipulating price until you can move it up or down at your whim. The ability to move prices down is inherent in the marketplace and your ability to compete in it. The ability to move prices up is the key to being an actual monopoly.

It Isn't Fair!

The second largest complaint is that Microsoft engages in unfair practices to privilege their software because they "own" the OS. Now, I haven't been a fan of the "it's not fair" defense since my kids grew up enough to employ it. I personally stopped expecting life to be fair a long time ago. The thing is, I'm enough of a libertarian that as long as all parties to a transaction are informed and consenting, I don't have much problem with them working out whatever deals they think they can.

Still, you can't deny that Microsoft likes its shady deals. I certainly wouldn't dream of denying it. In fact, I'm all for exposing those deals as soon as they're known, and the sooner the better. Does Microsoft have a deal with Dell that includes Dell anteing up for every PC purchased? Doesn't matter to me, but by all means, get the news out if you discover it to be true. I mean, as far as I can see, Dell wouldn't be doing so if the net cost to them weren't cheaper than doing it the other way. As long as Dell is able to compete in its markets for computers, I'm not really that interested. After all, if Dell raises the price of computers that don't have some version of a Microsoft OS, you have to know that they'll get hammered by their competitors who aren't trying to recoup such costs.

That's the magic of capitalism. You only get to set the price, you don't get to set the demand. If somebody else can do it cheaper, then they'll come in and prove it in the only way that matters—by offering their product at a lower price.

Does Microsoft sometimes fail to, ahem, document their complete APIs for external sources? That certainly appears to have been the case in the past. Insofar as they might have claimed to have documented the entire API, they have violated the law and should be held accountable for doing so. Outside of such a claim, I don't see how we have any standing to demand otherwise. Not that we shouldn't ask for better, but there's no cause to be slinging charges of moral depravity. You can't simply decide that a company has to release their full API when they haven't agreed to do so and expect to be taken seriously. Certainly, nobody expects the same from Apple. Fortunately, one consequence of all those shady deals makes Microsoft the most scrutinized software company on the planet so its ability to hide things is, shall we say, limited.

Scrabbling for the Top

Microsoft's dominance of the software market seems like it must have a monopoly somewhere. The fact that we can't detect it doesn't mean it isn't there, right? After all, random chance should dictate that some companies would successfully compete with Microsoft and their dominance would wane.

Ah. But since when did random chance have anything to do with markets, let alone software? There is, in fact, one thing that all successful companies do to become (and stay) successful: they attack #1. Indeed, those companies that rise to the first position and later fall always do so because they stop attacking #1. You see this with Sun. There was a period when they owned the corporate server market. The thing is, they stopped attacking themselves. Their resting gave their competitors an opportunity to come in and steal their lunch. Dell and HP saw that Sun's prices hadn't dropped even though the cost of hardware was falling steadily. They saw an opportunity and Sun is left wondering what happened. The same thing is happening with Oracle in the database server market and Sun (again) with the hot development language, Java.

And that's what has allowed Microsoft to dominate the OS and Office Application spaces for so long—they haven't stopped attacking #1, even when it's them. Microsoft, for some reason, has mastered the paranoia and internalized the lesson that they are only a couple of motivated geeks in a garage away from the #2 slot. Witness Office 2007 and the ribbon control. Microsoft could easily have sat on their dominance in the Office Application space. They didn't. Time will tell if that innovation makes their product better, but so far, it seems that it has.

The Beauty of Creative Destruction

Which brings me to the software development space. Microsoft has done here what they do in all the markets they come to dominate: stake out some initial territory and then expand to become the best value in that space (note that I said value, not software, or price, or technology). That's how they continue to dominate in business programming even though they charge money and the new kids on the block don't. Yeah, you can do some interesting things with Ruby on Rails, Java, or Eclipse. I'm not denying the achievements of others.

All I'm saying is that for me, the business developer, Microsoft makes the development decision an extremely easy one. For a paltry $2k a year, I can own everything Microsoft produces in one package—OS, IDE, servers, and Office Applications. I don't have to find out which distro is most popular. I don't have to research GNome vs. KDE vs. Xfce. And I don't have to browse a single Man page or HowTo.

Not that I wouldn't move if Microsoft stopped anteing up, but they don't seem to be doing so right now. Whether it's IronPython or Silverlight, or even Ruby, Microsoft shows no signs of letting others come in and eat their lunch. This is part of what makes it easy to be a Microsoft developer. If a good idea crops up in a space not currently dominated by Microsoft, you can bet that it won't be long before it's available in my dev environment either as a third-party add-in or from Microsoft itself.

The Wise Use of Power

All of that euphoria aside, Microsoft does have its problems. With great power comes great responsibility and Microsoft doesn't have a monopoly on ethical people in positions of power (uh, the "duh" is understood there, right?). Undercutting NUnit was a waste of community effort and good will. And what's happened with TestDriven.net is a bigger one. Indeed, with the details we have about the TestDriven.net case, it's obvious that Jason Weber at Microsoft behaved like an arrogant jerk and he deserves to take heat for it and Microsoft does as well.

Being a complacent consumer leads to complacent companies and products that never improve. So by all means, give Microsoft hell when they ask for it.

All I'm saying is that Microsoft isn't the dominant force it is in the markets it dominates because people are stupid. Any position that concludes that people don't know what is best for them is a position that I'm becoming increasingly impatient with. Brow-beating developers who don't kowtow to your party line isn't going to actually win you converts in whatever crusade you've decided to embark upon. By all means, give me your best pitch, I want to hear it. But don't assume that I don't have perfectly valid reasons for the choices I've made and even if I am a lazy bastard who couldn't program my way out of a wet paper bag, you are probably not best served by mocking me for it. Although, come to that, I sort of ask for it when I call OSS folk cry-babies with no justification...

Tags: , , ,

Programming | Software

Steve McConnell's Blog

by Jacob 25. May 2007 01:46

Oh my. Steve McConnell has started a blog. If you do not know who he is, you are either young in the ways of software development or aren't paying attention.

via Haacked

Tags: , ,

Software | Management

What's an Identicon?

by Jacob 12. May 2007 00:28

In perusing the release notes for Subtext 1.9.5, I noticed that Subtext now implements "Identicons". "Eh?" sez I. Not that I don't know what identicons are. They're a way to encode a web address in a manner that makes each address graphically unique with related addresses adopting a similar look.

Reading Phil's post, you can see identicons at work in the comments along with Gravatars (which Subtext has had for a while now—they're a central repository of an image representing you based on the email address associated with the post). Now, I've been meaning to implement gravatars in my Subtext skins for a while now, so I figured now seemed like a good time and began poking around.

Ouch. The original skin I copied six months or so ago didn't have gravatars in it, so I picked the code apart a little to figure out what might be needed. It turns out to be pretty easy, even if it took me forever to find: just add an asp:image with a particular id attribute to your Comments.ascx control. Subtext's default skins (I have got to start looking there first for these things) have it already.

Only, that turns out to be the easy part. The tricky part is figuring out that you'll also need to edit the web.config. Gravatars are documented on Subtext's main site, but it's a touch out of date, so you need to make sure that you have an updated web.config. Which is just as well because identicons are even newer and they're not documented at all except in the web.config file. The gravatar section looks like this:

Making sure that "GravatarEnabled" is set to true is the first bit, but the key to identicons is buried in the last four lines. Essentially, all you need to do is change them to look so:

With this, you're golden. Any gravatar that comes back empty gets made into an identicon. It does this by sending gravatar.com the identicon handler address in place of the "{1}" in the "GravatarEmailFormat" setting.

The only tricky part from there is updating the skin and appropriate style sheet(s).

UPDATE: After playing with issues of the above code displaying poorly on my current skin, I've swapped the <pre> tags out for images. I just didn't like where it was going with the clipping vs. scrolling and all. Clicking either image will give you a page with the original text (in case you want to copy and paste or just for nostalgia's sake). Apologies for anyone who was trying to read the post while I was futzing.

 

Tags: , , , , ,

Programming | Software

Subtext Release 1.9.5

by Jacob 11. May 2007 09:42

Phil Haack just announced the official release of Subtext 1.9.5. There's some cool new features in this release, one of which I made significant contributions to the project for. I'm inordinately proud of that. I've been running 1.9.5 for a while now and it's been pretty solid.

Anyway, you can download the latest release here. Subtext has a pretty responsive community and I've enjoyed working on the project.

Technorati tags: , ,

Tags: , ,

Software

More Cloudy Days

by Jacob 16. April 2007 00:48

If you have the eye of a good copy editor, you might have noticed some volatility in the ole Tag Cloud on the right. I made some changes at the request of people on the SubText developers list and reworked some stuff—most of which is completely invisible. The biggest visible change is that I decided that assuming an even dispersion around the mean might work in natural statistics, blog post tags tend to be more of a declining curve however.

What that means is that most algorithms for displaying tag clouds use a formula that allocates about half their categories to styles that are never visible. Most tag clouds I saw had slots for up to seven different visual styles that only really displayed three or four.

Well, that's just a waste of a good idea, I say! So I mucked with the weighting formula so that I'd see more visual variation in my clouds. We'll have to see if my theory holds after scrutiny and on blogs with larger traffic.

Tags: , , , , , ,

Programming | Software

scruffylookingcatherder.com

Information

    Recent Posts

    Calendar

    <<  September 2010  >>
    MoTuWeThFrSaSu
    303112345
    6789101112
    13141516171819
    20212223242526
    27282930123
    45678910

    View posts in large calendar
    Disclaimer
    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2010 Scruffy-looking Cat Herder