0

I am trying to post this question neutral of programming language so it helps the widest audience. But for those who must know, I am using Objective-C and iOS frameworks.

The background:

I have a format string that describes the eventual value of an attribute, which is also a string. Example: attribute name of "report1" might have format of:

"[chefName] has [totalOrders]"

I can have several such attributes with different formats. These formats are centralized in a data file. My desire is to have future developers update this data file only to change the behavior of the code.

I hand the format to a parser which returns an array of single item dictionaries describing how to handle each element of the format. To continue the example:

[ {"chefName": "directive"},
  {" has ": "literal"},
  {"totalOrders": "directive"}]

I then process each element of the array to compose the final value. Anything tagged "literal" is simply appended to the final string value. Anything tagged "directive" is looked up in a dispatch table (dictionary) of functions and the return value of that function is appended to the final string value.

For example: a function at the dispatch table key "totalOrders" might also be named totalOrders() and it would return "12" as a string.

More details leading to my question:

For a lot of functions in the dispatch table, they obviously know best how to calculate and return the appropriate value. However, for a few items, it is the caller of the function who best knows the value.

Continuing example: suppose collectInfo() is a function that loops thru the parsed format array of dictionaries. It might know what the return value of chefName() should actually be even though it has no idea what totalOrders() should be.

Here is how I have current solved this. Every function in the dispatch table takes an argument. Some functions merely return back the argument they are given. Before calling a function, the caller looks up the key from the dictionary in another dictionary that is has. If there is a match, it passes in that value.

Example: collectInfo() has a dictionary named "specialX" that looks like this:

{"chefName": lookupChef(c)}

"c" is a variable local to collectInfo() that the chefName() function would not know about. So what collectInfo() does is call lookupChef(c) and hand the return value to chefName() like this:

chefName(lookupChef(c))

And the entire code for chefName() is:

chefName(x) {
    return x
}

Doing this allows my code to still (mostly) be data driven. I do not have to include if/then string comparisons and hard code things like "chefName" into my loop in collectInfo().

So here is my problems with this solution:

  1. I still have that "specialX" dictionary hard coded into collectInfo(). That kills my purely data driven approach. I am having trouble abstracting it out to a data file. I'm not sure I ever can.
  2. Is there some way I can create the chefName() function so it knows what it needs to know to calculate the answer? That is, is there some way to tell it about lookupChef(c) directly without breaking encapsulation?
  3. After I have parsed the format, perhaps there is a better approach entirely to composing the final value?

One final note.

You might be wondering where the dispatch table and the functions within it come from. That is the other file future developers will update if a new element is added. For example, if a new format element is added "[quantityOfButtons]" then a new entry in the dispatch table and a new corresponding function would have to be added as well.

The file where collectInfo() is defined imports the file where the dispatch table and its functions are defined.

1 Answer 1

1

It sounds like the crux of the problem is:

For a lot of functions in the dispatch table, they obviously know best how to calculate and return the appropriate value. However, for a few items, it is the caller of the function who best knows the value.

What solution you should use depends entirely on why the caller knows best, which you haven't explained. But it would probably boil down to this: Whatever special thing collectInfo() has access to, it should be giving it to the dispatch table functions. Then chefName() can access the special thing itself instead of relying on specialX to provide lookupChef().

Without knowing exactly what the special thing is and why the functions don't already have access to it, I can only suggest the obvious options like passing it to each function as a parameter (since they all seem to be 0-ary right now) or passing it to the dispatch table constructor (if it's the kind of thing that needs constructing).


Regarding question three, it sounds like what you're doing now is looking at an "element" (single-key dictionary), getting the value it refers to, then simply appending that value to the final string. This is probably fine, but if you feel the need to improve it I would suggest keeping the values in an array until you've retrieved all of them, then concatenating everything afterward.

The advantages are that the elements can be processed in any order (even in parallel), and it's very easy to do some validation or formatting logic on the values before converting them all to strings. For instance, you might check that totalOrders is a number, then add <font color="red"></font> if the number is less than 10.

1
  • @Ixrex wrote "What solution you should use depends entirely on why the caller knows best..." I'm meditating on this. Thanks.
    – Jeff
    Jan 30, 2015 at 14:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.