A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.
Our project manager is having a design contest among the development teams. The prize is a 500$ (per person) for the team with the best solution.
Question: A task is defined by 'client-code'. That task is assigned to 'executing-code'.
First came up with a C-sytle design:
// do the job...
Once written it is easy to replace f() with any other function. Replacing the executer is more complex and requires dealing with c-pointers (like if you wish to execute a function which receives parameters).
Our next design is C++.
virtual void Execute() = 0;
// data members
Using this solution, the user has only to implement a 'concrete-command'. No pointers know how is needed.
What is your view of these designs?
Do you have any other to offer?
Thursday, September 14, 2006
Design is always a trade-off. You've implemented in the second design a standard command pattern, which is great for sweeping general problems of the type you described. However, the best designs are tailored to the problem.
What are the specific requirements?
Oh yeah, and in the second implementation, you've got a potential pointer exception.
Ie// What if I write:
Command * test = null;
or I write:
int i = 0;
Either handle the exception in a try-catch inside f() or use a dynamic_cast<> and check to see if the returned pointer is null or not.
Doing a dynamic_cast is faster, doing a try/catch is more comprehensive. Depends on the particulars of the requirements, which you choose.
This same exact question has been posted now 6 times, in two different discussion groups, by three different user names.
ISTM this is a homework question.
Maybe this time it's getting answers because the poster used a female name instead of male? <g>
Thursday, September 14, 2006
Have you considered a solution that utilizes boost::function?
You can assign generalized callback functions to this function object and, if necessary, bind arguments to the execution of this function with boost::bind.
Additionally, boost::function can be evaluated in a boolean context to avoid exceptions like the example presented above.
// myFunc is undefined
// Whatever error handling code you want
The other way to solve this problem is to implement a message passing/queueing scheme. You would have an Execute method on Executor that takes a given message signature (a struct, XML, whatever) and invokes it. Generally, in this case, the message has some sort of "target" property (be it another process, a web service, some compiled code, a pointer, whatever), some parameters and a return signature.
But that's only better design if you expect to handle commands from external sources. This is the way that server programs work (they take a request, execute it and then return some results).
See what I mean about requirements? *grin*
This topic is archived. No further replies will be accepted.Other recent topics
Powered by FogBugz