Choosing method names for a cache interface

As part of the overhaul of the WilsonORWrapper, I’m adding a cache service. To do this right, I need to implement an ICacheClient interface. This interface will define the methods and properties which any cache client will need to implement.

Sounds simple on the surface, but I quickly ran into a problem. What do you call your methods? Consider the following possibilities for naming four core methods.

  • Retrieving an item from the cache: Get, Retrieve, Load, Fetch, Read, Select.
  • Placing an item in the cache: Put, Set, Add, Insert, Save, Update.
  • Determining if an item exists in the cache: Contains, Exists, Has.
  • Remove an item from the cache: Remove, Delete, Clear.
  • Clear all items from the cache: Flush, Clear, ClearAll, DeleteAll, RemoveAll.

The worst part of determining a naming convention is that you are generally stuck with it once you choose it, unless you want to implement breaking changes into your application.

Most of the names above were found in some cache API currently in existence today. (I did a Google search to find as many as possible.) Some of them are not recommended because their usage is uncommon (such as Fetch, unless you have a DogCacheClient). I’d also stay away from the *All methods — they sound good on paper, but the difference between Remove and RemoveAll is quite big, and you can call the wrong one if not paying sufficient attention.

With those left over, you can organize them into groups based on similarity of use in well-known applications, languages, and APIs.

  • SQL Style: Select, Insert, Update, Exists, Delete, Clear.
    This style is good if you expect to have separate Insert and Update methods, where Insert can only add new items, and Update is used to change existing items.
  • Collection Style: Get, Add, Contains, Remove, Clear.
    The common naming used in Microsoft and Java collections.
  • Simple Style: Get, Put, Has, Remove, Clear.
    Short and sweet. You can arguably combine Remove and Clear if you’re brave.

Which one should I use for the WilsonORWrapper? One thought is to use the SQL style, since this is a wrapper for an O/R mapper, which is closely tied to SQL. However, I don’t want separate Insert and Update methods. Also, the point of the wrapper is to allow people to write in code, not in SQL, so the relationship to SQL should not dictate style.

That leaves us with the simple style and the collections style. NHibernate uses the simple style in their Cache API. Microsoft’s System.Collections namespace uses the collection style. I’ll go with a combined version: Get, Set, Contains, Remove, Clear, mostly for the reason that users of WilsonORWrapper are probably more familiar with Microsoft Collections than NHibernate, and because I prefer Set over Add.
Have you seen, or used, other naming conventions in your travels?

KISM: Keep it simple, Microsoft

Microsoft, the company who provided the products and tools for millions of people to build careers off (myself included), has often forgotten that the simple solutions are often the best. In a recent blog post, hammett wrote about Microsoft’s missteps in this area and their focus on YAGNI (You Ain’t Gonna Need It) — at least, where “You” refers to most people.

[Digression: Someone at some point commented on Microsoft Word that “90% of the features are used by 10% of the people”. If I was designing a product and 10% of my features were used by 90% of the people, and the other 90% of the features were used by 10%, I’d either write two products, or I’d write one product that was incredibly extensible using a plug-in architecture.]

This feature-bloat approach to technology reminds me of Microsoft’s Enterprise Library and the Data Access Application Block (DAAB). In the first release of the DAAB, you can call a parameterized stored procedure and get a DataReader back using one line of code, as illustrated below.

IDataReader reader = SqlHelper.ExecuteReader(
    connectionString, CommandType.StoredProcedure, storedProc, 
    new SqlParameter("@ID", 1));

In the latest DAAB (part of Enterprise Library 2.0), this becomes:

Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetStoredProcCommand(storedProc);
db.AddInParameter(cmd, "ID", DbType.Int32, 1);
IDataReader reader = db.ExecuteReader(cmd);

I also should mention I also should mention that the latter example also requires a special configuration section added to your application config file, whereas the former just requires a connection string (which likely you already include somewhere in your application configuration).

The first example hides the complexity that you may not need in most circumstances. Granted, you can still use (or write your own) SqlHelper, but why break away from this entirely?

Simplicity is a wonderful thing. Let’s hope Microsoft finds it again. Give power to those who need it, and simple elegance to those who don’t. It’s not hard to do both, if you accept the fact that one size does not fit all.

Copying an ADO RecordSet in Visual Basic

The ADO RecordSet object’s Clone method does a great job of making a duplicate copy of the RecordSet, with one major caveat: any changes to the clone are duplicated on the original. It’s more like a shallow copy than a deep copy.

To make an actual copy of a disconnected ADO RecordSet in Visual Basic, use a method like the one shown below, which was largely taken from Francesco Balena’s article on devx.com:

Private Function CopyRecordset(rsSource As ADODB.Recordset) As ADODB.Recordset
    Dim rs As ADODB.Recordset
    Dim pb As New PropertyBag
    ' create a copy of the recordset
    pb.WriteProperty "rs", rsSource
    Set rs = pb.ReadProperty("rs")
    ' release the memory
    Set pb = Nothing
    Set CopyRecordset = rs
End Function

How does ProxyBuster.net work?

I received an email today from Johnny B. (Good?), in which I was asked a question about a Web service I provide, ProxyBuster.net. The email was:

Hello. I had a little question and I’ll be so glad if you can answer me. I wanted to ask: What system or platform does ProxyBuster use in its process, is it CGI, PHP, ASP, JavaScript, or something else? I mean which one of these can manage to trick the firewall and access a forbidden file?

My response is: None of those, actually. The “trick” is understanding how firewalls work. Most firewalls/proxies do one of a few things:

  • Block by IP address.
  • Block by domain name.
  • Block by URL text.
  • Block by file extension.
  • Block by HTTP content type.
  • Block by actual content type.

Let’s say you want to access Google’s home page (http://www.google.com/index.html). A firewall can:

  • Block the IP address 216.239.39.99.
  • Block the domain name, www.google.com.
  • Block a URL that has “www.google.com” in it (as in http://www.google.com).
  • Block all files ending in “.html”.
  • Block all files that have the HTTP header content-type “text/html”.
  • Block all files that are actually text files.

In this case the first three bullet items are effective, but the last three would limit your ability to use the Internet as a whole. Usually binary files (ZIP files, EXE files, etc) are restricted by the latter three types of blocks, and entire sites by the first three types of blocks.

So how does ProxyBuster do its magic?

First, if your firewall/proxy blocks the IP address, that’s not a problem to ProxyBuster, because you do not connect to the site directly. ProxyBuster connects to the site and reads your data, then provides it to you. Of course, if your firewall/proxy blocked www.proxybuster.net or our IP address, you’d be out of luck using our service because you wouldn’t be able to connect to it!

Next, ProxyBuster returns the file to you in one of a few formats. First, the file is sent to you as “download.aspx” — which is a very generic file name and file extension that would be too restrictive to block. (For example, blocking “.aspx” files would make it impossible to browse Microsoft’s Web site.) Next, we give you the option to receive the file with an HTTP content-Type header “text/plain” even if the file is not a plain text file. Last, if your firewall/proxy blocks binary files, we can send you the file in a text-encoded format (so it’s transmitted as a text file); all you need to do is decode it after you receive it (which does require a separate utility).

I hope this sheds some light to the inner workings of ProxyBuster!