Я создаю объектную модель для устройства, которое имеет несколько каналов. Существительные, используемые между клиентом и мной, Channel
и ChannelSet
. («Набор» не является семантически точным, потому что он упорядочен, а правильный набор - нет. Но это проблема для другого времени.)
Я использую C #. Вот пример использования ChannelSet
:
// load a 5-channel ChannelSet
ChannelSet channels = ChannelSetFactory.FromFile("some_5_channel_set.json");
Console.Write(channels.Count);
// -> 5
foreach (Channel channel in channels) {
Console.Write(channel.Average);
Console.Write(", ");
}
// -> 0.3, 0.3, 0.9, 0.1, 0.2
Все денди. Однако клиенты не являются программистами, и их абсолютно смущает нулевая индексация - первый канал - это канал 1 для них. Но для согласованности с C # я хочу сохранить ChannelSet
индексированное значение с нуля .
Это обязательно вызовет некоторые разногласия между моей командой разработчиков и клиентами, когда они взаимодействуют. Но что еще хуже, любое несоответствие в том, как это обрабатывается в кодовой базе, является потенциальной проблемой. Например, вот экран пользовательского интерфейса, где конечный пользователь ( который думает с точки зрения 1 индексации ) редактирует канал 13:
Эта Save
кнопка в конечном итоге приведет к некоторому коду. Если ChannelSet
индексируется 1:
channels.GetChannel(13).SomeProperty = newValue; // notice: 13
или это, если оно проиндексировано нулями:
channels.GetChannel(12).SomeProperty = newValue; // notice: 12
Я не совсем уверен, как справиться с этим. Я чувствую, что это хорошая практика - поддерживать упорядоченный список с целочисленной индексацией ( ChannelSet
), совместимый со всеми остальными интерфейсами массивов и списков во вселенной C # (путем нулевой индексации ChannelSet
). Но тогда каждому фрагменту кода между пользовательским интерфейсом и серверной частью потребуется перевод (вычитание на 1), и мы все знаем, насколько коварными и распространенными ошибками уже являются ошибки.
Значит, такое решение тебя когда-нибудь укусило? Должен ли я обнулить индекс или один индекс?
источник
Ответы:
Такое ощущение, что вы объединяете Идентификатор
Channel
с его позицией внутриChannelSet
. Следующее - моя визуализация того, как ваш код / комментарии будут выглядеть в данный момент:Такое ощущение, что вы решили, что, поскольку
Channel
s внутри aChannelSet
идентифицируются числами, имеющими верхнюю и нижнюю границу, они должны быть индексами и, следовательно, основаны на C #, 0. Если естественным способом обращения к каждому из каналов является число от 1 до X, обращайтесь к ним с помощью номера от 1 до X. Не пытайтесь заставить их быть индексами.Если вы действительно хотите предоставить способ доступа к ним по индексу, основанному на 0 (какое преимущество это даст вашему конечному пользователю или разработчикам, использующим код?), Тогда внедрите индексатор :
источник
Показать пользовательский интерфейс с индексом 1, используйте индекс 0 в коде.
Тем не менее, я работал с такими аудиоустройствами и использовал индекс 1 для каналов и разработал код, который никогда не будет использовать «Индекс» или индексаторы, чтобы избежать разочарований. Некоторые программисты все еще жаловались, поэтому мы изменили это. Тогда другие программисты пожаловались.
Просто выберите один и придерживайтесь его. Есть большие проблемы, которые нужно решить в великой схеме распространения программного обеспечения.
источник
Option Base
, что это глупо, мне понравилась особенность некоторых языков, позволяющая массивам индивидуально указывать произвольные нижние границы. Например, если у вас есть массив данных по годам, то помимо определения размера массива[firstYear..lastYear]
может быть приятнее, чем иметь постоянный доступ к элементу[thisYear-firstYear]
.Используйте оба.
Не смешивайте пользовательский интерфейс с вашим основным кодом. Внутренне (в виде библиотеки) вы должны кодировать «не зная», как каждый элемент в массиве будет вызываться конечным пользователем. Используйте «естественные» 0-индексированные массивы и коллекции.
Часть программы, которая соединяет данные с пользовательским интерфейсом, представление, должна заботиться о том, чтобы правильно преобразовать данные между Ментальной моделью пользователя и «библиотекой», которая выполняет фактическую работу.
Почему это лучше?
источник
Вы можете увидеть коллекцию с двух разных точек зрения.
(1) Это, во-первых, регулярная последовательная коллекция , такая как массив или список. Индекс из
0
, очевидно, является правильным решением в соответствии с соглашением. Вы выделяете достаточно записей и сопоставляете номер канала с индексами, что является тривиальным (просто вычитаете1
).(2) Ваша коллекция - это, по сути, отображение между идентификаторами канала и информационными объектами канала. Просто бывает, что идентификаторы каналов - это последовательный диапазон целых чисел; завтра это может быть что-то вроде
[1, 2, 3, 3a, 4, 4.1, 6, 8, 13]
. Вы используете этот упорядоченный набор в качестве ключей сопоставления.Выберите один из подходов, задокументируйте его и придерживайтесь его. С точки зрения гибкости, я бы пошел с (2), потому что представление номера канала (по крайней мере, отображаемое имя), скорее всего, изменится в будущем.
источник
channels[int]
) будет нулевым индексированные целыми числами, а ГЭТ аксессоровGetChannelByFrequency
,GetChannelByName
,GetChannelByNumber
будет гибким.Dictionary
илиSortedDictionary
.operator [] (int index)
должен быть 0, аoperator [] (IOrdered index)
не будет. (Извиняюсь за приблизительный синтаксис, мой C # очень ржавый.)[]
язык, который использует эту перегрузку для поиска по произвольному ключу, программисты не должны предполагать, что ключи начинаются с0
и являются смежными, и должны резко бросить эту привычку. Они могут начинаться с0
, или1
, или1000
, или со строки"Channel1"
, вот и весь смысл использования оператора[]
с произвольными ключами. OTOH, если бы это был C, и кто-то говорил: «Должен ли я оставить элемент0
в массиве неиспользуемым, чтобы начать с1
», тогда я бы не сказал «очевидно, да», это был бы закрытый вызов, но я бы склонялся к «нет».Все и их собака используют нулевые индексы. Использование индексов на основе одного в вашем приложении навсегда вызовет проблемы с обслуживанием.
Теперь то, что вы отображаете в пользовательском интерфейсе, полностью зависит от вас и вашего клиента. Просто отобразите номер канала i + 1 вместе с номером канала #i, если это делает вашего клиента счастливым.
Если вы выставляете класс, то вы выставляете его программистам. Люди, которых смущает индекс, начинающийся с нуля, не являются программистами, поэтому здесь есть разрыв.
Вы, кажется, беспокоитесь о преобразовании между пользовательским интерфейсом и кодом. Если вас это беспокоит, создайте класс, содержащий представление интерфейса пользователя для номера канала. Один вызов, превращающий номер 12 в представление интерфейса пользователя «Канал 13», и один вызов, превращающий «Канал 13» в число 12. В любом случае, вы должны сделать это на тот случай, если клиент передумает, поэтому есть только две строки кода. изменить. И это работает, если клиент запрашивает римские цифры или буквы от А до Я.
источник
Вы смешиваете две концепции: индексация и идентификация. Они не одно и то же, и их не следует путать.
Какова цель индексации? Быстрый произвольный доступ. Если производительность не является проблемой, и, учитывая ваше описание, это не так, то использование коллекции с индексом не является необходимым и, вероятно, случайным.
Если вы (или ваша команда) смущены тем, что индекс против идентификатора, вы можете решить эту проблему, не имея индекса. Используйте словарь или перечислимый и получите канал по значению.
Первый более понятен, второй короче - они могут или не могут быть переведены в один и тот же IL, но в любом случае, если вы используете это для раскрывающегося списка, это должно быть достаточно быстро.
источник
Вы открываете интерфейс через свой
ChannelSet
класс, с которым вы ожидаете взаимодействия ваших пользователей. Я бы сделал так, чтобы они могли использовать их настолько естественно, насколько это возможно. Если вы ожидаете, что ваши пользователи начнут считать с 1 вместо 0, представьте этот класс и его использование с учетом этого ожидания.источник
Индексирование на основе 0 было популярным и защищалось важными людьми, потому что объявление показывает размер объекта.
На современных компьютерах, на которых будут работать ваши пользователи, важен ли размер объекта?
Если ваш язык (C #) не поддерживает чистый способ объявления первого и последнего элемента массива, вы можете просто объявить больший массив и использовать объявленные константы (или динамическую переменную) для идентификации в логическом начале и конце активная область массива.
Для объектов пользовательского интерфейса вы почти наверняка можете позволить себе использовать объект словаря для отображения (если у вас есть 10 миллионов объектов, у вас есть проблема пользовательского интерфейса), и если лучшим объектом словаря окажется список с потраченное впустую пространство с обеих сторон, вы не потеряли ничего важного.
источник