I have a very class heavy approach to writing C++ code, which I don't think is necessarily wrong. However, I often use classes without knowing if I actually need them, which I feel leads to making poor/unnecessary design choices. I think this may be a problem. I know there isn’t a definitive right answer to this, but perhaps there are guidelines that could help nudge me in the right direction when it comes to making design decisions?
To use as an example here is an asset system I tried to make as part of my game engine library learning project.
class IAssetLoader {
public:
virtual ~IAssetLoader() = default;
virtual std::unique_ptr<std::any> load(const AssetMetadata& metadata) = 0;
};
class MeshLoader : public IAssetLoader {
public:
MeshLoader(IGraphicsDevice* graphicsDevice);
std::unique_ptr<std::any> load(const AssetMetadata& metadata) override;
private:
IGraphicsDevice* m_graphicsDevice;
};
class TextureLoader : public IAssetLoader {
public:
TextureLoader(IGraphicsDevice* graphicsDevice);
std::unique_ptr<std::any> load(const AssetMetadata& metadata) override;
private:
IGraphicsDevice* m_graphicsDevice;
};
This made sense to me because a MeshLoader and TextureLoader both load assets, therefore are types of an asset loader. However, from what I understand about inheritance and polymorphism, they aren't really interchangeable. Where I use a mesh loader I'm probably not going to use a texture loader and vice versa. There isn't any shared logic/state as of yet and the state they do have (the graphics device) could probably just be passed as a method parameter instead. I think the only advantage I get out of this is being able to store them into a single container std::unordered_map<AssetType, std::unique_ptr<IAssetLoader>> loaders; inside of an AssetManager class.
std::unique_ptr<std::any>is a very smelly type, which makesIAssetLoadera smelly type too. If you have anIAssetLoader, and no other context, you can't do anything useful. \$\endgroup\$