Seems like I need to argue to why I told him to make the class a singleton.
The osu!api is something we want to get from everywhere and I can't see a reason why we would need to create multiple osu!api objects.
In the end, there will always have only one osu!api object, on which we will call the classic "getBeatmaps" or "getUser" methods.
So if you don't want it as a singleton, I can't see how you want to make the osu!api class so it's not a singleton yet only one can be used.
I know singleton is something that is always see as "bad practice", but there is some cases where it can fit what we want to do, and I think this is the perfect case where singleton is a good way to do what we want to do.
Also, it's been a long time since I checked here, so:
abraker wrote:
I might not fully understood what you meant, but I did it this way to make the coding cleaner. If I did
Osu_Info::getInfo(Osu_Info::MODE::get_user_best, "param1", "param2", "param3", etc);
Then the order of the parameters would matter and in most cases not all paramaters will be used. Consider this code:
// load parameters
params[U32 Osu_Info::PARAM::user_ID] = "abraker";
params[U32 Osu_Info::PARAM::game_mode] = GAMEMODE::Mania;
params[U32 Osu_Info::PARAM::limit] = "50";
user_best = Osu_Info::getInfo(Osu_Info::MODE::get_user_best, params);
If I was to do what you propose it would look like this:
Osu_Info::getInfo(Osu_Info::MODE::get_user_best, "abraker", "", "50", "", "", "", GAMEMODE::Mania, "");
I suppose I can do this, but it looks ugly IMO.
Well, in cases like this you have the method overloading that can make things work pretty well.
For example, instead of having only one method with a lot of arguments, you can always have multiple methods with the most used arguments. But this is your choice. I just tend to prefer having multiple methods with variable number of arguments instead of passing an array/object of parameters.
Edit: I forgot to add that you can always separate the method in multiple methods like getBeatmap, getUser, getUserBest, ...
This will simplify a lot the method calls as we will have the correct method to call for what we want, will be less prone to errors and will be a lot easier to use.
abraker wrote:
I can't figure this out for the life of me! There doesn't seem an easy to do this within Visual Studio. I think I will have to create a new project and copy everything to the new folder. I'll do this in the next update.
Apparently you fixed it, but in cases like this you just need to rename the project.sln file and the project.vcxproj file.
No need to recreate the project, as visual studio doesn't care how the files are called, as long as they contain the right informations.
abraker wrote:
Do I? I am using it as a string.
if (_param[U32 PARAM::game_mode] != "")
url += ("m=" + _param[U32 PARAM::game_mode] + "&");
I could pass it as a 3rd parameter, but I want to keep consistency. All parameters will be passed through an array of 8 strings.
No, but I mean, instead of doing something like:
params[U32 PARAM:game_mode] = "something";
params[U32 PARAM:limit] = 50;
you could do:
enum Parameter
{
kGameMode = 0,
kLimit = 1
}
params[Parameter::kGameMode] = "something";
params[Parameter::kLimit] = 50;
And your parameters could be defined in a map<int, string> or even better, in a custom class, where your [] operator would look like:
operator[] (Parameter param)
{
switch(param)
{
case Parameter::kGameMode:
// Handle game mode setter
break;
case Parameter::kLimit:
// Handle limit setter
break;
default:
break;
}
}
Sorry if I'm not really clear. If this is the case I'll try to make a better example, or something like that.
abraker wrote:
You mean typedef? If so, I did it for the previous design with tables, but didn't feel like vector<vector<string>> needed one. Though, I can make it so.
No, I meant that you would make something like an Osu::User that will contain all the informations parsed from the json.
For example:
namespace Osu
{
struct User
{
long id;
std::string username;
...
}
}
This would be way better to understand and to use than a vector, and would be less prone to errors.
Oh and a last thing about the singleton.
Instead of putting in the object a field named instance and initializing/returning it from a get_instance method, you can just make a get_instance method containing the following:
const Osu_Info& Osu_Info::getInstance()
{
static Osu_Info instance;
return instance;
}
This will create a static instance of the Osu_Info object the first time this method will be called and will use the same each time this method is called.
Oh and you can also make a shortcut macro, like:
#define [whatever] Osu_Info::getInstance()
This will enable users to call [whatever].setApiKey(), or [whatever].getInfo() instead of calling the cumbersome Osu_Info::getInstance() each time.