Je crée un modèle d'objet pour un appareil qui a plusieurs canaux. Les noms utilisés entre le client et moi sont Channel
et ChannelSet
. ("Ensemble" n'est pas sémantiquement précis, car il est ordonné et un ensemble approprié ne l'est pas. Mais c'est un problème pour une autre période.)
J'utilise C #. Voici un exemple d'utilisation de 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
Tout est dandy. Cependant, les clients ne sont pas des programmeurs et ils seront absolument déroutés par l'indexation zéro - le premier canal est le canal 1 pour eux. Mais, par souci de cohérence avec C #, je veux garder l' ChannelSet
index à partir de zéro .
Cela est sûr de provoquer des déconnexions entre mon équipe de développement et les clients lorsqu'ils interagissent. Mais pire, toute incohérence dans la façon dont cela est géré dans la base de code est un problème potentiel. Par exemple, voici un écran d'interface utilisateur où l'utilisateur final ( qui pense en termes de 1 indexation ) édite le canal 13:
Ce Save
bouton va finalement aboutir à du code. Si ChannelSet
est 1 indexé:
channels.GetChannel(13).SomeProperty = newValue; // notice: 13
ou ceci s'il est indexé zéro:
channels.GetChannel(12).SomeProperty = newValue; // notice: 12
Je ne sais pas vraiment comment gérer cela. Je pense que c'est une bonne pratique de garder une liste ordonnée et indexée d'entiers (les ChannelSet
) cohérente avec toutes les autres interfaces de tableau et de liste dans l'univers C # (par indexation zéro ChannelSet
). Mais alors, chaque morceau de code entre l'interface utilisateur et le backend aura besoin d'une traduction (soustrayez de 1), et nous savons tous à quel point les erreurs insidieuses et courantes de coup par coup sont déjà.
Alors, une décision comme celle-ci vous a-t-elle déjà mordu? Dois-je zéro index ou un index?
la source
Réponses:
On a l'impression que vous confondez l'identifiant pour le
Channel
avec sa position dans aChannelSet
. Voici ma visualisation de l'apparence actuelle de votre code / commentaires:Il semble que vous ayez décidé que parce que les
Channel
s dans unChannelSet
sont identifiés par des nombres qui ont une limite supérieure et inférieure, ils doivent être des index et donc comme il est basé sur C #, 0. Si la façon naturelle de faire référence à chacun des canaux est un nombre entre 1 et X, faites-leur référence par un nombre entre 1 et X. N'essayez pas de les forcer à être des index.Si vous voulez vraiment fournir un moyen d'y accéder par un index basé sur 0 (quel avantage cela donne-t-il à votre utilisateur final ou aux développeurs qui consomment le code?), Alors implémentez un indexeur :
la source
Affichez l'interface utilisateur avec l'index 1, utilisez l'index 0 dans le code.
Cela dit, j'ai travaillé avec des périphériques audio comme celui-ci et utilisé l'index 1 pour les canaux et conçu le code pour ne jamais utiliser "Index" ou indexeurs pour éviter la frustration. Certains programmeurs se plaignaient toujours, alors nous l'avons changé. Ensuite, d'autres programmeurs se sont plaints.
Choisissez-en un et respectez-le. Il y a de plus gros problèmes à résoudre dans le grand schéma consistant à sortir les logiciels.
la source
Option Base
c'était idiot, j'ai aimé la fonctionnalité offerte par certains langages permettant aux tableaux de spécifier individuellement des limites inférieures arbitraires. Si l'on a un tableau de données par année, par exemple, au-delà de la possibilité d'avoir un tableau dimensionné[firstYear..lastYear]
peut être plus agréable que d'avoir toujours accès à l'élément[thisYear-firstYear]
.Utilise les deux.
Ne mélangez pas l'interface utilisateur avec votre code principal. En interne (en tant que bibliothèque), vous devez coder "sans savoir" comment chaque élément du tableau sera appelé par l'utilisateur final. Utilisez les tableaux et collections «naturels» indexés sur 0.
La partie du programme qui joint les données à l'interface utilisateur, la vue, doit veiller à traduire correctement les données entre le modèle mental de l'utilisateur et la «bibliothèque» qui effectue le travail réel.
Pourquoi est-ce mieux?
la source
Vous pouvez voir la collection sous deux angles différents.
(1) Il s'agit, en premier lieu, d'une collection séquentielle régulière , comme un tableau ou une liste. L'index de
0
est donc évidemment la bonne solution, suivant la convention. Vous allouez suffisamment d'entrées et mappez le numéro de canal aux indices, ce qui est trivial (il suffit de soustraire1
).(2) Votre collection est essentiellement un mappage entre les identifiants de canal et les objets d'informations de canal. Il se trouve que les identifiants de canal sont une plage séquentielle d'entiers; demain ce pourrait être quelque chose comme
[1, 2, 3, 3a, 4, 4.1, 6, 8, 13]
. Vous utilisez cet ensemble ordonné comme clés de mappage.Choisissez l'une des approches, documentez-la et respectez-la. Du point de vue de la flexibilité, j'irais avec (2), car la représentation du numéro de canal (au moins le nom affiché) est relativement susceptible de changer à l'avenir.
la source
channels[int]
) sera zéro entiers indexés, et les accesseurs GetGetChannelByFrequency
,GetChannelByName
,GetChannelByNumber
sera flexible.Dictionary
ouSortedDictionary
.operator [] (int index)
devrait être basé sur 0, alorsoperator [] (IOrdered index)
que non. (Toutes mes excuses pour la syntaxe approximative, mon C # est très rouillé.)[]
dans un langage qui utilise cette surcharge pour la recherche par clé arbitraire, les programmeurs ne doivent pas supposer que les clés commencent à partir0
et sont contiguës, et devraient mettre fin à cette habitude. Ils peuvent commencer par0
, ou1
, ou1000
, ou la chaîne"Channel1"
, c'est tout l'intérêt d'utiliser l'opérateur[]
avec des clés arbitraires. OTOH, si c'était C et que quelqu'un disait "devrais-je laisser un élément0
dans un tableau inutilisé pour commencer à partir de1
" alors je ne dirais pas "évidemment, oui", ce serait un appel serré mais je m'appuierais sur "non".Tout le monde et son chien utilisent des index à base zéro. L'utilisation d'index à base unique dans votre application vous causera des problèmes de maintenance pour toujours.
Maintenant, ce que vous affichez dans une interface utilisateur, cela dépend entièrement de vous et de votre client. Affichez simplement i + 1 comme numéro de canal, ainsi que le canal #i, si cela rend votre client heureux.
Si vous exposez une classe, vous l'exposez aux programmeurs. Les personnes que vous confondez avec un index de base zéro ne sont pas des programmeurs, il y a donc une déconnexion ici.
Vous semblez vous inquiéter de la conversion entre l'interface utilisateur et le code. Si cela vous inquiète, créez une classe portant la représentation de l'interface utilisateur d'un numéro de canal. Un appel transformant le numéro 12 en représentation d'interface utilisateur "Canal 13", et un appel transformant "Canal 13" en numéro 12. Vous devez le faire de toute façon, au cas où le client changerait d'avis, il n'y a donc que deux lignes de code changer. Et cela fonctionne si le client demande des chiffres romains ou des lettres de A à Z.
la source
Vous mélangez deux concepts: l'indexation et l'identité. Ils ne sont pas la même chose et ne doivent pas être confondus.
Quel est le but de l'indexation? Accès aléatoire rapide. Si les performances ne sont pas un problème, et compte tenu de votre description, ce n'est pas le cas, alors l'utilisation d'une collection qui a un index est inutile et probablement accidentelle.
Si vous (ou votre équipe) êtes confus par l'index par rapport à l'identité, vous pouvez résoudre ce problème en n'ayant pas d'index. Utilisez un dictionnaire ou un énumérable et obtenez le canal par valeur.
Le premier est plus clair, le second est plus court - ils peuvent ou non être traduits dans le même IL, mais de toute façon, étant donné que vous l'utilisez pour une liste déroulante, cela devrait être assez rapide.
la source
Vous exposez une interface à travers votre
ChannelSet
classe avec laquelle vous attendez de vos utilisateurs qu'ils interagissent. Je le rendrais aussi naturel pour eux que possible. Si vous pensez que vos utilisateurs commenceront à compter à partir de 1 au lieu de 0, exposez cette classe et son utilisation en gardant cette attente à l'esprit.la source
L'indexation basée sur 0 était populaire et défendue par des personnes importantes, car la déclaration indique la taille de l'objet.
Avec les ordinateurs modernes, avec les ordinateurs que vos utilisateurs utiliseront, la taille de l'objet est-elle importante?
Si votre langauge (C #) ne prend pas en charge une manière propre de déclarer le premier et le dernier élément d'un tableau, vous pouvez simplement déclarer un tableau plus grand et utiliser des constantes déclarées (ou une variable dynamique) pour identifier le début et la fin logique de la zone active de la matrice.
Pour les objets d'interface utilisateur, vous pouvez presque certainement vous permettre d'utiliser un objet dictionnaire pour votre mappage (si vous avez 10 millions d'objets, vous avez un problème d'interface utilisateur) et si le meilleur objet dictionnaire se révèle être une liste avec gaspillé d'espace à chaque extrémité, vous n'avez rien perdu d'important.
la source