Sugerir traducción
 
Otros han sugerido:

progress indicator
No hay más sugerencias.
MSDN Magazine > Inicio > Todos los números > 2008 > Noviembre >  Ejecución de prueba: determinación grupo de pru...
Ver contenido:  en paraleloVer contenido: en paralelo
La información aquí ofrecida es contenido traducido automáticamente que los miembros de la comunidad pueden editar. Quienes deseen contribuir a mejorar la traducción, pueden hacer clic en el vínculo “editar” asociado a cualquiera de los siguientes enunciados.
Test Run
Group Determination In Software Testing
Dr. James McCaffrey
Code download available at: TestRun2008_11.exe (153 KB)
Browse the Code Online
Consider the general problem of determining a best option from a list of choices, where the decision-making process is performed by a group of people rather than by a single person or by a purely quantitative technique. Examples of this type of activity include the residents of a state voting for the state's governor from a list of candidates and the board of directors of a large company determining which of several smaller companies to target for acquisition. In essence, the group must rank its options in some way so that the best one can be determined.
Group determination of a best alternative occurs in software development and testing, too. For example, consider a group of beta users choosing the best user interface from a set of prototypes. Or imagine the members of an open source project voting for a policy.
I have observed that the practical techniques for performing group determination of a best alternative, and the potential pitfalls of the process, are not widely known in the software testing community. There are dozens of group analysis techniques. In this month's column I describe five of the most common methods used for group determination of a best alternative in a software testing environment: the pure plurality technique, the majority runoff technique, the Borda count system, the Condorcet method, and the Schulze method.
All of these analysis techniques are well-known outside of software engineering and have been extensively researched. I describe each technique with an emphasis on its application to software testing. I think you'll find knowledge of group analysis techniques a valuable addition to your toolkit.
Situations where exactly one of a set of alternatives must be selected by a group of people occur in a wide range of problem domains. Different problem domains tend to use different terminology. In sociology, for example, the study of this type of problem is usually called social choice theory and typically uses terms such as options and evaluators. In political science, analysis of these problems is often called voting theory and uses the terms candidates and voters. In mathematics, group determination of a best alternative is frequently considered a sub-branch of decision theory. I will use a mixture of terminologies in my discussion because there is no specific terminology set used when these techniques are applied to a software development and testing environment.
The techniques I describe in this column apply to a fairly narrow range of problems and do not apply strictly to quantitative scenarios where a best choice is clearly defined. As you'll see, when a group of people select a "best" alternative, the meaning of best is defined by the technique used. Also, the techniques I describe here do not apply to collaboration scenarios where a group of people use discussion and negotiation to arrive at a consensus decision.

