Unity 6.3
0 онлайн 77 гостей 3 в системе
Вход
Руководство по стилю C# для чистого и масштабируемого кода Глава 7 из 13 Оригинал, стр. 43

Методы

Методы

Вы понимаете, что работаете с чистым кодом, когда каждая прочитанная процедура оказывается почти в точности такой, какой вы ее ожидали увидеть. — Уорд Каннингем, создатель вики и один из основателей экстремального программирования

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

Хорошее имя метода отражает его назначение. Например, GetDistanceToTarget ясно описывает цель метода. Если в проекте используются разные единицы измерения, можно выбрать еще более точное имя GetDistanceToTargetInMeters, показывающее, что расстояние возвращается в метрах.

При создании методов пользовательских классов следуйте этим рекомендациям: — Используйте меньше аргументов. Аргументы повышают сложность метода; сократите их число, чтобы упростить чтение и тестирование. — Избегайте избыточной перегрузки. Можно создать бесконечное множество вариантов перегруженного метода. Оставьте только те, которые соответствуют реальным сценариям вызова.

Если вы все же перегружаете метод, во избежание путаницы сделайте так, чтобы каждая перегрузка имела разное число параметров. — Избегайте побочных эффектов. Метод должен делать только то, что заявлено в его имени. По возможности не изменяйте данные вне его области действия и передавайте аргументы по значению, а не по ссылке. Если результат возвращается через out или ref, это должно быть единственной целью метода.

Для некоторых задач побочные эффекты полезны, но они могут привести к непредвиденным последствиям. Методы без побочных эффектов уменьшают вероятность неожиданного поведения.

— Вместо флага создайте отдельный метод. Не заставляйте один метод работать в двух режимах в зависимости от флага; создайте два метода с разными именами. Например, не используйте GetAngle, который по флагу возвращает градусы или радианы. Создайте GetAngleInDegrees и GetAngleInRadians. . Булев флаг в списке аргументов выглядит безобидно, но может запутать реализацию или нарушить принцип единственной ответственности.

Методы или функции? В Unity и C# принято говорить о методах, а не о функциях, поскольку метод — это функция, определенная в контексте класса или объекта. C# является объектно-ориентированным языком: его основа — классы и объекты, а методы описывают действия объектов. Функция — более общее название блока кода, который выполняет определенную задачу. В процедурных языках функции могут существовать независимо, но в объектно-ориентированных языках, таких как C#, они инкапсулированы в классах и называются методами.

Методы расширения Методы расширения позволяют добавлять функциональность в классы, в том числе закрытые для наследования, и дают аккуратный способ расширять API UnityEngine. Чтобы создать метод расширения, объявите статический метод и поставьте ключевое слово this перед первым параметром — типом, который требуется расширить. Предположим, нужно создать метод ResetTransformation, который удаляет масштабирование, поворот и смещение объекта GameObject.

Можно создать статический метод, указав первым параметром Transform и поставив перед ним ключевое слово this:

C#
// ПРИМЕР: определение метода расширения

public static class TransformExtensions {
    public static void ResetTransformation(this Transform transform) {
        transform.position = Vector3.zero;
        transform.localRotation = Quaternion.identity;
        transform.localScale = Vector3.one;
    }
}

Затем, когда понадобится применить этот метод, вызовите ResetTransformation. Класс ResetOnStart вызывает его для текущего Transform в методе Start.

C#
// ПРИМЕР: вызов метода расширения

public class ResetOnStart : MonoBehaviour {
    void Start() { transform.ResetTransformation(); }
}

Чтобы упорядочить код, определяйте методы расширения в статических классах. Например, методы, расширяющие Transform, можно поместить в класс TransformExtensions, методы для Vector3 — в Vector3Extensions и так далее. Методы расширения позволяют создавать множество полезных утилит без дополнительных компонентов MonoBehaviour. Подробнее см. материал Unity Learn «Методы расширения»: он поможет пополнить арсенал приемов разработчика игр.

Принцип DRY: не повторяйтесь В книге «Программист-прагматик» Энди Хант и Дейв Томас сформулировали принцип DRY — «не повторяйтесь». Этот известный принцип разработки программного обеспечения рекомендует избегать дублирования и повторения логики. Так проще исправлять ошибки и снижать стоимость сопровождения. Если вы следуете принципу единственной ответственности, при изменении класса или метода не придется править несвязанный код. Устранив логическую ошибку в коде, соответствующем принципу DRY, вы исправите ее сразу во всех местах.

Противоположность DRY — WET («нам нравится печатать» или «пишите все дважды»). Код считается WET, если в нем есть ненужные повторения. Представьте две системы ParticleSystem (explosionA и explosionB) и два объекта AudioClip (soundA и soundB). Каждая система ParticleSystem должна воспроизводиться вместе со своим звуком. Для этого можно написать простые методы, подобные следующим.

C#
// ПРИМЕР: ПИШЕМ ВСЕ ДВАЖДЫ

private void PlayExplosionA(Vector3 hitPosition) {
    explosionA.transform.position = hitPosition;
    explosionA.Stop();
    explosionA.Play();
    AudioSource.PlayClipAtPoint(soundA, hitPosition);
}
private void PlayExplosionB(Vector3 hitPosition) {
    explosionB.transform.position = hitPosition;
    explosionB.Stop();
    explosionB.Play();
    AudioSource.PlayClipAtPoint(soundB, hitPosition);
}

Каждый метод принимает позицию типа Vector3, перемещает туда ParticleSystem и запускает эффект. Сначала система частиц останавливается на случай, если она уже воспроизводится, а затем симуляция запускается заново. После этого статический метод AudioSource.PlayClipAtPoint создает звуковой эффект в той же точке. Один метод фактически является копией другого с небольшими заменами. Такой код работает, но для каждого нового взрыва придется создавать еще один метод с той же логикой. Вместо этого выполните рефакторинг и сведите логику к одному методу PlayFXWithSound:

C#
// ПРИМЕР: версия после рефакторинга по принципу DRY

private void PlayFXWithSound(ParticleSystem particle, AudioClip clip, Vector3 hitPosition) {
    particle.transform.position = hitPosition;
    particle.Stop();
    particle.Play();

AudioSource.PlayClipAtPoint(clip, hitPosition); } Добавляя новые объекты ParticleSystem и AudioClip, вы сможете по-прежнему воспроизводить их совместно тем же методом. Обратите внимание: дублировать код можно и без нарушения принципа DRY. Главное — не дублировать логику. Здесь основная функциональность вынесена в метод PlayFXWithSound. Если логику потребуется изменить, достаточно исправить один метод, а не оба — PlayExplosionA и PlayExplosionB.