Проблема читаемости кода C # - PullRequest
4 голосов
/ 29 мая 2011
        int scalar = creature is SpecialCreature ? (creature.IsAwesome ? 700 : 500) : (creature is NotSoNormalCreature ? 
            (creature.IsAwesome ? (creature is IGreatCreature ? 450 : 280) : 240) : 
            (creature.IsAwesome ? (creature is IGreatCreature ? 300 : 200) : 160));

как мне написать этот код, чтобы сделать его более читабельным?

Я думал о создании ifs, но потом подумал о создании своего рода «ConditionFactory»? Имеет ли это какой-то смысл или это слишком сложно для такой простой задачи?

int scalar;

if (creature is SpecialCreature)
{
    scalar = creature.IsAwesome ? 700 : 500;
}
else if (creature is NotSoNormalCreature)
{
    if (creature.IsAwesome)
    {
        scalar = creature is IGreatCreature ? 450 : 280;
    }
    else
    {
        scalar = 240;
    }
}
else
{
    if (creature.IsAwesome)
    {
        scalar = creature is IGreatCreature ? 300 : 200;
    }
    else
    {
        scalar = 160;
    }
}

Ответы [ 5 ]

8 голосов
/ 29 мая 2011

Не совсем уверен, что вы собираетесь, но поскольку вы используете цепочку наследования базового типа, вы можете выбрать что-то вроде

interface ICreature
{
    bool IsAwesome { get; set; }
    int GetScalar();
}

abstract class Creature : ICreature
{
    public bool IsAwesome { get; set; }
    public virtual int GetScalar()
    {
        return 160;
    }
}

class SpecialCreature : Creature
{
    public override int GetScalar()
    {
        return this.IsAwesome ? 700 : 500;
    }
}

class NotSoNormalCreature : Creature
{
    public override int GetScalar()
    {
        return this.IsAwesome ? 450 : 280;
    }
}

// more ICreatures...

, что позволит вам реализовать свое существособственная логика для определения скаляра, и ваш потребляющий код может потерять усложнение забота .

ICreature creature = GetCreatureFromSomewhere();
int scalar = creature.GetScalar();
4 голосов
/ 29 мая 2011

Это не совсем то, что вам нужно здесь, но я использую метод Extension для реализации такого рода цепного метода, когда условие может быть разрешено до списка Or или And.

Что-то вроде

if (true.IfOr(condition1 == a, condition2 == b) 
{ 
  something(); 
}

метод расширения тогда довольно прост:

public static bool IfOr(this bool result, params bool[] tests)
{
  foreach (bool test in tests)
    if (!test)
      return !result;
  return result;
}

Еще один метод, который может работать, хотя и может быть не очень оптимальным, - это использовать делегат Predicate в .net и определить список методов.которые выполняют ваши отдельные единицы логики.Затем вы можете заменить свои вложенные третичные операторы лямбда-выражением.У меня нет примера кода для этого, извините.

И наконец, иногда нет ничего лучше, чем старый добрый оператор switch.Я полагаю, что .Net имеет тенденцию компилировать их в виде таблиц переходов, так что, если вы сначала упорядочите свой тест по наиболее кратным из них, то вы сможете получить довольно производительный и читаемый код.И это можно обслуживать, вместо того, чтобы скрывать логику или реализацию хитростями.

0 голосов
/ 29 мая 2011

Как насчет старого доброго:

if (creature is SpecialCreature)
{
    scalar=getSpecialCreatureScalar(creature);
}
else if (creature is NotSoNormalCreature)
{
    scalar=getNotSoNormalCreatureScalar(creature);
}
else
{
    scalar=getScalar(creature);
}

.. А потом

int GetSpecialCreatureScalar(SpecialCreature creature)
{
    return creature.IsAwesome ? 700 : 500;
}   

int GetNotSoNormalCreatureScalar(NotSoNormalCreature creature)
{
    if (creature.IsAwesome)
    {
        return creature is IGreatCreature ? 450 : 280;
    }
    else
    {
        return 240;
    }
}   

int GetScalar(Creature creature)
{
    if (creature.IsAwesome)
    {
        return creature is IGreatCreature ? 300 : 200;
    }
    else
    {
        return 160;
    }
}  

.. Дает значение if.Делает другое ИМО.

0 голосов
/ 29 мая 2011

Вот так я заново сделал код и сделал его читаемым

// Original code spread apart
int scalar = creature is SpecialCreature ? (
    creature.IsAwesome ? 700 : 500
) : (
    creature is NotSoNormalCreature ? (
        creature.IsAwesome ? (
            creature is IGreatCreature ? 450 : 280
        ) : 240
    ) : (
        creature.IsAwesome ? (
            creature is IGreatCreature ? 300 : 200
        ) : 160
    )
);

// Readable code with hybrid if() and ? :
if (creature is SpecialCreature)
{
    scalar = creature.IsAwesome ? 700 : 500;
}
else if (creature is NotSoNormalCreature)
{
    if (creature.IsAwesome)
    {
        scalar = creature is IGreatCreature ? 450 : 280;
    }
    else
    {
        scalar = 240;
    }
}
else
{
    if (creature.IsAwesome)
    {
        scalar = creature is IGreatCreature ? 300 : 200;
    }
    else
    {
        scalar = 160;
    }
}

Я хочу порекомендовать перенести этот расчет в каждый класс, если это возможно, с переопределениями для разных ветвей.

0 голосов
/ 29 мая 2011

Я думаю, что реальная проблема заключается в том, что вы жестко кодируете «данные конфигурации». Если вам, где сказать, вырвать эти «настройки» и поместить их в XML-файл конфигурации, то не исчезнет ли весь этот беспорядок?

Это может показаться излишним, пока вы не настроите свои различные конфигурации, чтобы сделать игру более удобной для игры ... отдельный файл конфигурации позволяет вам легко играть (и возвращать).


EDIT:

Кстати, я бы отформатировал вложенное троичное выражение, как показано ниже ..., чтобы сделать его более читабельным.

int scalar =
  creature is SpecialCreature
  ? creature.IsAwesome ? 700 : 500
  : creature is NotSoNormalCreature
    ? creature.IsAwesome
      ? creature is IGreatCreature ? 450 : 280
      : 240
    : creature.IsAwesome
      ? creature is IGreatCreature ? 300 : 200
      : 160
;

Приветствия. Кит.

...