Pure Plurality and Majority Runoff
Let's begin the discussion of group determination of a best alternative with a look at the simplest and most common technique—but let me warn you that this is not the best approach in many testing situations. Suppose you are developing an enterprise software application for your company's internal use and you create four quite different user interface prototypes. Although you could ask a single person to evaluate the different prototypes, in many cases a better approach is to ask a group of people to rank the four different designs.
It turns out that the process of performing a group evaluation and interpreting the results is somewhat trickier than you might expect. The simplest possible group evaluation technique is to submit the choices to the evaluators and allow them to choose, or vote for, just one alternative. The alternative that receives the most votes is declared the winner. This technique is often called the pure plurality rule.
So, suppose you submit your four different prototypes (let's call them A, B, C, and D) to 10 evaluators and ask each person to choose the best prototype. And suppose the results are: Prototype A is best according to 4 people, prototype B is ranked best by 3 people, prototype C is chosen by 2 people, and prototype D is selected best by 1 person. Therefore, you select prototype A for further development.
There are several problems with this. Suppose that while your evaluators are looking at your four prototypes, they either implicitly or explicitly rank each choice, as shown in Figure 1. In this diagram, each column represents one evaluator's ranking of the prototypes.
Figure 1 Prototype Rankings for 10 Evaluators (Click the image for a larger view)
Notice that although prototype A is selected by the pure plurality rule, that prototype is evaluated as the worst by 60% of the evaluation group. Additionally, in this situation, suppose prototype A was compared in turn against each of the other prototypes. Prototype A would lose each head-to-head comparison by a 60% to 40% margin. A second, closely related problem with the pure plurality technique is that in some sense the non-winning opinions do not contribute directly to the final result.
The problems with pure plurality lead to another group selection technique usually called the majority runoff system. There are several variations on the technique, but the winner is required to gain more than 50% of the first-place votes of all votes cast.
This can be accomplished by having multiple rounds of voting or performing just a single round of voting but requiring the evaluators to rank all options. For example, if evaluators vote for the best prototype design according to the data in Figure 1, no prototype would have a majority after the first round of voting. So the list of candidates could be reduced, usually to the top two options; in this case, prototype A with four votes and prototype B with three votes.
A second round of voting then takes place. If at that time evaluators vote according to the ranking preferences in Figure 1, after the second round of voting prototype A would still receive four votes as best, but prototype B would receive six votes because the evaluators who originally selected prototypes C and D would now select prototype B.
In my experience, using multiple rounds of voting in a software development and testing environment has significant disadvantages compared to using a single round. For one thing, in some software development scenarios, multiple rounds of voting simply aren't feasible. Additionally, because it entails dealing with human beings, multiple rounds of voting can get tedious. Worse, situations can arise where a group of people are voting for losing alternatives over and over (receiving negative feedback each time) until they are forced to choose an option they don't really like. If the voters are stakeholders in the sense that they will be affected by the outcome of the voting, you may end up with disenfranchised voters at the end of a physical runoff scheme.
Instead of performing multiple actual rounds of voting where each evaluator votes for just one alternative, you can simply perform one round of voting but require evaluators to rank all candidates from best to worst. This allows you to determine voters' preferences in virtual rounds of voting.
Requiring ranking of all choices has certain disadvantages, too. The technique often isn't practical when the number of options is large (typically more than eight), simply because humans have difficulty comparing large numbers of alternatives. Also, research has shown that evaluators tend to get careless with their evaluations of options that are low on their list of preferences. And, when performing multiple physical rounds of voting, evaluators may not rank a subset of alternatives in the same order in which they rank the entire set of alternatives.
Schulze Method: Pros and Cons
The Schulze method has strengths and weaknesses. One weakness in some scenarios is that Schulze is far from intuitive. In situations where evaluators are stakeholders, the Schulze method can easily be viewed as a mysterious black box technique that produces a magic result.
The primary advantage of the Schulze method is that it has been extensively analyzed and has been shown to meet many favorable criteria. (Recall that the Borda count system can be affected by the removal of an irrelevant alternative.)
There are many voting-system criteria. For example, the monotonicity criterion can be loosely stated as the principle that a winning option cannot become a non-winner by one or more evaluators ranking that option higher. The independence of clones alternatives criterion is, stated loosely, that adding a new option that is identical to an existing option should not change the outcome of an analysis. There are many proposed voting-system criteria, and the Schulze method has been shown to meet most of these criteria as well.
An interesting exception is that the Schulze method violates what is called the participation criterion. In informal terms, it is possible to add to an existing system, new voters who prefer the current winner to some other alternative, which results in the less-preferred alternative becoming a Schulze winner.
In spite of its shortcomings, the Schulze method is often very effective, especially in situations with a large, educated group of evaluators (meaning they have knowledge of the underlying Schulze method) who are determining a policy alternative (as opposed to a product decision) and who are stakeholders in the final result. For example, the Schulze method is used by several open source groups to determine general policy decisions and to elect officers. In software testing scenarios, the Schulze method is generally the first technique I will choose to employ, and then I will use those results as a baseline against the results of other techniques.

Borda Count System
The problems with the pure plurality and majority runoff techniques led to the development of two group analysis techniques that are very common. These techniques, the Borda count system and the Condorcet pair-wise comparison method, are named after the two mathematicians who proposed the approaches in the late 1700s.
The Borda count approach is very simple and one with which you are almost certainly familiar. Suppose there are n alternatives. Each evaluator ranks the alternatives from best to worst. A top-ranked alternative is assigned a value of n-1 points, a second-ranked alternative is assigned n-2 points, and so on, down to the last-ranked alternative, which receives 0 points. The Borda count is just the sum of the point values for each alternative.
A quick example will make the ideas clear. Suppose there are four choices, A, B, C, and D. In this case, a first-place ranking is worth 3 points, second place is worth 2, third place is worth 1, and last place is worth 0 points. Figure 2 shows the results and then, underneath, the Borda counts for seven evaluators where alternative A is selected as the best option.
Figure 2 Results and Borda Counts for Seven Evaluators (Click the image for a larger view)
The Borda count technique is widely used in many problem domains, especially in sports competitions. Advantages of the Borda count technique when used in a software development and testing environment are that the technique seems to make sense intuitively, and all evaluators' opinions are taken into account.
The Borda count system has several technical problems, however. Suppose that we decide to remove option D, which was a clear loser. Common sense suggests that removing an irrelevant alternative should not affect the final result. But Figure 3 shows what happens after removing option D. Now option B becomes the best alternative instead of option A. In other words, with this set of data, removing an irrelevant alternative changes the outcome. It is even possible to construct Borda count examples where the best alternative actually becomes the worst alternative. This effect is sometimes called the Borda count winner-becomes-loser paradox.
Figure 3 Results and Borda Counts after Removing Option D (Click the image for a larger view)
There are two other closely related technical problems with the Borda count technique. The first is the pair-wise comparison problem. It is possible when using the Borda count technique to run into situations where the Borda winner would lose against every alternative in a head-to-head comparison.
Suppose, for example, that there are four alternatives and 12 evaluators (see Figure 4). Using the Borda count method, alternative A is selected as best with 25 points. However, if we look at head-to-head comparisons we notice that alternative B is preferred to all other alternatives: B is preferred to A by a score of 7 people to 5, B is preferred to C also by 7 to 5, and B is preferred to D again by 7 to 5.
Figure 4 Option B Is the Head-to-Head Winner (Click the image for a larger view)
Another problem with the Borda count technique is that it is vulnerable to evaluator manipulation. It is theoretically possible to affect the outcome of a Borda count evaluation by adding a spurious alternative that is very close (in terms of evaluators' preferences) to an existing alternative. This can have the effect of diluting close alternatives and changing the winner of the analysis. The references at the end of this column contain examples of the effect.
Despite the Borda count technique's technical flaws, the system is quite practical and often works well for policy determination by small groups in a software testing environment. Based on my experience, the Borda count technique is generally seen by voters as fair in a subjective way, and, therefore, if voters are stakeholders, the people who voted for non-winning alternatives generally accept the result of the voting and do not come away with a psychological bias against the winning alternative.
The moral of the story here is that if you do use the Borda count technique, be alert for, and check your data for, the effect of removing an irrelevant alternative, the result of pair-wise comparisons between the Borda count winner and non-winning alternatives, and the mid-process addition of a new alternative.

Condorcet Technique and Schulze Method
The Condorcet technique for collaboratively determining the best option from a set of choices was developed primarily as a reaction to the head-to-head paring problem of the Borda count method. The Condorcet method is very simple. It requires evaluators to rank all alternatives, and then a comparison of the results between each possible pair of alternatives is performed.
If one alternative beats every other alternative in a head-to-head comparison, then that one alternative is declared the Condorcet winner. If there is no Condorcet winner, then a separate, tie-breaking technique is employed. The tie-breaking technique can be any other technique; the point of the Condorcet system is that a unanimous head-to-head winner should automatically win over any alternatives chosen by any other criteria.
In practice, the Condorcet system is not often used by itself as a group evaluation technique. Instead, evaluation techniques such as pure plurality and Borda count are mathematically analyzed to see if they satisfy the Condorcet principle in all cases. So, instead of reading something like, "We decided to use the Condorcet system to evaluate our alternatives," it is more usual to read something like, "We decided to use the XYZ evaluation system, which satisfies the Condorcet principle."
One of the most interesting systems that satisfies the Condorcet principle has a variety of names, including the Schulze method, the clone-proof Schwartz sequential dropping technique, and the beat-path method. I will call this technique the Schulze method.
The Schulze method is somewhat more complicated than the other techniques I've described so far. It is similar to the Condorcet system in the sense that Schulze looks to see if one option dominates all other options. However, instead of directly using raw ranking data, as the Condorcet system does, the Schulze method performs a head-to-head comparison using an indirect measure of the strength between alternatives. This indirect measure is called the path strength.
Let's walk through an example. Take a look at Figure 5. It shows a simple demo of the Schulze method in action. The first part shows the example input. There are four options (A, B, C, and D) and 11 evaluators. The first line means that 3 evaluators rank option A better than B, which in turn is better than C, which is better than D. The Schulze method allows evaluators to rank options equal to each other and also allows evaluators to leave out alternatives altogether.
Figure 5 Schulze Method Demonstration (Click the image for a larger view)
The next part of the output shows a matrix of pair-wise defeats. This defeats matrix is computed directly from the original ranking data.
The first row of the matrix means option A is preferred by 6 voters over option B, preferred by 3 voters over option C, and by 4 voters over option D. The second row of the matrix means option B is preferred by 5 voters over option A, by 7 voters over option C, and by 8 voters over option D. The third and fourth rows, for options C and D, respectively, are interpreted similarly. The pair-wise defeats matrix has 0 values on the main diagonal because these values are comparisons between an option and itself.
At this point the Condorcet system would check this direct pair-wise data to see if there is a unanimous head-to-head winner, but the Schulze method derives an indirect measure of strength between alternatives. The next part of output is the strength of paths between each option. This is the key idea behind the Schulze method and is a very clever notion. The third row of this matrix means the strength of the path from option C to option A is 8, the strength from C to B is 4, and the strength from C to D is 10.
Explaining the idea of path strength is best done visually, as shown in Figure 6. First we express the raw ranking data as a matrix of pair-wise defeats. Next we can conceptualize the pair-wise defeats data as a directed graph.
Figure 6 Pair-Wise Defeat Data in Matrix and Graph Forms (Click the image for a larger view)
The arrow from node A to node B means that option A is preferred by 6 evaluators over option B. I do not put an arrow from node B to node A because option B is preferred by only 5 evaluators over option A, so A dominates B. In this example, all the arrows are unidirectional, but if two nodes are preferred by equal numbers of evaluators, then I can draw a bidirectional arrow.
Now consider the path between node A and node D. A beats B by 6, and B in turn beats D by 8. We chose 6, the smaller of these two values, to represent the overall strength of path between A and B. The idea is that the overall strength between two nodes that have intermediate nodes is best represented by the smallest direct node-to-node strength. Notice that we can also take a different path from A to D and say that A beats B by 6, and B beats C by 7, and C beats D by 10, and select the smallest number, 6, which would give the same result.
It turns out that computing the strength of each pair of nodes can be performed by a variation of the elegant Floyd–Warshall algorithm, as I'll explain in a moment. The standard Floyd–Warshall algorithm finds the shortest paths in a weighted, directed graph. Once the path strengths have been determined, we can determine the Schulze method winners by checking to see if there is any option where its path strength is greater than or equal to all other options' corresponding path strengths.
Figure 7 shows the matrix of path strengths that corresponds to the data in Figure 6 and demonstrates that option B is a Schulze method winner. Visually, an option is a Schulze winner if every path strength value on that option's row is greater than or equal to the corresponding value across the matrix's main diagonal.
Figure 7 Path Strength Data Used to Determine a Schulze Winner
Option B is the winner because option B's path strength to option A is 7 (but option A's path strength to B is just 6), option B's path strength to option C is 7 (but C's path strength to B is just 6), and option B's path strength to option D is 8 (but D's path strength to B is just 6). On the other hand, option D is not a Schulze winner because option D's path strength is better than option A (7 to 6), but option D's strength is worse than option C (6 to 10).

