The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Design challenge

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:

void f()
{
// do the job...
}

execute(void *task)
{
void (*pFunc)();
pFunc= (void(*)())task;    
pFunc();
}

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++.

class Command
{
public:
 Command();
 virtual ~Command();
 virtual void Execute() = 0;
}

class ConcreteCommand:Command
{
 void Execute()
 {
 }
 private:
 // data members
 ...
}

class Executer
{
 f(Command *p)
 {
  p->Execute()
 }
}

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?

Laura
Laura
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?

- James.
James Birchall Send private email
Thursday, September 14, 2006
 
 
Oh yeah, and in the second implementation, you've got a potential pointer exception. 

Ie// What if I write:

Command * test = null;
Executer e;

e.f(test);

or I write:

int i = 0;
Executer e;

e.f((Command *)&i);

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.

- James.
James Birchall Send private email
Thursday, September 14, 2006
 
 
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>
KenW
Thursday, September 14, 2006
 
 
Yeah, project managers are always offering $500 prizes in design contests... just do your own damn homework.
Mike S Send private email
Thursday, September 14, 2006
 
 
Have you considered a solution that utilizes boost::function?
http://www.boost.org/doc/html/function.html

You can assign generalized callback functions to this function object and, if necessary, bind arguments to the execution of this function with boost::bind.
http://www.boost.org/libs/bind/bind.html

Additionally, boost::function can be evaluated in a boolean context to avoid exceptions like the example presented above.

i.e.

boost::function<void()> myFunc;

if(myFunc)
    myFunc();
else
{
    // myFunc is undefined
    // Whatever error handling code you want
}
Daniel Price Send private email
Thursday, September 14, 2006
 
 
James, thanks.

Laura
Laura
Thursday, September 14, 2006
 
 
Laura,

You're welcome.

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*

- James
James Birchall Send private email
Thursday, September 14, 2006
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz