What is the correct way to call a service in a controller?

The best practice is to inject a service as a dependency into a controller, and then we can utilize the service object to invoke its methods. 

What is dependency injection?

Dependency injection is a design pattern in which an object or function receives other objects or functions that it depends on. It means we can directly inject the services to the class __construct method, and it will load the dependency runtime when instantiate the class.

Credit - https://www.tothenew.com/blog/services-and-dependency-injection-in-drupal/

Why use dependency injection?

  1. It improves code reusability.
    Services in Drupal enable us to define our code in a manner that promotes reusability across multiple modules. This is achieved by injecting these services as dependencies, allowing them to be utilized by various modules.
     
  2. It improves the flexibility and maintainability of code by loose coupling.
    Services in drupal are loosely coupled which enhances the independence of a service from other code components. This loose coupling results in increased flexibility and maintainability for the service.
     
  3. It improves testability.
    Drupal services can easily be used with unit testing making it effortless to write test cases.

Let's come back to our question, the recommended best practice is to inject a service as a dependency into a controller and then utilize its object to invoke its methods. 

Okay, let's see how we can do this.

Step 1:- Develop your service

File:- my_module.services.yml

services:
  my_module.helper:
    class: Drupal\my_module\ModuleHelper
    arguments: [ '@logger.factory' ]

File:- /my_module/src/ModuleHelper.php

<?php

namespace Drupal\my_module;

use Drupal\backup_migrate\Core\Translation\TranslatableTrait;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;

/**
 * Provides a 'ModuleHelper' class.
 */
class ModuleHelper {

  use TranslatableTrait;

  /**
   * Logger key.
   */
  const LOGGER_NAME = "my_module";

  /**
   * Logger service.
   *
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  protected $logger;

  /**
   * Construct service object.
   *
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerChannelFactory
   *   Logger factory service.
   */
  public function __construct(LoggerChannelFactoryInterface $loggerChannelFactory) {
    $this->logger = $loggerChannelFactory->get(self::LOGGER_NAME);
  }

  /**
   * A test function to log info.
   */
  public function testHelperFunction() {
    $this->logger->info($this->t("Helper function called."));
  }

}

Step 2:- Create your controller and inject your service.

File:- my_module.routing.yml

my_module.test_ctrl:
  path: '/site/test-ctrl'
  defaults:
    _controller: '\Drupal\my_module\Controller\TestController::index'
  requirements:
    _permission: 'access content'

File:- /my_module/src/Controller/TestController.php

<?php

namespace Drupal\my_module\Controller;

use Drupal\my_module\ModuleHelper;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Controller\ControllerBase;

/**
 * Provides a 'TestController' class.
 */
class TestController extends ControllerBase {

  /**
   * Module helper service.
   *
   * @var \Drupal\my_module\ModuleHelper
   */
  protected $moduleHelper;

  /**
   * TestController constructor.
   *
   * @param \Drupal\my_module\ModuleHelper $moduleHelper
   *   Module helper service.
   */
  public function __construct(ModuleHelper $moduleHelper) {
    $this->moduleHelper = $moduleHelper;
  }

  /**
   * {@inheritdoc}
   *
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *   The Drupal service container.
   *
   * @return static
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('my_module.helper')
    );
  }

  /**
   * Index of controller.
   */
  public function index() {
    $this->moduleHelper->testHelperFunction();

    return [
      '#markup' => $this->t('Response form my controller, You can check dblog for logged message'),
    ];
  }

}

Dependency Injection for a Form :- https://www.drupal.org/docs/drupal-apis/services-and-dependency-injection/dependency-injection-for-a-form