The Schulze Method in Code
In this example there is just one Schulze winner, but it is possible for there to be multiple Schulze winners. In situations like these you would have to use some form of tiebreaker. Let's go over some of the code in the program that generates the output in Figure 5 to help explain the Schulze method.
The program begins by setting up an enumeration type to represent the alternatives and a global value N to hold the actual number of alternatives:
   enum options { A, B, C, D, E, F, G, H, I, J };
   static int N; // actual number of options
Then the demo program sets up problem input as a string array:
   string[] rawData = new string[] {
           "A>B>C>D 3",
           "B>C>D>A 4",
           "C>D>A>B 2",
           "D>C>B>A 1",
           "C>A>B>D 1"
                          };
For simplicity, my demo program assumes that ties are not allowed and that all options are ranked. Doing so lets me parse the raw data strings very easily. The complete demo program is available in the code download that accompanies this column. You should be able to modify the code to allow ties and missing options, without too much trouble.
Next, my demo program scans through the rawData string array and determines and prints the number of options and the number of evaluators. Then the programs rescans the input array and creates a matrix of pair-wise defeats data using a static helper method named MakeDefeats:
int[,] defeats = MakeDefeats(rawData);
Console.WriteLine("\n== Pairwise defeats data is: \n");
Print(defeats);
The defeats matrix is then passed as input to another helper method, named MakePathStrengths, which creates a matrix of path strengths:
int[,] strengths = MakePathStrengths(defeats);
Console.WriteLine("\n== Path strength data is: \n");
Print(strengths);
Inside the MakePathStrengths method, I begin by eliminating entries that are dominated:
int[,] result = new int[N, N];
for (int i = 0; i < N; ++i)
{
  for (int j = 0; j < N; ++j)
  {
    if (d[i, j] > d[j, i])
      result[i, j] = d[i, j];
    else
      result[i, j] = 0;
  }
}
Notice that the statement result[i, j] = 0; is not technically necessary because C# automatically initializes int arrays to all 0 values.
Next I use a variation of the Floyd–Warshall algorithm to compute the strength of each possible path:
for (int k = 0; k < N; ++k) {
  for (int i = 0; i < N; ++i) {
    if (k == i) continue;
    for (int j = 0; j < N; ++j) {
      if (k == j || i == j) continue;
      result[i, j] =
        Math.Max(result[i, j], Math.Min(result[i, k], result[k, j]));
    } //j
  } //i
} //k
If you go ahead and hand-trace through this code, you will see how it implements the determination of the path strength that exists between node [i] and node [j], as I described previously. The Max method in the code works to ensure that on each iteration through the outer loop I update the result matrix only if a stronger path happens to be found. The Min method in the code corresponds to the idea of using the smallest direct node-to-node strength to represent the overall path strength that is in existence between any two nodes.
After I have all the path strengths, I can use that information to compute an array that represents Schulze winners and then iterate through that array and display the enumeration value that corresponds to each winner:
bool[] winners = MakeWinners(strengths);
Console.WriteLine("\n== Best option(s) is: \n");
for (int i = 0; i < winners.Length; ++i) {
  if (winners[i] == true)
    Console.Write(Enum.GetName(typeof(options), i) + " ");
}
The MakeWinners method sets up a one-dimensional Boolean array where a value of true indicates a winner and a value of false indicates a non-winner. I assume every option is a winner, then iterate through the path strength matrix, comparing the strength value at index [i,j] with that at index[j,i] to see if that option is in fact a non-winner:
static int[] MakeWinners(int[,] ps) {
  bool[] result = new bool[N];

  for (int i = 0; i < N; ++i)
    result[i] = true;

  for (int i = 0; i < N; ++i)   {
    for (int j = 0; j < N; ++j)
      if (ps[i, j] < ps[j, i])
        result[i] = false;
  }
  return result;
}

