I’m trying to use the middleware pattern to avoid repeating same code over and over again. In my application I work with user data a lot, therefore there are a lot of checks here and there. The problem I encountered is that my middlewares only work with pure functions, that do not depend on any data. I will try to explain with pseudo code examples (JavaScript but I hope it doesn’t matter too much).
This is my middleware helper function:
type Function = (user: User) => boolean;
On(user: User, functions: Function[]){
for (let i = 0; i < functions.length; i++) {
const result = functions[i](user);
if (!result) break;
}
}
Now we can write a bunch of functions that would perform some kind of check on User
and return a boolean, then continue or break:
function IsAuthorized(user){
if (!user.authorized) {
user.print("You are not authorized");
return false;
}
return true;
}
And finally use them like so:
On(user, [ IsAuthorized, IsAdmin, IsAnotherCheck, FinallyTheActualFunction ]);
But all those functions only work with simple checks that require nothing more than user
object. For example, a function could perform a lookup whether an user
is in group
. Since this operation is expensive (imagine fetching it from SQL/disk/etc), it would be better to pass the group
object to next checks so they do not repeat this task.
What should I do in this situation?
Have an object to set custom properties on and pass to the next function?
Also is it okay to throw
instead of returning false then handling the exception at the helper function?
Your middleware will need access to the services that can tell it what it wants to know. You should not be bothered too much with how expensive this is. Caching of static data from the database in your middleware layer may help but may not be meaningful if it is for an interactive logon. Make it work first.
Passing on information may defeat the purpose of a validation. You want to hear from the level that has the truth, not ask a question and provide the answer as an argument.
Throwing exceptions and handling them at the appropriate level is the OO way to do it and should make your life easier in validation scenarios like the ones you describe.