Could someone explain what is the correct way of using Lightning helpers? Is that any place where I can find best practices how to move code from the controller to the helper? Sometimes I see in js controller methods that call methods directly from the helpers without any additional logic inside of controller method. But sometimes developers move part of code to the helpers.
Here is a article to give you a very good idea about helper.js vs controller.js.
The most important thing is that same instances of the component share one helper. This is important when you're doing things like
action.setStorable() in your
helper and you have same data that should only be fetched once, then all instances of your component (except the first) won't go to server to fetch it.
Generally, it's best to
handleClick\handleChange\handleLoad in your controller and then
execute/fetch/get it in your helper. This is the pattern that made the most sense to me so far.
The accepted answer from Rajesh is good here. To re-enforce that and add some non-SF terminology to it, it's helpful to think in terms of the Model-View-Controller pattern.
If you try to draw boxes around a Lightning Component to decide what's the Model, what's the View, and what's the Controller, then I think it ends up like this:
View: The markup
Controller: The controller.js, this translates front-end commands (e.g. click, hover, etc.) into more abstract commands that can be sent to the Model
Model: The helper.js, and the Apex Controller. This is the business logic, storage, etc. It doesn't really know about the UI. The UI should be able to change without this changing. So, for example, if you had a text input in your markup and you changed it for some radio buttons, the model should never have to change. In Lightning, controller.js might have to change but helper.js should not. (Unfortunately, Lightning's abstractions are currently a bit leaky here so you might have to use Apex to get your list of options. You could do this by introducing a new component which just fetches those options, gets included in the markup, and doesn't break MVC in this particular component)
It's easy to get confused about MVC:
<lightning:input>is MVC, and so is your custom component that uses it
Anything other than trivial logic ends up being broken up into methods that call other methods and the lack of that capability in controllers (but it being allowed in helpers) makes controllers often end up delegating all their work to a corresponding helper method.
I sure hope there is some strong benefit of this controller/helper pattern to the framework or some categories of components because I've found it in general to just result in more boiler plate code to have to write and refactor - not elegant.