More to Evaluate
Some of the key factors you should consider when using group evaluation techniques include the number of alternatives, the number of evaluators, whether the alternatives are policy decisions or product decisions, and the extent to which evaluators are affected by the final result of the analysis. In general, you should use more than one group analysis technique when possible in order to use multiple results to cross-validate your analysis (if multiple techniques yield the same conclusion, you gain some measure of confidence in your results).
The situations where the techniques I've described in this column are used are almost always quite subjective. Your experience and intuition must play a big part in analyzing group determination results.
As a general rule of thumb, the pure plurality technique is only effective in situations where evaluators are not stakeholders or when ranking all alternatives is not feasible. The majority runoff technique has the potential to alienate up to 49% of your evaluators, and based on my experience you should generally use this technique primarily to supplement other techniques.
The Borda count system, in spite of technical flaws, works quite well, especially when the evaluators are stakeholders in the analysis. The Condorcet principle is very simple and so can often be used to validate the results of other techniques. The Schulze method is an excellent general-purpose technique in many software testing situations, except when you are dealing with a relatively small group of evaluators who are influenced by the results and who do not understand the Schulze algorithm.
This column just scratches the surface of an interesting and useful subject. There is a large body of research on group techniques to determine the best alternative from a set of options. One good reference is the book A Primer in Social Choice Theory, by Wulf Gaertner (Oxford University Press, 2006). I also recommend Comparing Voting Systems, by Hannu Nurmi (Springer-Verlag, 1987).
You might find it interesting to compare the problem of group analysis to determine a best alternative to the related problem of rating a set of alternatives based on multiple attributes. If that's the case, I address two different multi-attribute decision techniques in the June 2005 ( msdn.microsoft.com/magazine/cc163785 ) and October 2006 ( msdn.microsoft.com/magazine/cc300812 ) installments of the Test Run column.

Send your questions and comments for James to testrun@microsoft.com .

Dr. James McCaffrey works for Volt Information Sciences, Inc., where he manages technical training for software engineers working for Microsoft in Redmond. He has worked on several Microsoft products including Internet Explorer and MSN Search. James is the author of .NET Test Automation Recipes (Apress, 2006), and he can be reached at jmccaffrey@volt.com or v-jammc@microsoft.com .

Ejecución de prueba
Determinación del grupo de pruebas de software
Dr. James McCaffrey
Descarga de código disponible en: MSDN Code Gallery (153 KB)
Examinar el código en línea
Tenga en cuenta el problema general de determinar la mejor opción de una lista de opciones, donde el proceso de toma de decisiones se realiza por un grupo de personas en lugar de una persona sola o mediante una técnica puramente cuantitativa. Algunos ejemplos de este tipo de actividad son los residentes de un estado para regulador del estado de una lista de candidatos y el panel de directores de una compañía grande determinar cuál de varias compañías más pequeñas como destino para la adquisición de voto. En esencia, el grupo debe clasificar sus opciones de alguna manera para que se puede determinar la mejor uno.
Determinación del grupo de una alternativa mejor también se produce en desarrollo de software y las pruebas. Por ejemplo, considere un grupo de usuarios beta eligiendo la mejor interfaz de usuario de un conjunto de prototipos. O imagine los miembros de un proyecto de código fuente abierto voto para una directiva.
Ha observado que las técnicas prácticas para efectuar la determinación del grupo de una alternativa mejor y las posibles dificultades del proceso, no se conocen mucho en el software prueba comunidad. Existen docenas de técnicas de análisis de grupo. En la columna de este mes es describir cinco de los métodos más comunes utilizados para la determinación de grupo de una alternativa mejor en un entorno de pruebas de software: la técnica plurality puro, la técnica de runoff mayoría, el sistema de recuento Borda, el método Condorcet y el método Schulze.
Todos estas técnicas de análisis son conocidos fuera de ingeniería de software y han ha investigado mucho. Describen cada técnica con un énfasis en su aplicación para probar el software. CREO que encontrará conocimiento de las técnicas de análisis del grupo una incorporación valiosa para el Kit de herramientas.
Situaciones en las que se debe seleccionar exactamente un conjunto de alternativas por un grupo de personas se producen en una amplia gama de dominios con problemas. Dominios con problemas diferentes tienden a usar terminología diferente. En sociology, por ejemplo, el estudio de este tipo de problema normalmente se denomina teoría de elección sociales y normalmente utiliza términos como opciones y los evaluadores. En political ciencia, análisis de estos problemas se suele llamar teoría voto y utilizan el términos candidatos y voters. En matemáticas, determinación del grupo de una alternativa mejor con frecuencia se considera un sub-branch de teoría de toma de decisiones. VOY a utilizar una combinación de terminología en mi explicación porque no hay ningún conjunto de terminología específica utilizado cuando estas técnicas se aplican a un entorno de pruebas y desarrollo de software.
Las técnicas que describen en esta columna aplican a un intervalo bastante estrecho de problemas y no aplicará estrictamente a cuantitativos escenarios donde una opción mejor está claramente definida. Como verá, cuando se selecciona una alternativa "mejor", el significado de mejor en un grupo de personas se define mediante la técnica que utiliza. Además, las técnicas que describen aquí no se aplican a escenarios de colaboración en un grupo de personas utilizar discusión y negociación para llegar a una decisión de consenso.

