1

This was my Initial Method

public String GetAllDocuments(string url,int pager =0)
{
    if (SessionInfo.IsAdmin)
    {
        ReportHandler dal = new ReportHandler();
        var documents = dal.FetchDocumentsList(SessionInfo.ClientID, pager);
        string documentsDataJSON = JsonConvert.SerializeObject(documents);

        return documentsDataJSON;
    }
    else
    {
        return "Sorry!! You are not authorized to perform this action";
    }
}

Visual Studio shows the following Code Metrics:-

Member: GetAllDocuments(string, int) : string
Maintainability Index: 67
Cyclomatic Complexity: 2
Class Coupling: 7
Lines of Code: 7

So in order to improve it, I modified my method as below:-

public String GetAllDocuments(string url,int pager =0)
{
    ReportHandler dal = new ReportHandler();
    var documents = dal.FetchDocumentsList(SessionInfo.ClientID, pager);
    //moved the JSON Conversion to Separate class
    string documentsDataJSON = JsonHandler<T>.ConvertToJSON(documents);
    return documentsDataJSON;
}


But still it shows the Code Metrics as

Member: GetAllDocuments(string, int) : string
Maintainability Index: 72
Cyclomatic Complexity: 1
Class Coupling: 5
Lines of Code: 5

I can't submit this, unless the Maintainability Index is 90+.

What else can I do to improve Code Metrics.

Also, I am thinking for such small things creating separate method/class isn't it overhead

doppelgreener
  • 4,809
  • 10
  • 46
  • 63
Kgn-web
  • 7,047
  • 24
  • 95
  • 161

3 Answers3

2

You should often encapsulate any creation of objects in a factory interface, an instance of which you pass to the constructor of the class that wants to use it.

Thus your class would have a constructor and field like so:

public MyClass(IReportHandlerFactory reportHandlerFactory)
{
     if (reportHandlerFactory == null)
         throw new ArgumentNullException(nameof(reportHandlerFactory));

     _reportHandlerFactory = reportHandlerFactory;
}

private readonly IReportHandlerFactory _reportHandlerFactory;

This is known as dependency injection, specifically constructor injection.

To do this effectively you would probably also want to create an interface for your ReportHandler class. Then the factory interface would go something like this:

public interface IReportHandlerFactory
{
    IReportHandler Create();
}

And your report handler interface like this:

public interface IReportHandler
{
    IEnumerable<Document> FetchDocumentsList(Guid clientID, int pager);
}

...and so on. Hopefully you get the idea.

You should also split up your method, maybe something like this:

public String GetAllDocuments(string url,int pager =0)
{
    if (SessionInfo.IsAdmin)
    {
        return documentsData(_reportHandlerFactory, SessionInfo.ClientID, page);
    }
    else
    {
        return "Sorry!! You are not authorized to perform this action";
    }
}

private static String documentsData(
    IReportHandlerFactory reportHandlerFactory, 
    Guid clientID,
    int pager)
{
    IReportHandler dal = reportHandlerFactory.Create();

    var documents = dal.FetchDocumentsList(clientID, pager);
    string documentsDataJSON = JsonConvert.SerializeObject(documents);

    return documentsDataJSON;
}

NOTE: To be honest, this question is really a better fit for https://codereview.stackexchange.com/

I highly recommend the following books on this subject:

Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin)

and

Dependency Injection in .NET (Mark Seemann)

or Mark Seemann's blog.

