Hacker News new | ask | show | jobs
by badclient 5439 days ago
Nice post that would be even nicer if accompanied by some pseudocode examples.

You go on and on about constantly reducing the size of your controllers. I'm sold! I just don't know where to start :(

Let's say I am verifying login. So I have the controller that looks something like this:

Function logincontroller() {

if (model->verify(user,pass)) redirect(validurl) Else Redirect(invalidurl)

}

How can I improve this? Btw my intended syntax was php but left out proper syntax due to iPhone:)

1 comments

That looks pretty much correct:

* Model handles its own logic (in this case, verification of credentials)

* Controller controls what happens (calling model to verify, redirecting user)

In general, models should only be concerned about their own data, and about their relations to other models. All behavior related to users should be handled by controllers (that call models as needed).

Thanks for the reply!

Let's say I add a few more things to that controller: namely ability to check if account is disabled(and to disable after x attempts and notify user) or if a captcha needs to be shown or was shown etc.

I feel before you know it the controller can get fairly complicated with all the asserts in real-life scenarios. May be the orig author is ok with it but reading the post I started getting ideas about simple 5-10 line controllers.

Many of those real-life scenario assertions can be implemented as before/after/around filters, since they apply to many routes.

In Rails, :except and :only are super useful on filters.

Also, another possibility is to noun-ify some verbs. (Some may prefer to call it resource-ification, or REST-ification)

For example, you could create a PasswordResetRequest model, which handles all of the logic for checking the old password, the password confirmation, the new password's complexity, etc. Then it would be responsible for executing the actual password change as well.

As a bonus, noun-ification enables easy logging because you'll already have a data structure to store.

Usually with Node.js/Express we handle stuff like authentication on middleware, so controllers don't need to bother. The route just includes the authentication/authorization middleware if one is needed.

Here is a simple example for hooking in route-specific middlewares: https://gist.github.com/978411#file_express_middlewares.coff...

Disabled accounts should be checked in the model. But instead of returning a boolean, it could throw appropriate exceptions (WrongPasswordException, AccountDisabledException) that you can then handle in the controller.
This would be my preferred approach, you can even just key translations based on the name of the exception, then handle them all with a generic flash message / template.
Really? Throwing exceptions on known states of your model... hardly exceptional.
How else would you achieve it - throwing exceptions for program flow is quite common in Python for example; Iterator.next() throws StopIteration when it reaches the end of the iterable.
That's an exceptional circumstance, the iterator is not responsible for knowing whether you have reached the end of the collection.

You could achieve it by catering for these cases in your logic if user.authorize(email, pass): ... success ... else: ... fail ...

rather than try: user.authorize(email, pass) ... success ... except WrongPasswordException: ... fail ...