Plurality pura y Runoff mayoría
Vamos a comenzar la discusión de grupo de determinación de una alternativa mejor con una apariencia en la técnica más sencilla y más comunes, pero permitirme advertirle de que éste no es el mejor enfoque en muchas situaciones de pruebas. Supongamos que está desarrollando una aplicación de software de empresa para uso interno de la compañía y crear cuatro prototipos de interfaz de usuario bastante diferente. Aunque podría solicita una sola persona para evaluar los prototipos diferentes, en muchos casos un enfoque mejor es pedir un grupo de personas para clasificar los cuatro diseños diferentes.
Parece el proceso de realización de una evaluación de grupo y interpretar el resultado es un poco más complicado que cabría esperar. La técnica de evaluación de grupo posibles más sencilla es enviar las respuestas a los evaluadores y permitiéndoles que elija, o votado, sólo una alternativa. La alternativa que recibe los votos la mayoría se declara el ganador. Esta técnica se denomina a menudo la regla plurality puro.
Por lo tanto, supongamos que envíe los prototipos diferentes cuatro (llamar a vamos a, B, C y D) a 10 evaluadores y pedirle a cada persona para elegir el prototipo mejor. Y suponga que los resultados son: un prototipo es mejor según a personas 4, prototipo B se ordenados mejor por personas 3, prototipo C es elegido por dos personas y prototipo D está activada de mejor forma de persona 1. Por tanto, se selecciona un prototipo para el desarrollo más.
Hay varios problemas con esto. Supongamos que mientras que los evaluadores están examinando los prototipos de cuatro, ya sea implícita o explícitamente clasificar cada opción, tal como se muestra en la figura 1 . En este diagrama, cada representa columna un evaluador de clasificación de los prototipos.
La figura 1 las clasificaciones de prototipo de evaluadores 10 (haga clic en la imagen de una vista más grande)
Observe que aunque se selecciona un prototipo por la regla plurality puro, prototipo que se evalúa como el peor por 60 % del grupo de evaluación. Además, en esta situación, supongamos que A se compara a su vez con cada uno de los otros prototipos de prototipo. UN prototipo perderían cada comparación head-to-head por un margen de 60 % 40 %. Un problema en segundo lugar, estrechamente relacionado con la técnica plurality puro es que en cierto sentido las opiniones no galardonados no contribuyen directamente al resultado final.
Los problemas con plurality puro llevar a otra técnica de selección de grupo, normalmente denominada el sistema de runoff mayoría. Hay varias variaciones de la técnica, pero es necesario para tener más de 50 % de los votos de primer lugar de todos los votos convierte el ganador.
Esto puede realizarse teniendo varias series de votación o realizar sólo una ronda única de voto, pero que requieren los evaluadores clasificar todas las opciones. Por ejemplo, si evaluadores votar por el diseño de prototipo mejor según a los datos de la figura 1 , prototipo no tendría una mayoría después de la primera ronda de voto. Por lo que la lista de candidatos puede se reduzca, normalmente a las opciones superior dos; en este caso, el prototipo de A con cuatro votos y prototipo B con tres votos.
Una segunda ronda de votación a continuación, tiene lugar. Si en la que tiempo evaluadores votar conforme a las preferencias de clasificación en la figura 1 , después de la segunda ronda de votos un prototipo aún recibiría cuatro votos como mejor, pero podría recibir prototipo B seis aprueba porque los evaluadores que originalmente seleccionado prototipos C y D ahora podrían seleccionar prototipo B.
Según mi experiencia, el uso de varias series de voto en un desarrollo de software y entorno de prueba tiene desventajas importantes comparadas con un sistema único. En primer lugar, en algunos escenarios de desarrollo de software, varias series de votos simplemente no sea factibles. Además, ya que implica tratar los seres humanos, pueden obtener varias series de votos tediosos. Lo que es peor, pueden surgir situaciones donde un grupo de personas se para perder alternativas a través y votos sobre (recibir negativo comentarios cada vez) hasta que están obligados a elegir una opción no realmente deseen. Si los voters son los participantes en el sentido de que se verán afectados por el resultado de la votación, es posible que acabará con voters disenfranchised al final de una combinación de runoff físico.
En lugar de realizar varios redondea real de votos donde cada evaluador vota para sólo una alternativa, puede realizar simplemente una redondea de votos pero requiere evaluadores clasificar todos los candidatos de mejor lo peor. Esto permite determinar preferencias de voters en redondea virtual de voto.
Requerir clasificación de todas las opciones tiene algunos inconvenientes, demasiado. La técnica a menudo no resulta práctica cuando el número de opciones es grande (normalmente más de ocho), simplemente porque los humanos tienen dificultades para comparar un gran número de alternativas. Además, investigación ha demostrado que evaluadores tienden a obtener descuidados con sus evaluaciones de opciones que son bajos en su lista de preferencias. Y, al realizar varias redondea físico de voto, evaluadores no pueden clasificar un subconjunto de alternativas en el mismo orden en que clasificar todo el conjunto de alternativas.
El método de Schulze: profesionales y DIA
método de la Schulze tiene puntos fuertes y débiles. Un punto débil en algunos casos es Schulze lejos de intuitiva. En situaciones en las que evaluadores son los participantes, el método Schulze puede verse fácilmente como una técnica caja negra desconcertante que genera un resultado mágica.
La ventaja principal del método Schulze es que ha sido analizado ampliamente y se ha demostrado cumplir muchos criterios favorables. Recuerde que el sistema de recuento Borda puede verse afectado por la eliminación de una alternativa son irrelevante.
Hay muchos criterios de sistema de voto. Por ejemplo, el criterio monotonicity puede escasamente indicarse como el principio que una opción excelente no es no ganador por uno o más evaluadores clasificación esa opción superior. La independencia de clones criterio alternativas se, se indica flexible, que al agregar una nueva opción que es idéntica a una opción existente no debe cambiar el resultado de un análisis. Hay muchos criterios de sistema de voto propuestos, y el método Schulze se ha muestra cumplen la mayoría de estos criterios así.
Una excepción interesante es que el método Schulze infringe lo que se denomina el criterio de participación. En términos informales, es posible agregar a un sistema existente, nuevas voters que prefieren el ganador actual a alguna otra alternativa, lo que provoca la alternativa preferida menos convertirse en un ganador Schulze.
A pesar de sus inconvenientes, el método Schulze a menudo es muy eficaz, especialmente en situaciones con un grupo grande, con de evaluadores (lo que significa que tiene conocimiento de método Schulze subyacente) que se determina una alternativa de directivas (como la diferencia a una decisión de producto) y quiénes son los participantes en el resultado final. Por ejemplo, el método Schulze se utiliza por varios grupos de código abierto para determinar las decisiones de directiva general y para elegir los agentes. En escenarios de pruebas de software, el método Schulze normalmente es la primera técnica que elijo emplear y, a continuación, VOY a utilizar los resultados como una línea de base con los resultados de otras técnicas.

