Снижение сложности класса - когнитивная сложность C#
Пожалуйста, посоветуйте мне, как я могу улучшить когнитивную сложность моего кода.
У меня есть метод, в котором есть цикл while, и внутри этого множества блоков IF ELSE я попытался удалить IF ELSE с помощью операторов SWITCH, но не улучшил когнитивную сложность в соответствии с анализом куба SONAR. Пожалуйста, подскажите, как мне улучшить сложность
Это мой существующий код: -
while (this.moveNextDelegate(fileLineEnumerator))
{
var line = fileLineEnumerator.Current;
var recordType = GetRecordType(line); // This Method returns the type of record
if (recordType == "1")
{
headerId++;
fileHeader = line; // Here fileHeader is being used in downsteam code flow - line 19
// some custom logic - deleted
}
else if (recordType == "5")
{
batchHeader = line; // Here batchHeader is being used in downsteam code flow - line 19
isRepeativeRecord = false;
}
else if (recordType == "6")
{
batchHeaderId = // some custom logic - deleted
// Here batchHeaderId is being used in downsteam code flow - line 35
detailId++;
isFlag = false;
isRepeativeRecord = true;
// some custom logic - deleted
}
else if (recordType == "7" && !isFlag)
{
addendaId++;
detailRecordsExist = true;
// some custom logic - deleted
}
currentIndex++;
}
Мой новый код с использованием оператора Switch - но все еще нет улучшений со сложностью
while (this.moveNextDelegate(fileLineEnumerator))
{
var line = fileLineEnumerator.Current;
var recordType = GetRecordType(line);
switch (recordType)
{
case "1":
{
headerId++;
fileHeader = line;
// some custom logic - deleted
break;
}
case "2":
{
batchHeader = line;
isRepeativeRecord = false;
break;
}
case "6":
{
// some custom logic - deleted
break;
}
case "7":
{
if (!isFlag)
{
// some custom logic - deleted
}
break;
}
case "8":
{
if (!isFlag)
{
// some custom logic - deleted
}
break;
}
}
currentIndex++;
}
1 ответ
Переключение с
if/else
к
switch
Оператор может быть хорошей идеей, не отбрасывайте его из окончательного кода, но он не уменьшит сложность, потому что оператор «if / else / switch» все еще существует в теле вместе с другими
if
заявления.
Чтобы избежать сложности сонара, напишите более простые методы , каждый из которых преследует одну цель , лучше тестировать и иметь меньше логики для понимания.
https://en.wikipedia.org/wiki/SOLID
Взглянув на свой код, вы можете извлечь некоторые методы, я провел некоторый рефакторинг, чтобы уменьшить сложность, как вы можете видеть в списке ниже:
- извлекать код тела в метод
- извлекать код тела "типа записи" в другие методы
- вы все еще можете выполнить рефакторинг классов (с осторожностью, это может быть чрезмерной инженерией)
private void Foo()
{
FileEnumerator fileLineEnumerator = new FileEnumerator();
while (this.moveNextDelegate(fileLineEnumerator))
{
string line = fileLineEnumerator.Current;
ReadNextLine(line);
currentIndex++;
}
}
private void ReadNextLine(string line)
{
var recordType = GetRecordType(line);
if (recordType == "1")
{
this.ReadHeader(line);
}
else if (recordType == "5")
{
ReadBatchHeader(line);
}
else if (recordType == "6")
{
ReadRepeativeRecord();
}
else if (recordType == "7" && !this.isFlag)
{
ReadDetail();
}
}
private void ReadDetail()
{
this.addendaId++;
this.detailRecordsExist = true;
}
private void ReadRepeativeRecord()
{
this.batchHeaderId = this.detailId++;
this.isFlag = false;
this.isRepeativeRecord = true;
}
private void ReadBatchHeader(string line)
{
this.batchHeader = line;
this.isRepeativeRecord = false;
}
private void ReadHeader(string line)
{
this.headerId++;
this.fileHeader = line;
}
Похоже, вы пишете ридер, поэтому, если у вас много читателей / шагов, таких как чтение заголовка, тела, нижнего колонтитула файла, с деталями и рекурсивным содержимым, вы можете разделить каждый фрагмент в отдельный класс, например
HeaderReader
,
BodyReader
,
DetailReader
, но это может быть чрезмерной инженерией, так что вам решать, стоит ли оно того.
public class ReadState
{
public RecordType RecordType { get; set; }
public string Line { get; set; }
}
public class ReadResult
{
public int HeaderId { get; set; }
}
public class BodyReader : IYourCustomFileFragmentReaderInterface
{
public bool Test(ReadState state)
{
// check if is header
return state.RecordType == RecordType.Body;
}
public ReadResult Read(ReadResult result, ReadState state)
{
// write state
result.HeaderId = int.Parse(state.Line);
return result;
}
}
С отдельными читателями вы можете сгруппировать в список
IYourCustomFileFragmentReaderInterface
, вызов
Test()
и если это правда, то вызовите
Read
метод.