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:
- 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.
- 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?
- 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.