I'm attempting to refactor what is becoming a very large method -- currently 350 or so lines -- that contains a high degree of cyclomatic complexity.
I understand and ascribe to the theories that methods should be short and that concerns should be separated, and I've been reading over things like this and this among others. I'm struggling to refactor my method, though, for a couple of reasons. To help illustrate these, first here is a simplified example of what the method looks like before refactoring:
private static void ProcessMessage(Message toProcess)
{
var processingIssues = new StringBuilder();
var transformedAttachments = new List<TransformedAttachmentData>();
foreach (var attach in toProcess.Attachments)
{
//in reality there is quite a bit of nested logic here,
//but I'll represent it as a single if-else block.
if (true)
{
//in reality, a third-party library is used in multiple
//levels of this logic hierarchy to produce the transformed data.
transformedAttachments.Add(new TransformedAttachmentData(attach));
}
else
{
processingIssues.AppendLine(
string.Format(@"Issue ""{0}"" occurred with " +
@"attachment ""{1}"".", "blah blah problem", attach.Name));
}
}
/*
* do something else complex here with
* processingIssues and validResults
*/
}
First, the very cyclomatic complexity which is concerning to me is born of a complicated set of business rules that need to be applied which together sum up to a couple shared sets of data (represented here as processingIssues
and transformedAttachments
). Basically what this means to me is that not only should I break the foreach
out into its own method, but I should also further consider breaking the logic tree contained within it into additional methods in the interest of keeping my methods "short". In other words, it would seem as though it's not enough just to break my current method into its two obvious outer-most parts: "pre-processing" and "post-processing" of the attachments, if you will. How far do I need to go with this given that I am dealing with a complicated logic tree with concerns that are not so "separate" from one another. In other words, if "separation of concerns" is one reason to refactor to smaller methods, but so is "cyclomatic complexity" -- both of which seem to be orthogonal concepts -- which is the "right" reason to refactor, and how should I do it in the latter case?
Second, in order to separate out some of the concerns to separate methods, those separate methods will have to return multiple variables (again, processingIssues
and transformedAttachments
), both of which are only needed within the separate methods themselves, so I'm faced with the choice: use output parameters, or create a small class to wrap the return values. Which is better?
Any guidance on this topic and my specific hang-ups would be much appreciated.