Sistema de cuenta Borda
Los problemas del plurality puro y mayoría runoff técnicas llevó al desarrollo de dos técnicas de análisis de grupo que son muy comunes. Estas técnicas, el sistema de recuento Borda y el método de comparación par a par Condorcet, reciben los dos matemáticos que propone los métodos en el tiempo de ejecución 1700s.
El enfoque de recuento Borda es muy sencillo y otro con la que está casi ciertamente familiarizado. Supongamos que hay n alternativas. Cada evaluador clasifica las alternativas de mejor lo peor. Una alternativa de rango superior se asigna un valor de n-1 puntos, una alternativa ordenados el segundo está asignada puntos n-2 etc., hacia abajo a la alternativa última clasificación, que recibe 0 puntos. El recuento de Borda es sólo la suma de los valores de punto de cada alternativa.
Un rápido ejemplo hará que las ideas borrar. Supongamos que hay cuatro opciones, A, B, C y D. En este caso, una clasificación en primer lugar la pena 3 puntos, segundo lugar merece la pena 2 tercer lugar merece la pena 1 y último lugar merece la pena 0 puntos. la figura 2 muestra los resultados y, a continuación, debajo, la Borda recuento de evaluadores siete en una alternativa es seleccionada como opción mejor.
La Figura 2 resultados y Borda cuenta para evaluadores 7 (haga clic en la imagen de una vista más grande)
La técnica de recuento Borda ampliamente se utiliza en muchos dominios de problema, especialmente de deportes competitions. Ventajas de la técnica de recuento Borda cuando se utiliza en un entorno de pruebas y desarrollo de software son que la técnica parece sentido de manera intuitiva, y las opiniones de todos los evaluadores se tienen en cuenta.
El sistema de conteo de Borda tiene varios problemas técnicos, de sin embargo. Suponga que se decide quitar la opción D, que era un perdedor claro. Sentido común sugiere que quitar alternativa irrelevante debería afectar no al resultado final. Pero la figura 3 muestra lo que sucede después de quitar opción D. Ahora la opción B se convierte en la mejor alternativa en lugar de opción a. En otras palabras, con este conjunto de datos, quitar un cambios alternativo irrelevantes el resultado. Es posible construir Borda recuento ejemplos donde la mejor alternativa se convierte en realidad en la alternativa peor. Este efecto se denomina la paradox de Borda recuento perdedor se convierta en ganador.
La figura 3 resultados y Borda cuenta después de quitar D opciones (haga clic en la imagen de una vista más grande)
Hay dos otros problemas técnicos estrechamente relacionados con la técnica de recuento Borda. El primero es el problema de comparación par a par. Es posible cuando mediante la técnica de recuento Borda para ejecutarse en situaciones donde la ganador Borda perderían frente a cada alternativa en una comparación head-to-head.
Por ejemplo, supongamos que hay cuatro alternativas y evaluadores 12 (consulte la figura 4 ). Utilizar el método de recuento Borda, una alternativa esté seleccionada como mejor con 25 puntos. Sin embargo, si observamos comparaciones head-to-head se observe que B alternativo es preferido para otras alternativas: B es preferido a por un resultado de siete personas a 5, B es preferible a C también por 5 a 7 y B es mejor a D nuevo por 5 a 7.
La figura 4 opción B es el ganador de Head-to-Head (haga clic en la imagen de una vista más grande)
Otro problema con la técnica de recuento Borda es que es vulnerable a manipulación de evaluador. Teóricamente es posible afectar al resultado de un Borda recuento evaluación mediante la adición de una alternativa falsos que es muy cerca (en términos de las preferencias de evaluadores) alternativa existente. Esto puede tienen el efecto diluting cierre alternativas y cambiando el ganador del análisis. Las referencias al final de esta columna contienen ejemplos del efecto.
A pesar de técnica errores la técnica de recuento Borda, el sistema es muy práctico y a menudo funciona bien para la determinación de directiva por grupos pequeños en un entorno de pruebas de software. Según mi experiencia, la técnica de recuento Borda es generalmente considera por voters justo de una manera subjetiva, y, por lo tanto, si voters son los participantes, las personas que elegida para alternativas galardonados no suelen aceptan el resultado de la votación y no vienen inmediatamente con una diferencia psychological frente a la alternativa ganador.
La moraleja del artículo aquí es que si utilizar la técnica de recuento Borda, esté alerta para y, compruebe los datos para, el efecto de quitar una alternativa irrelevante, el resultado de par a par comparaciones entre el Borda contar ganador y no galardonados alternativas y la incorporación mid-process de una alternativa nueva.

