Мне кажется, что часть трудностей здесь заключается в выборе хорошего описательного имени, которое охватывает все, что делает метод.Естественно, проблема в том, что иногда у вас есть много сложной логики, которую вы не можете легко описать простым именем.
В случае, представленном в вашем примере кода, у меня возникнет соблазн упростить имясам метод к чему-то более обобщенному:
Receipt Transaction(long amount, long cardNumber)
{
buy(amount);
accumulatePoints(cardNumber);
return generateReceipt();
}
Так что насчет этой логической проблемы, которую я упомянул?Это само по себе сводится к тому, очень ли ваш метод очень фиксирован в том, что он делает.Если можно завершить транзакцию только с использованием последовательности Buy-> Points-> Receipt, то работает более простое имя, но также более описательное имя, и разумным вариантом может быть свободный интерфейс.
А как насчет тех случаев, когда у клиента нет карты вознаграждения или он не хочет получать квитанцию?Как насчет тех ситуаций, когда несколько предметов могут быть куплены за одну транзакцию - если, конечно, метод покупки может представлять предмет покупки, а не просто сумму, рассчитанную в другом месте?Как только вы начинаете вводить вопросы / варианты в последовательность, дизайн становится немного менее очевидным, а наименование становится намного сложнее.Вы, конечно, не захотите использовать сумасшедшее длинное имя, например:
BuyAndAddPointsIfTheCustomerHasACardAndReturnAReceiptIfTheCustomerAsksForIt(...)
Конечно, оно точно говорит вам, что оно делает, но также выдвигает на первый план потенциальную проблему в том, что метод может быть ответственным за слишком многовещи, или что он может скрывать более сложный запах кода за одним из методов, которые он вызывает.Аналогично, простое имя метода, такое как «Транзакция» , может упрощать сложную проблему, которую необходимо лучше понять.
Свободный интерфейс может быть очень полезен при условии, что он помогает разработчику принимать разумные решения о том, как применять вызываемые беглые методы.Если вызывающая последовательность важна, вам нужно ограничить возвращаемые типы следующими вариантами в последовательности.Если вызывающая последовательность менее важна, то вы можете использовать тип возврата с более обобщенным интерфейсом, который позволяет выбирать методы для вызова в любой последовательности.
Относительно того, использовать ли свободный интерфейс ввсе, я не думаю, что это должно решаться просто как средство разложения трудно назвать методы.Вы делаете выбор дизайна, с которым вам придется жить в течение всего срока службы продукта, и с точки зрения обслуживания я обнаружил, что плавные интерфейсы могут усложнить визуализацию проекта, а также его организацию и поддержку в вашем проекте.код.В конечном итоге вам нужно решить, можете ли вы с этим смириться в качестве компромисса с теми преимуществами, которые он вам дает.Для меня я обычно начинаю с вопроса, являются ли комбинации вариантов использования фиксированными и простыми или они относительно бесконечны.Если последнее, свободный интерфейс может помочь сохранить ваш код чище и проще в использовании в нескольких сценариях.Я также рассмотрел бы, принадлежит ли код более обобщенному уровню, такому как API, например, где свободный интерфейс может работать хорошо, или что-то более специализированное.