tags:

views:

47

answers:

3

Hi, I have been developing this class for loading plugins in the form of shared objects for an application. I currently have thought of 2 ways of loading the file names of all the plugins to be loaded by the app. I have written an interface for loading file names. I have a few questions about how to improve this design. Please help. Thanks.

EDIT: Code change per feedback :D.

#include "Plugin.h"

//This class is an interface for loading the list of file names of shared objects. 
//Could be by loading all filienames in a dir, or by loading filenames specified in a file.
class FileNameLoader
{
    public:
        virtual std::list<std::string>& LoadFileNames() = 0;
};

class PluginLoader
{
public:
    explicit PluginLoader(LoadingMethod, const std::string& = "");
    virtual ~PluginLoader();

    virtual bool Load();

    virtual bool LoadPlugins(FileNameLoader&);
    virtual bool LoadFunctions();

protected:
private:
    explicit PluginLoader(const PluginLoader&);
    PluginLoader& operator=(const PluginLoader&);

    bool LoadSharedObjects();

    list<std::string> l_FileNames;
    list<PluginFunction*> l_Functions;
    list<Plugin*> l_Plugins;
};

Anything that seems ugly still? Thanks for the feedback anyway.

A: 

You created a fine interface, but then you don't use it. And you then store the file names in a private member l_FileNames.

I would change the PluginLoader constructor to accept a FileNameLoader reference and use that reference to load file names. This way you won't need the LoadingMethod in the PluginLoader class.

Write two classes that implement the FileNameLoader interface, one for each loading method.

edit:

class FileNameLoader
{
    public:
        //RVO will work right? :D
        virtual std::list<std::string>& LoadFileNames() = 0;
};

class FileNameLoaderByFile : public FileNameLoader
{
public:
    std::list<std::string>& LoadFileNames()
    {
        //  ...
    }

}

class FileNameLoaderByDirectory : public FileNameLoader
{
public:
    std::list<std::string>& LoadFileNames()
    {
        //  ...
    }

}



class PluginLoader
{
public:
    explicit PluginLoader(FileNameLoader& loader)
    {
    fileNames = loader.LoadFileNames()
    }

    virtual ~PluginLoader();

private:
    list<std::string> fileNames;
};
vulkanino
I am pretty clear on the fact that no matter which way I generate the file names, they'll all be a list. That is why I wrote an interface for just the file name generating functionality.
nakiya
Yes, that is why I said you don't need the loading method in your class, you already have the interface.
vulkanino
What if I change it to : `virtual bool LoadPlugins(FileNameLoader*);`? And supply the file name loader from outside?
nakiya
vulkanino
Exactly what I meant in the post above. Ah, I think the problem with arguments is solved also :D.
nakiya
+1  A: 

It looks to me like you have your functionality spread across the enum, FileNameLoader, and the PluginLoader classes.

My suggestion would be to make a PluginLoaderByFile class, and a PluginLoaderByDir class - possibly with one inheriting from another, or possibly with a common base class. This way you can define other subclasses including the necessary additional code, and keep it encapsulated, if necessary, down the track.

This also makes it easier to use e.g. the factory or builder patterns in future.

sje397
Wouldn't a lot of code be duplicated then? I am sorry for being relentless, I only want to know the reasoning. :D
nakiya
Why would code be duplicated? This allows you to put common code in the base class.
sje397
Two things I would really want to avoid: (1) loosing type safety with e.g. a vector of parameters, or (2) a function that always returns a list of size 1.
sje397
A: 

As for your statement of the current problem. U can use either

  • vector for params or
  • since u are using a string u can as well parse it using some delimiter (say " ", ",")

However I wouldn't let the params or method of loading be visible in the PluginLoader.

Instead would use a common/generic interface.

aeh