TL; DR: не используйте логические аргументы.
Смотрите ниже, почему они плохие и как их заменить (жирным шрифтом).
Логические аргументы очень трудно читать, и, следовательно, их трудно поддерживать. Основная проблема заключается в том, что цель обычно ясна, когда вы читаете сигнатуру метода, в которой указан аргумент. Однако наименование параметра обычно не требуется в большинстве языков. Таким образом, у вас будут анти-паттерны, например, RSACryptoServiceProvider#encrypt(Byte[], Boolean)
где логический параметр определяет, какой тип шифрования будет использоваться в функции.
Таким образом, вы получите звонок как:
rsaProvider.encrypt(data, true);
где читатель должен искать сигнатуру метода просто, чтобы определить, что на true
самом деле может означать ад . Передача целого числа, конечно, так же плоха:
rsaProvider.encrypt(data, 1);
скажет вам столько же, а точнее, так же мало. Даже если вы определите константы, которые будут использоваться для целого числа, пользователи функции могут просто игнорировать их и продолжать использовать литеральные значения.
Лучший способ решить эту проблему - использовать перечисление . Если вам нужно передать перечисление RSAPadding
с двумя значениями: OAEP
или PKCS1_V1_5
тогда вы сразу сможете прочитать код:
rsaProvider.encrypt(data, RSAPadding.OAEP);
Логическое значение может иметь только два значения. Это означает, что если у вас есть третий вариант, вам придется реорганизовать свою подпись. Обычно это не может быть легко выполнено, если проблема заключается в обратной совместимости, поэтому вам придется расширять любой открытый класс другим открытым методом. Это то, что Microsoft наконец сделала, когда они представили, RSACryptoServiceProvider#encrypt(Byte[], RSAEncryptionPadding)
где они использовали перечисление (или, по крайней мере, класс, имитирующий перечисление) вместо логического значения.
Может быть даже проще использовать полный объект или интерфейс в качестве параметра, если сам параметр должен быть параметризован. В приведенном выше примере само дополнение OAEP может быть параметризовано с использованием значения хеш-функции для внутреннего использования. Обратите внимание, что теперь существует 6 алгоритмов хеширования SHA-2 и 4 алгоритма хеширования SHA-3, поэтому число значений перечисления может взорваться, если вы используете только одно перечисление, а не параметры (возможно, это следующее, что Microsoft собирается выяснить ).
Логические параметры также могут указывать на то, что метод или класс не спроектированы должным образом. Как и в примере выше: любая криптографическая библиотека, кроме .NET, вообще не использует флаг дополнения в сигнатуре метода.
Почти все гуру программного обеспечения, которые мне нравятся, предостерегают от логических аргументов. Например, Джошуа Блох предостерегает их в высоко оцененной книге «Эффективная Ява». В общем, они просто не должны использоваться. Можно утверждать, что их можно использовать, если есть один параметр, который легко понять. Но даже тогда: Bit.set(boolean)
вероятно, лучше реализовать двумя способами : Bit.set()
и Bit.unset()
.
Если вы не можете напрямую изменить код, вы можете определить константы, чтобы хотя бы сделать их более читабельными:
const boolean ENCRYPT = true;
const boolean DECRYPT = false;
...
cipher.init(key, ENCRYPT);
гораздо более читабельно, чем:
cipher.init(key, true);
даже если бы вы предпочли:
cipher.initForEncryption(key);
cipher.initForDecryption(key);
вместо.