Community
  • 1
  • 1
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • Wowwww. Highly insightful to me. Really appreciate :) – Kgn-web Dec 20 '16 at 08:30
  • Mattherw, everything is clear to me in your post. But I am not sure how should I implement interface `IReportHandlerFactory` – Kgn-web Dec 20 '16 at 09:45
  • Please add it to your post. It will guide me in a long way :) – Kgn-web Dec 20 '16 at 09:45
  • @Please check this post. http://stackoverflow.com/questions/41240184/how-to-implement-factory-design-pattern-in-c-sharp – Kgn-web Dec 20 '16 at 10:32
  • "You should often encapsulate any creation of objects in a factory interface" : I disagree with *often* and *any creation*. There are very few specific cases when it is better than no factory. – guillaume31 Dec 20 '16 at 11:51
  • Plus, people massively tend to misimplement Factories and struggle with them, by lack of comprehension of why they should use them in the first place (see OP's other question about using the Factory). – guillaume31 Dec 20 '16 at 11:53
  • @guillaume31 What is your definition of "often" then? To me, "often" doesn't mean "most of the time", if that's what you thought I was saying. And I know about the dangers of using factories; that's why I suggested some reading material for the OP. In the specific case given by the OP, the class name is `ReportHandler`. This seems likely to be the sort of thing you'd want to provide an abstract class or interface for, and you'd want to avoid newing up concrete types for it. – Matthew Watson Dec 20 '16 at 12:12
  • @guillaume31, can you please review this. http://codereview.stackexchange.com/questions/150382/is-this-the-right-way-to-implement-factory-pattern – Kgn-web Dec 20 '16 at 12:28
  • @MatthewWatson "often" = "frequently", a.k.a. the opposite of "rarely". And, IMO, you *rarely* need to use a Factory, because it rarely has a benefit in terms of problem solving or maintainability. Using a Factory when you don't need to results in clutter, fragility and error proneness. – guillaume31 Dec 20 '16 at 15:15
  • @guillaume31 In the specific context of the code in the OP, in my opinion where you have something like a "ReportHandler", you do fairly often need to use an interface, to aid unit testing if nothing else. Remember, my reply is not in a vacuum; rather, it is in the context of the OP. Indeed, the OPs code is part of the implementation of a Controller in an MVC application - an area where the usefulness of factory classes is above average. – Matthew Watson Dec 20 '16 at 15:17
  • @MatthewWatson I do agree with the abstract class/interface part (see my answer) – guillaume31 Dec 20 '16 at 15:20
  • @Kgn-web I can't answer your `codereview` question in its current form, because I have no idea how to please Visual Studio's quality analyzer. I can answer with general maintainability advice, though. – guillaume31 Dec 20 '16 at 15:25
  • @guillaume31, no worries about maintainability index, but can you please add your valuable inputs to the code-snippet posted "How can I improve it further" . http://codereview.stackexchange.com/questions/150382/factory-for-report-handlers – Kgn-web Dec 20 '16 at 15:28
2

Take a maintainability index as a tool, not a goal.

There's no point in increasing the maintainability index if you don't realize why your code wasn't maintainable in the first place. You'll just keep moving code around to satisfy the index, without ever understanding what you're doing.

Your question shouldn't be

How to update this class/method to improve Code Metrics?

but

How to improve the maintainability of this class?

I see a number of problems with it right now :

  • Dependencies are implicit, i.e. you're new'ing things up directly inside the method. This makes the code less flexible, composable and readable.

    Passing the ReportHandler dependency in to GetAllDocuments() or the class constructor instead would be better.

  • It is poorly testable. If ReportHandler were an interface (or an abstract class) instead, you could substitute it with a fake report handler in tests for GetAllDocuments() for improved performance and testing. Note that you do not have to use a Factory to do that, a simple interface with one real implementation and a test implementation are good enough.

  • Parameter url is not used.

  • SessionInfo.IsAdmin is a kind of magic shorthand that is prone to the same range of problems as the above. If you're in a controller, it's no big deal but if you're supposed to be in a business layer, this will hamper testability and maintainability.

Community
  • 1
  • 1
guillaume31
  • 13,738
  • 1
  • 32
  • 51
  • Really appreciate you for sharing your inputs. – Kgn-web Dec 20 '16 at 12:14
  • Can you please review my updated snippet http://codereview.stackexchange.com/questions/150382/is-this-the-right-way-to-implement-factory-pattern – Kgn-web Dec 20 '16 at 12:14
  • I would be very thankful to you if can share your review or if using the snippet can show how do I implement the same using SOLID principles – Kgn-web Dec 20 '16 at 12:19
0

If you interested in just make Maintainability Index better read how this is calculated: http://www.projectcodemeter.com/cost_estimation/help/GL_maintainability.htm

You can see that it depends mostly on number of lines of code.

If want good design, stop using concrete implementations, use one of SOLID principles - Dependency Inversion. For example, instead of using:

ReportHandler dal = new ReportHandler();

You shoud use something like:

IReportHandler dal = reportHandlerFactory.GetReportHandler();
// where reportHandlerFactory is IReportHandlerFactory which is also 
// make dependency on interface but not on concrete class 

Or even better is to inject such things using DI container.

Dzianis Yafimau
  • 2,034
  • 1
  • 27
  • 38
  • Your post seems higly appealing to me. Can you please add more details in your post about `IReportHandler dal = reportHandlerFactory.GetReportHandler();` . – Kgn-web Dec 20 '16 at 08:07
  • 1
    @Kgn-web, I edited my answer. Does it make sense for you? It is just an example anyway, you should design you code with regards to principles of good programming (patterns, SOLID etc.). As other recommended here it is worth starting from DI – Dzianis Yafimau Dec 20 '16 at 09:16
  • Yes. It makes sense to me. Thanks :) – Kgn-web Dec 20 '16 at 09:26
  • Please check this post. http://stackoverflow.com/questions/41240184/how-to-implement-factory-design-pattern-in-c-sharp – Kgn-web Dec 20 '16 at 10:32
  • Why a Factory? Also, you don't explain why this is good design. – guillaume31 Dec 20 '16 at 11:54
  • Question is too broad to eplain, I just show an idea and direction for further reading/learning. Short answer is SOLID – Dzianis Yafimau Dec 20 '16 at 12:06
  • Yes.agreed but I am trying to learn to use Factory pattern in real time. Can you please check this post .http://codereview.stackexchange.com/questions/150382/is-this-the-right-way-to-implement-factory-pattern – Kgn-web Dec 20 '16 at 12:16