Как лучше обращаться с параметрами метода?
Аргументировать довольно просто и даже сослаться на конкретные абзацы из книги Implementing domain-driven design, а именно, то что автор пишет про сервисы. Автор книги довольно четко рассказывает почему сервисы не должны обладать состоянием.

У вас классический сервис и у вас проблема, только лишь потому, что вы впринципе неправильно подошли к проектированию вашего сервиса.

В первую очередь вам нужно спроектировать интерфейс CalculatorInterface

interface CalculatorInterface {
  public function calculate($products, $city);
}

Далее вам нужно создать две реализации этого интерфейса CdekCalculator и EmsCalculator

class CdekCalculator implements CalculatorInterface {
  public function calculate($products, $city) {
     // реализация расчета через cdek
  }
}

class EmsCalculator implements CalculatorInterface {
  public function calculate($products, $city) {
    // реализация расчета через ems
  }
}

И теперь ваш класс доставки будет выглядеть таким образом

class Delivery {
  private $calculator;

  public function __construct(CalculatorInterface $calculator) {
     $this->calculator = $calculator;
  }
  public function calculate($products, $city) {
    //тут ещё какая-то логика, которая определяет условия доставки, если она вообще возможна
    return $this->calculator->calculate($products, $city);
  }
}

Предмета спора больше нет. Вы просто передаете в класс Delivery нужную реализацию калькулятора. Код выше это псевдоязык, не php и вообще только базовая идея того, как это должно быть. У вас наверняка тут же возникнет вопрос, как вам тогда выводить все расчеты доставки в ваш UI. Но извините не могу написать за вас всё приложение.

Это базовые вещи в объектно-ориентированном программировании. Называется полиморфизм подтипов. Без этих знаний невозможно писать хороший объектно-ориентированный  код. Лучше оба придите к выводу, что вам срочно нужно почитать какие-нибудь книги об объектно-ориентированном программировании и начать с самых основ, что такое полиморфизм и в частности полиморфизм подтипов.

Вообще protected/private методы и ветвления из условных конструкций - это практически всегда показатель спагетти-кода и первый звоночек, что вы пишете процедурный код используя ООП синтаксис. Вы придете к этому выводу если будете разрабатывать через TDD, а затем сможете нагуглить ваши предположения у других программистов.
Дядя Боб говорил "The best functions are those with no parameters!". Так что свойства.