Возможное решение целей, не обязательно заголовок вопроса:
Вместо того, чтобы подать специальное предложение всем, служите ему случайным наборам IP-адресов за один раз. Например, разделите пространство IP в 256 уникальных блоков, и в time=0, только позвольте людям с IP-адресами в первом блоке, и в time=5 секунды, позвольте людям от первого блока и второго блока..., пока прошлый временной интервал не наступает, и позвольте всем видеть соглашение. Одна идея рандомизировать его состояла бы в том, чтобы взять младшие значащие биты md5/sha их IP плюс немного соли на основе соглашения.
Это позволило бы сценаристам все еще иметь преимущество в том, что у них есть почти нулевое время отклика и сила при наличии нескольких IP-адресов, но это означало бы, что данный бот не будет иметь преимущество перед другим клиентом, который был 'более удачливым', чем они из-за их IP-адреса.
Объединение этого с некоторыми из других идей походит на хорошую идею.
ИМХО, если вам нужны операторы if / switch, лучше перегрузить. Дженерики должны использоваться там, где реализация не зависит от конкретного типа, чтобы его можно было повторно использовать.
Итак, как общее правило:
Запах кода.
Если у вас есть « какой-то if / switch », это запах кода, который просто кричит о полиморфизме . Это предполагает, что дженерики не решение этой проблемы. Обобщения следует использовать, когда код не зависит от конкретных типов , которые вы ему передаете.
Посмотрите это видео Google Tech Talks: « The Clean Code Talks - Наследование, полиморфизм и Тестирование ». Он конкретно касается того, о чем вы говорите.
Шаблон, который вы описываете, где использование универсальных шаблонов приводит к кучке операторов ifs / switch, является анти-шаблоном.
Одним из решений этого является реализация шаблона стратегии, что позволяет использовать дженерики, но в то же время изолировать проблемы метода Parse от знания того, как действовать в каждом отдельном случае.
Пример:
class SomeParser
{
void Parse<T>(ParseStrategy<T> parseStrategy, T data)
{
//do some prep
parseStrategy.Parse(data);
//do something with the result;
}
}
class ParseStrategy<T>
{
abstract void Parse(T data);
}
class StringParser: ParseStrategy<String>
{
override void Parse(String data)
{
//do your String parsing.
}
}
class IntParser: ParseStrategy<int>
{
override void Parse(int data)
{
//do your int parsing.
}
}
//use it like so
[Test]
public void ParseTest()
{
var someParser = new SomeParser();
someParser.Parse(new StringParser(), "WHAT WILL THIS PARSE TO");
}
и тогда вы сможете передать любую из разработанных вами стратегий. Это позволит вам правильно изолировать ваши проблемы по нескольким классам и не нарушать SRP (принцип единой ответственности.
Хотя здесь нет единого правила, подходящего для всех, универсальные шаблоны следует использовать, когда конкретный тип не имеет значения . Это не значит, что вы не можете ограничить тип, но этот конкретный тип на самом деле не имеет значения. В этом случае метод синтаксического анализа полностью зависит от каждого типа (и отличается для каждого типа). Дженерики здесь не кажутся хорошим решением.
Здесь есть одна проблема - если вам требуются операторы if / switch для работы универсальных шаблонов, у вас, вероятно, более серьезная проблема. В этой ситуации наиболее вероятно, что общий аргумент не будет работать (правильно) для КАЖДОГО типа, а только для фиксированного набора типов, с которыми вы работаете. В этом случае гораздо лучше предоставить перегрузки для индивидуальной обработки определенных типов.
У этого есть много преимуществ:
Если ваш аргумент МОЖЕТ работать с любым типом, это становится менее очевидным. В этом случае я бы все равно подумал о включении перегрузок, а также общего резервного метода для типов. Это обеспечивает повышение производительности, когда вы передаете методу "ожидаемый" тип, но вы все равно можете работать с другими, неожиданными типами.
Если ваш аргумент МОЖЕТ работать с любого типа это становится менее ясным. В этом случае я бы все равно подумал о включении перегрузок, а также общего резервного метода для типов. Это обеспечивает повышение производительности, когда вы передаете методу "ожидаемый" тип, но вы все равно можете работать с другими, неожиданными типами.
Если ваш аргумент МОЖЕТ работать с любого типа это становится менее ясным. В этом случае я бы все равно подумал о включении перегрузок, а также общего резервного метода для типов. Это обеспечивает повышение производительности, когда вы передаете методу "ожидаемый" тип, но вы все равно можете работать с другими, неожиданными типами.
re пользователь не может передать недопустимый аргументЕсли ваш аргумент МОЖЕТ работать с любым типом, это становится менее очевидным. В этом случае я бы все равно подумал о включении перегрузок, а также общего резервного метода для типов. Это обеспечивает повышение производительности, когда вы передаете методу "ожидаемый" тип, но вы все равно можете работать с другими, неожиданными типами.
re пользователь не может передать недопустимый аргументЕсли ваш аргумент МОЖЕТ работать с любым типом, это становится менее очевидным. В этом случае я бы часто все же рассматривал возможность включения перегрузок, а также общего резервного метода для типов. Это обеспечивает повышение производительности, когда вы передаете методу "ожидаемый" тип, но вы все равно можете работать с другими, неожиданными типами.
и не так очевидно для начинающих пользователейЕсли ваш аргумент МОЖЕТ работать с любым типом это становится менее очевидным. В этом случае я бы часто все же рассматривал возможность включения перегрузок, а также общего резервного метода для типов. Это обеспечивает повышение производительности, когда вы передаете методу "ожидаемый" тип, но вы все равно можете работать с другими, неожиданными типами.
и не так очевидно для начинающих пользователейЕсли ваш аргумент МОЖЕТ работать с любым типом это становится менее очевидным. В этом случае я бы все равно подумал о включении перегрузок, а также общего резервного метода для типов. Это обеспечивает повышение производительности, когда вы передаете методу "ожидаемый" тип, но вы все равно можете работать с другими, неожиданными типами.
плюс общий резервный метод для типов. Это обеспечивает повышение производительности, когда вы передаете методу «ожидаемый» тип, но вы все еще можете работать с другими, неожиданными типами. плюс общий резервный метод для типов. Это обеспечивает повышение производительности, когда вы передаете методу "ожидаемый" тип, но вы все равно можете работать с другими, неожиданными типами.