Create form via a controller
This is definitely possible (and preferable). There are a few ways to do this, but I think the preferred approach is to first specify your form in your routing entry (mymodule.routing.yml)

mymodule.some.route:
  path: '/foo/bar'
  defaults:
    _form: '\Drupal\mymodule\Form\MyForm'
    _title: 'My form title'


The routing system will automatically build your form for you. The class \Drupal\mymodule\Form\MyForm should implement FormInterface. An easy starting point is to extend \Drupal\Core\Form\FormBase.

There are several examples of this in core. For instance, the entity.user.admin and user.admin_permissions routes in users.routing.yml.