Let's say we have two functions which first do some parameter checking. They return early if the checks are not met. Then they do stuff. Quite simple:
function funcA (inputParam) {
if(!inputParam.valueA) {
// Do error handling
return;
}
// Do stuff
}
function funcB (inputParam) {
if(!inputParam.valueB) {
// Do error handling
return;
}
// Do stuff
}
Now, after implementing and using those functions frequently, we realize that there is another condition which needs to be met in both functions. Of course, we do not want to copy&paste that parameter check, but re-use it for both functions. It is not that simple to put it into a function and call the function because the called function would need to make sure that the rest of the caller function is not executed if the param check fails.
A function like
function checkC (inputParam) {
if(!inputParam.valueC) {
// Do error handling
return;
}
}
will not work, because if we call it like
function funcA (inputParam) {
checkC(inputParam)
// Do stuff
}
then it will always reach Do stuff
no matter the outcome of the parameter check, but if you do
function funcA (inputParam) {
return checkC(inputParam)
// Do stuff
}
then Do stuff
will never be reached of course.
So, what would be the most elegant way which requires the least refactoring?
Ideas I came up with:
function commonFunction(inputParam, proceedWithAOrB) {
if(!inputParam.valueC) {
// Do error handling
return;
}
if(proceedWithAOrB === 'a') {
return funcA (inputParam);
}
if(proceedWithAOrB === 'b') {
return funcB (inputParam);
}
}
But that would require a significant amount of refactoring.
function checkParamC (inputParam) {
if(!inputParam.valueC) {
return false;
}
return true
}
function checkParamCErrorHandling (inputParam) {
// Do error handling
}
function funcA (inputParam) {
if(!checkParamC (inputParam)) {
return checkParamCErrorHandling (inputParam);
}
// Do stuff
}
That way, we would not need to copy&paste actual logic, but it is still not very elegant.
I feel like that I'm missing something and there must be a more elegant solution to this?
Edit For some reason, throw new Error...
is not an option in my case.
You could use a mixin...
function requireCheckC(callable){
return function(inputParam){
if(!inputParam.valueC) {
// Do error handling
return;
}
return callable(inputParam);
}
}
const funcA = requireCheckC(function(inputParam) {
if(!inputParam.valueA) {
// Do error handling
return;
}
// Do stuff
});
Basically the requireCheckC will return a function that first checkC and then follow with the execution of the function passed in parameter.
While I'd still say the best way would be to use error throwing for... well, handling errors...