Condorcet técnica y el método de Schulze
La técnica Condorcet para determinar la mejor opción de un grupo de opciones de colaboración se desarrolló principalmente como una reacción ante el problema paring head-to-head del método Borda recuento. El método Condorcet es muy sencillo. Requiere evaluadores clasificar todos alternativas y, a continuación, se realiza una comparación de los resultados entre cada par de alternativas posible.
Si una alternativa late cada otra alternativa en una comparación head-to-head, que una alternativa se declara el ganador de Condorcet. Si no hay ningún ganador Condorcet, a continuación, se emplea una técnica separada, desempate. La técnica de desempate puede ser cualquier otra técnica; el punto del sistema Condorcet es que automáticamente debe ganar ganador head-to-head unanimous sobre las alternativas elegidas por cualquier otro criterio.
En la práctica, el sistema Condorcet no suele utilizarse por sí mismo como una técnica de evaluación de grupo. En su lugar, técnicas de evaluación como plurality pura y recuento de Borda matemáticamente se analizan para ver si cumplen el principio Condorcet en todos los casos. Así que, en lugar de leer algo parecido a, "hemos decidido utilizar el sistema Condorcet para evaluar nuestras alternativas, " es más habitual para leer algo parecido a, "hemos decidido utilizar el sistema de evaluación XYZ, que satisface el principio Condorcet."
Uno de los sistemas más interesantes que satisface el principio Condorcet tiene una gran variedad de nombres, incluido el método Schulze, la técnica de Schwartz secuencial soltar duplicado de prueba y el método ritmo de ruta de acceso. Llamará esta técnica al Schulze método.
El método Schulze es algo más compleja que las otras técnicas que he descrito hasta ahora. Es similar al sistema Condorcet en el sentido de que parezca Schulze para ver si una opción domina todas las demás opciones. Sin embargo, en lugar de datos de clasificación original de utilizar directamente, como el sistema Condorcet hace, el método de Schulze realiza una comparación head-to-head con una medida indirecta de la seguridad entre las alternativas. Esta medida indirecta se llama a la seguridad de ruta de acceso.
Vamos a describa un ejemplo. Eche un vistazo a la figura 5 . Muestra una sencilla demostración del método Schulze de acción. La primera parte muestra la entrada de ejemplo. Hay cuatro opciones (A, B, C y D) y evaluadores 11. La primera línea significa que evaluadores 3 clasificar una opción mejor que B, que a su vez es mejor que C, que es mejor que D. El método de Schulze permite evaluadores a opciones de clasificación igual a entre sí y también permite evaluadores dejar fuera alternativas totalmente.
La figura 5 demostración de Schulze (método) (haga clic en la imagen de una vista más grande)
La siguiente parte de la salida muestra una matriz de par a par sirve para saltarse esta premisa. Esta matriz sirve para saltarse esta premisa se calcula directamente desde los datos de clasificación original.
La primera fila de la matriz significa opción A es preferido por voters 6 sobre la opción B, preferida por 3 voters sobre opción C y por 4 voters sobre opción D. La segunda fila de la matriz significa opción que B es preferido por 5 voters sobre opción A, por voters 7 a través de la opción C y por 8 voters sobre opción D. Las filas tercera y cuarta, para las opciones C y D, respectivamente, se interpretan de manera similar. La matriz de par a par sirve para saltarse esta premisa tiene los valores 0 de la diagonal principal porque estos valores son las comparaciones entre una opción y él mismo.
En este momento el sistema Condorcet podría comprobar esta datos par a par directos para ver si existe un ganador head-to-head unanimous, pero el método Schulze deriva una medida indirecta de seguridad entre las alternativas. La parte siguiente del resultado es la eficacia de las rutas entre cada una de las opciones. Esto es la idea clave en el método Schulze y es un concepto muy inteligente. La tercera fila de esta matriz significa que la seguridad de la ruta de opción C a una opción es 8, la intensidad de C a B es 4 y la intensidad de C a D es 10.
Explicar la idea de intensidad de la ruta de acceso mejor se realiza visualmente, tal como se muestra en la figura 6 . En primer lugar los datos sin procesar de clasificación se expresar como una matriz de par a par sirve para saltarse esta premisa. A continuación se pueden desarrollar los datos sirve para saltarse esta premisa par a par como un gráfico dirigido.
Figura 6 Pair-Wise los datos Defeat en matriz y formularios de gráfico (haga clic en la imagen de una vista más grande)
La flecha del nodo al nodo B significa esa opción A es preferido por evaluadores 6 sobre opción B. No coloque una flecha de nodo B al nodo A porque la opción B es preferir evaluadores sólo 5 sobre opción A, por lo que A domina B. En este ejemplo, todas las flechas son unidireccionales, pero si se dos nodos se prefiere por números iguales de evaluadores, a continuación, puede dibujar una flecha bidireccional.
Ahora, considere la ruta entre el nodo A y D. de nodo A su vez un pulsaciones B por 6 y B late D por 8. Hemos optado por 6, el menor de estos dos valores, para representar la eficacia general de ruta de acceso entre A y B. La idea es que la seguridad general entre dos nodos que tienen nodos intermedios mejor está representada por la fuerza de nodo a nodo directa más pequeño. Observe que también se puede tomar una ruta diferente de A D y pulsaciones de decir que un ritmos B por 6 y B pulsaciones C: por 7 y C, D por 10 y seleccione el número más pequeño, 6, que se proporcionan el mismo resultado.
Resulta que la seguridad de cada par de nodos de informática puede realizar una variante del algoritmo Floyd–Warshall elegante, como explicaré en un momento. El algoritmo estándar de Floyd–Warshall busca las rutas de acceso más cortas en un gráfico ponderado, dirigido. Una vez han determinado los puntos fuertes de ruta de acceso, podemos determinar los ganadores de método Schulze mediante la comprobación para ver si hay cualquier opción donde la intensidad de la ruta de acceso es mayor o igual que correspondiente puntos fuertes de ruta de acceso de todas las demás opciones.
la figura 7 muestra la matriz de puntos fuertes de ruta de acceso que corresponde a los datos en la figura 6 y demuestra que la opción B es un ganador del método Schulze. Visualmente, una opción es el ganador Schulze si cada valor de intensidad de la ruta de acceso en la fila de esa opción es mayor o igual al valor correspondiente en la diagonal principal de la matriz.
La figura 7 datos de intensidad de ruta de acceso para determinar un ganador Schulze
Opción B es el ganador porque opción B intensidad de ruta de acceso a la opción A 7 (pero opción la intensidad de ruta de acceso a B es 6), opción B intensidad de ruta de acceso a la opción C es 7 (pero intensidad de la ruta de acceso de C a B es 6), y la opción B intensidad de ruta de acceso a la opción D es 8 (pero intensidad de la ruta de acceso de D a B es 6). Por otro lado, opción D no está un ganador Schulze porque intensidad de ruta de acceso de la opción de D es mejor que opción A (7 a 6), pero la intensidad de la opción de D es peor que la opción C (6 a 10).

El método Schulze en código
En este ejemplo hay sólo un ganador Schulze, pero es posible que haya ser ganadores Schulze varios. En casos como éstos tendría que utilizar algún tiebreaker. Vamos a través de la parte del código en el programa que genera el resultado en la figura 5 para ayudar a explicar el método Schulze.
El programa comienza con la configuración de un tipo de enumeración para representar las alternativas y un valor global N para contener el número real de alternativas:
   enum options { A, B, C, D, E, F, G, H, I, J };
   static int N; // actual number of options
A continuación, el programa de demostración configura problema entrada como una matriz de cadenas:
   string[] rawData = new string[] {
           "A>B>C>D 3",
           "B>C>D>A 4",
           "C>D>A>B 2",
           "D>C>B>A 1",
           "C>A>B>D 1"
                          };
