views:

119

answers:

4

I have an application loading CAD data (Custom format), either from the local filesystem specifing an absolute path to a drawing or from a database.

Database access is realized through a library function taking the drawings identifier as a parameter.

the identifiers have a format like ABC 01234T56-T, while my paths a typical windows Paths (eg x:\Data\cadfiles\cadfile001.bin).

I would like to write a wrapper function Taking a String as an argument which can be either a path or an identifier which calls the appropriate functions to load my data.

Like this:

Function CadLoader(nameOrPath : String):TCadData;

My Question: How can I elegantly decide wether my string is an idnetifier or a Path to a file? Use A regexp? Or just search for '\' and ':', which are not appearing in the Identifiers?

A: 

In my opinion, the K.I.S.S. principle applies (or Keep It Simple Stupid!). Sounds harsh, but if you're absolutely certain that the combination :\ will never be in your identifiers, I'd just look for it on the 2nd position of the string. Keeps things understandable and readable. Also, one more quote:

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. - Jamie Zawinski

Roald van Doorn
There's also that saying about making things as simple as possible, but not any simpler. Your solution would fail for UNC paths, for starters.
mghie
+5  A: 

Try this one

Function CadLoader(nameOrPath : String):TCadData;
begin
  if FileExists(nameOrPath) then
    <Load from file>
  else
    <Load from database>
end;
Bharat
+1 sounds like simple yet very good logic!
Remko
would certainly work, but wouldn't the automatic call to FileExists() cause unnecessary exceptions/fault conditions when the database identifiers are relatively easy to identify in comparison to a path to a file? Or perhaps I am optimizing prematurely?
Scott W
There is one caveat with `FileExists()` and similar functions: Using non-atomic operations in a multi-tasking system is inherently prone to failure. The call could return just before the file is created or deleted, and in both cases the result would be wrong. Simply trying to open the file (and handling the exception) would therefore be better. The same goes for the database access BTW, unless an explicit transaction is used. So I would just try both accesses, in the order of decreasing likelihood or cost, and raise an exception only if both fail.
mghie
+2  A: 

I would do something like this:

function CadLoader(nameOrPath : String) : TCadData;
begin
 if ((Pos('\\',NameOrPath) = 1) {UNC} or (Pos(':\',NameOrPath) = 2) { Path })
    and FileExists(NameOrPath) then
 begin
   // Load from File
 end
 else
 begin
   // Load From Name
 end;
end;

The RegEx To do the same thing would be: \\\\|.:\\ I think the first one is more readable.

Robert Love
Quite more readable
sum1stolemyname
A: 

You should pass in an additional parameter that says exactly what the identifier actually represents, ie:

type 
  CadLoadType = (CadFromPath, CadFromDatabase); 

Function CadLoader(aType: CadLoadType; const aIdentifier: String): TCadData; 
begin 
  case aType of 
    CadFromPath: begin 
      // aIdentifier is a file path... 
    end; 
    CadFromDatabase: begin 
      // aIdentifier is a database ID ... 
    end; 
  end; 
end; 

Then you can do this:

Cad := CadLoader(CadFromFile, 'x:\Data\cadfiles\cadfile001.bin'); 

Cad := CadLoader(CadFromDatabase, 'ABC 01234T56-T'); 
Remy Lebeau - TeamB