I know that in ColdFusion, making the access level of a function remote means that all arguments are required. How do I correctly deal with optional arguments? Often we are getting requests sent to these functions with:
?method=doSomething&requiredArg="something"&optionalArg1=&optionalArg2=
Is the only way to deal with this making the type of the argument in the function "any" or "string" and doing type checking in the code? I'm considering building an master "remoteApiCFC" that does this with a function and running it on every remote function to get a local.arguments struct. Is there a better way?
This is how you define optional arguments for a method:
remote string function foo (
required string bar,
string option1="optional") {
return(bar & option1);
}
Related
My team works on an HTTP web server in C++. The codebase has aged over time, and has a widespread problem of 12+ parameters being passed to every function.
A fake example: We need to build a Car, but in order to do that, we have the following function:
MaybeBuildCar(engine_params, steering_params, interior_params, fuel_params, available_inventory, parts, &debug);
Someone on our team has proposed that we create a wrapper CarBuilder class whose constructor takes in the params and "stateful" objects like available_inventory, then has a separate function for BuildCar as follows:
CarBuilder car_builder(engine_params, steering_params, interior_params, fuel_params, available_inventory, &debug);
auto car = car_builder.BuildCar(parts);
Personally, I don't see much value in having a class with a single public function that is always called. We'll always need these parameters, and we'll always need the parts, so this just adds more steps to build the car. It could even add confusion, as now a user of CarBuilder must know to both construct it and call BuildCar.
Admittedly, this simplifies our helper functions within car_builder.cc, as they also require passing these params, but to me that's misusing what a class is for: maintaining state.
Is creating this CarBuilder a misuse of the class, or is simply cleaning up function signatures a valid use? Does anyone have any suggestions on how to tackle this problem?
Minimizing function parameters can be a blessing for heavily used functions in a performance-sensitive environment:
If you pass 6 references to a function, that is 6 pointer copies pushed to the stack;
If you pass a single CarBuilder, it is one "reference-that-contains-6-other-references".
It depends on your situation.
you could define a class that contains all parameters and in each function just passed this object.
struct CarComponent
{
public:
EngineParams engine_params;
SteeringParams steering_params;
InteriorParams interior_params;
FuelParams fuel_params;
AvailableInventory available_inventory
};
MaybeBuildCar(car_component);
other_function(car_component);
Advantage:
Function's signature is decoupled from changing members of the struct (CarComponent). easy to change.
Refactor all the parameters in each function with a specific object. it prevents repetition and it becomes easier to read the code.
I am currently working on an HTTP API that I want to use to perform CRUD operations on a database. I try to write the code for it as generic and modular as possible. I am using the MySQL X DevAPI.
Currently, I am stuck on the following problem:
mysqlx::Result MySQLDatabaseHandler::jsonToCUDOperation (const nlohmann::json& json, mysqlx::Table& table, int crudEnum)
The function above takes as an argument a reference to a json object, a reference to a table object and an integer.
What I want this function to do is:
Check the integer to decide what operation to perform
Check the size of the json to know how many parameters are gonna be passed to the variadic function of the X DevAPI that is used to perform the operation.
Assemble and perform the function call
For example, assume a table "users", as well as a json object "X" with following contents:
{"id":1,"username":"test_user","email":"test#test.com","first_name":"test"}
Now, when I would call the function like this
jsonToCUDOperation(X, users, MySQLDatabaseHandler::cud::create);
I would want the function to parse the json object and call the mysqlx::Table::Insert function with parameters (and parameter count) based on the json object's keys and values, so eventually calling
users.insert("id", "username", "email", "first_name")
.values("1", "test_user", "test#test.com", "test").execute();
I first thought about achieving this behavior using a template function, but then I figured it wouldn't make sense, since the template function definitions are generated at compile time, and what I desire would require dynamic behavior at runtime. So I thought that it is not possible to design this as I intend, as it was my understanding that the behavior of a C++ function cannot change at runtime based on the parameters you pass to it. But I've figured that before I begin developing a solution which can only handle a limited json object size, I'd ask here to assure that I actually cant do what I want.
Thanks in advance for enlightening me
You can actually just pass STL containers to the CRUD functions provided by MySQL's X DevAPI
I have found out in the answer to a previous question a way to call a function defined in a (C++) xll without registering it. I was previously using the registering infrastructure provided by XLW and I was using the XlfOper type to pass the arguments between VBA and the xll.
The c++ function goes like this:
extern "C" {
LPXLOPER EXCEL_EXPORT a_function(XlfOper arg1, XlfOper arg2);
}
Following the answer to my previous solution, I am directly declaring the function, something like that:
Declare Function an_exported_function Lib "MyDrive:\MyPath\myxll.xll"_
Alias "a_function" (arg1 As Object, arg2 As Object) as Object
By attaching to the excel process I can see that the function is being called but I am getting garbage or null data in the arguments. This, I guess, comes from the fact that I have not told to VBA how to convert to the correct data type.
How can I correctly call an XlfOper argument? I think that calling an LPXLOPER should do the job, since xlw states the following:
It is important not to add any data members or virtual
functions to this class. The design of xlw relies on the fact that class
XlfOper has the same size as LPXLOPER/LPXLOPER12, this assumption allows
values of those types received from Excel to be interpreted by the library
as instances of XlfOper.
After some research i have found it: Passing User-Defined Types
MSDN wrote: Many DLL functions require you to pass in a data structure by using a predefined format. When calling a DLL function from VBA, you pass a user-defined type that you have defined according to the function's requirements.
So, you need to define XlfOper data structure ;)
In the mocking framework Hippomocks it is possible to check the passed arguments within an expectation. For example:
void Class::Method(int arg1);
...
m_mockRepository_p->ExpectCall(someObject_p, Class::Method).With(1);
Is there a possibility to check only some of the passed arguments? What should I write instead of ??? in the following code?
void Class::Method(int arg1, char* buffer_p);
...
m_mockRepository_p->ExpectCall(someObject_p, Class::Method).With(1,???);
For your information: The use case is that someObjet_p creates internally a buffer to read data in it and passes it to Class::Method. Firstly I don't care in which buffer someObject_p would like the data to put in. Secondly I don't have access to the internals of someObject_p to pass it to With() - which is quite reasonable.
Note: I've tagged the question as C++ as I make use of ExpectCall but I'd guess the same would apply to ExpectCallFunc for flat functions.
Second note: Hippomocks provides methods for expectations named "Match()", "getArgs()", "assignArgs()" and "matchesArgs()" but neither did I find any documentation on it nor do I know whether they are intended to be used (for my use case) or not.
Pass in a Don't-Care as that parameter:
m_mockRepository_p->ExpectCall(someObject_p, Class::Method).With(1, _);
I'm currently going from C# to C++ and rewriting some game engine code and I think I'm at a wall with tr1; Essentially what I want to do is have an input layer take input from the touchscreen and then fire a callback to notify any elements listening to that input. Now tr1/boost seem to make this super easy via the use of function and bind, however firing callbacks that are void() is no problem, but now I'm trying to send parameters through to these callback when invoke (enums for instance).
The problem here is that when I call bind, and insert the parameter, it doesn't act as a place holder rather it acts as the permanent value to be passed. For instance my code here:
Containing class:
tr1::function<void (MenuActions action)> callback;
callback = tr1::bind(&MenuScene::handleInputCallback, this, MenuActions::neutral);
m_menuUILayer->registerCallback(callback);
Has the intent that I create a function and bind it then registerCallback passes this callback into the member class and stores the reference. This part works, but now in the member class I can invoke the callback however the default parameters are always sent...
Member class:
if (m_callback)
{
m_callback(MenuActions::backgroundTouchDown);
}
So here rather than MenuActions::backgroundTouchDown being sent to the main containing class in the callback, the default MenuActions::neutral is still being used. I'm wondering if I'm missing something, or perhaps my lack of sleep is just sending me down the wrong path? Thanks guys!
You should use placeholders
callback = tr1::bind(&MenuScene::handleInputCallback, this,
tr1::placeholders::_1);
and then call like
if (m_callback)
{
m_callback(MenuActions::backgroundTouchDown);
}
and your function handleInputCallback can have default parameter, defaulted to MenuActions::neutral