Por motivos de simplicidad, mi programa de demostración se supone que no se permiten relaciones y que todas las opciones están ordenadas. Me analizar las cadenas de datos sin formato fácilmente permite hacerlo. El programa de demostración completa está disponible en la descarga de código que acompaña a esta columna. Debe poder modificar el código para permitir las relaciones que falten opciones y, sin demasiado problema.
A continuación, mi programa de demostración examina la matriz de cadenas rawData y determina e imprime el número de opciones y el número de evaluadores. A continuación, los programas rescans la matriz de entrada y crea una matriz de datos de par a par sirve para saltarse esta premisa con un método auxiliar estática denominado MakeDefeats:
int[,] defeats = MakeDefeats(rawData);
Console.WriteLine("\n== Pairwise defeats data is: \n");
Print(defeats);
A continuación, se pasa la matriz sirve para saltarse esta premisa como entrada a otro método auxiliar, denominado MakePathStrengths, que crea una matriz de puntos fuertes de ruta de acceso:
int[,] strengths = MakePathStrengths(defeats);
Console.WriteLine("\n== Path strength data is: \n");
Print(strengths);
En el método MakePathStrengths, comienzo eliminando las entradas que se dominado:
int[,] result = new int[N, N];
for (int i = 0; i < N; ++i)
{
  for (int j = 0; j < N; ++j)
  {
    if (d[i, j] > d[j, i])
      result[i, j] = d[i, j];
    else
      result[i, j] = 0;
  }
}
Observe que el resultado de la instrucción [i, j] = 0; no es técnicamente necesario porque C# inicializa automáticamente las matrices de int a todos los valores 0.
A continuación utilice una variante del algoritmo Floyd–Warshall para calcular la seguridad de cada ruta de acceso posible:
for (int k = 0; k < N; ++k) {
  for (int i = 0; i < N; ++i) {
    if (k == i) continue;
    for (int j = 0; j < N; ++j) {
      if (k == j || i == j) continue;
      result[i, j] =
        Math.Max(result[i, j], Math.Min(result[i, k], result[k, j]));
    } //j
  } //i
} //k
Si siga adelante y mano de seguimiento mediante este código, verá cómo implementa la determinación de la seguridad de ruta de acceso que existe entre el nodo [i] y nodo [j], como se ha descrito anteriormente. El método máximo en el código funciona para asegurarse de que en cada iteración del bucle externo actualice la matriz de resultados sólo si una ruta de acceso más seguro ocurre que se va a buscar. El método mínimo en el código corresponde a la idea de utilizar la menor intensidad de nodo a nodo directa para representar la intensidad de ruta de acceso general que se encuentra en existencia entre los dos nodos.
Una vez que tenga todos los puntos fuertes de ruta de acceso, PUEDO utilizar esa información para calcular una matriz que representa los ganadores de Schulze y, a continuación, realizar una iteración a través de dicha matriz y mostrar el valor de enumeración correspondiente a cada ganador:
bool[] winners = MakeWinners(strengths);
Console.WriteLine("\n== Best option(s) is: \n");
for (int i = 0; i < winners.Length; ++i) {
  if (winners[i] == true)
    Console.Write(Enum.GetName(typeof(options), i) + " ");
}
El método MakeWinners establece copia una matriz de tipo Boolean unidimensional donde el valor true indica que un ganador y el valor false indica que no ganador. Supone que todas las opciones es el ganador, recorrer la matriz de intensidad de la ruta de acceso, comparar el valor de intensidad de índice [i, j] con eso en índice [j, i] para ver si esa opción es en realidad no ganador:
static int[] MakeWinners(int[,] ps) {
  bool[] result = new bool[N];

  for (int i = 0; i < N; ++i)
    result[i] = true;

  for (int i = 0; i < N; ++i)   {
    for (int j = 0; j < N; ++j)
      if (ps[i, j] < ps[j, i])
        result[i] = false;
  }
  return result;
}

Más para evaluar
Algunos de los factores claves debe considerar la posibilidad cuando se utiliza técnicas incluyen el número de alternativas, el número de evaluadores, evaluación de grupo si las alternativas son las decisiones de directivas o las decisiones de producto y la extensión a la que se ven afectados evaluadores por el resultado final del análisis. En general, debe utilizar más de una técnica de análisis de grupo cuando sea posible usar varios resultados para cruzadas validar su análisis (si varias técnicas produzcan la misma conclusión, obtendrá alguna medida de confianza en los resultados).
Las situaciones donde se utilizan las técnicas que he descrito en esta columna casi siempre son muy subjetivas. La experiencia y los intuition deben reproducen una parte grande en analizar los resultados de determinación de grupo.
Como general regla general, la técnica plurality puro es sólo eficaz en situaciones donde evaluadores no son los participantes o cuando todas las alternativas de clasificación no es factible. La técnica de runoff mayoría tiene el potencial para alienate hasta 49% de los evaluadores, y según mi experiencia se debería suelen utilizar esta técnica principalmente para complementar otras técnicas.
El sistema de recuento Borda, a pesar de defectos técnicos, funciona bastante bien, especialmente cuando los evaluadores son los participantes en el análisis. El principio Condorcet es muy sencillo y por lo que puede a menudo se utiliza para validar los resultados de otras técnicas. El método Schulze es una técnica general excelente de software muchas pruebas de las situaciones, excepto cuando se está trabajando con un grupo relativamente pequeño de evaluadores quién está influida por los resultados y que no comprender el algoritmo Schulze.
Esta columna sólo resumen la superficie de un asunto interesante y útil. Hay un cuerpo grande de investigación en técnicas de grupo para determinar la mejor alternativa de un conjunto de opciones. Una buena referencia es la libreta de un manual en teoría opciones Social (Social), por Wulf Gaertner (Oxford University Press, 2006). También se recomienda comparación voto Systems, por Hannu Nurmi (Springer-Verlag, 1987).
Puede que le resulte interesante para comparar el problema de análisis de grupo para determinar una alternativa mejor para el problema relacionado de clasificación de un conjunto de alternativas según varios atributos. Si es el caso, trata de dos técnicas de decisión multi-attribute diferentes en el (junio de 2005 msdn.microsoft.com/Magazine/cc163785 ) y (de octubre de 2006 msdn.microsoft.com/Magazine/cc300812 ) partes de la columna prueba ejecutar.

Envíe sus preguntas y comentarios para James a testrun@Microsoft.com .

Dr. James McCaffrey funciona para información biológicas volt, Inc., que administra el formación técnica para ingenieros de software trabajar para Microsoft en Redmond. Ha trabajado en varios productos de Microsoft como Internet Explorer y MSN Search. Juan es el autor del .NET Test Automation Recipes (Apress, 2006), y puede ponerse en jmccaffrey@volt.com o v-jammc@microsoft.com .

Page view tracker