3
\$\begingroup\$

I'm refactoring a WPF application that uses Repository pattern to access the web services, I've got a tons of repository wrote as

public class DiagnosticsRepository : DefaultRepositoryBase, IDiagnosticsRepository
{
    public Task<IList<MasterDiagnosticType>> GetMasterDiagnosticTypes(string username)
    {
        var client = GetServiceStackClient();

        var request = new MasterDiagnosticTypesRequest
        {
            UserName = username
        };

        return client.PostAsync(request);
    }

    public Task<IList<MasterDiagnostic>> GetMasterDiagnosticsFromType(int type)
    {
        var client = GetServiceStackClient();

        var request = new MasterDiagnosticRequest()
        { MasterType = type };

        return client.PostAsync(request);
    }

    public Task<DiagnosticoDataResponse> GetMasterDiagnostic(string storedProcedure)
    {
        var client = GetServiceStackClient();

        var request = new DiagnosticoDataRequest()

        {
            StoredProcedureName = storedProcedure,
            Data = DateTime.Today
        };

        return client.PostAsync(request);
    }
}

How can I review it so that I can avoid the repetition? the only part that changes is the request

\$\endgroup\$
  • \$\begingroup\$ I assume you meant 'refactoring' instead of 'reviewing'? \$\endgroup\$ – Pieter Witvoet Aug 4 '17 at 10:18
  • \$\begingroup\$ you're right, fixing title \$\endgroup\$ – advapi Aug 4 '17 at 10:19
  • 1
    \$\begingroup\$ I think you need first refactor PostAsync. As I can see from your code this method can return many different types. I suggest to generalize return type of this method with kind of IPostResponse. As for parameter of the method I would define it as IPostRequest. And all request types should implement this interface. After these changes refactoring of repositories will be trivial. \$\endgroup\$ – Maxim Aug 4 '17 at 10:27
  • \$\begingroup\$ PostAsync is from ServiceStack \$\endgroup\$ – advapi Aug 4 '17 at 10:28
  • \$\begingroup\$ I am not sure but it seems that you can specify type of the response via generic type parameter of the method like PostAsync<IPostResponse>. I didn't work with ServiceStack but it looks configurable. \$\endgroup\$ – Maxim Aug 4 '17 at 10:36
1
\$\begingroup\$

If you must keep the code the same way, I can think of only reducing the repeated

var client = GetServiceStackClient();
return client.PostAsync(request);

by doing something like this:

public class DiagnosticsRepository : DefaultRepositoryBase, IDiagnosticsRepository
{
    public Task<IList<MasterDiagnostic>> GetMasterDiagnosticsFromType(int type)
    {
        var request = new MasterDiagnosticRequest()
        {
            MasterType = type
        };

        return Refactor<IList<MasterDiagnostic>, MasterDiagnosticRequest>.Get(request);
    }

    public Task<DiagnosticoDataResponse> GetMasterDiagnostic(string storedProcedure)
    {
        var request = new DiagnosticoDataRequest()
        {
            StoredProcedureName = storedProcedure,
            Data = DateTime.Today
        };

        return Refactor<DiagnosticoDataResponse, DiagnosticoDataRequest>.Get(request);
    }

    // get rid of the repetition... 
    private class Refactor<TRespone, TRequest>
    {
        public static Task<TRespone> Get(TRequest request)
        {
            var client = GetServiceStackClient();
            return client.PostAsync(request);
        }
    }
}

Frankly, I don't think you should have all these various methods and signatures at all. You could reduce the repository to just the methods that are usually found in a repository (ex: Add, Update, GetById, Delete, Etc...

Which would mean your repository would potentially just look like this instead:

public class DiagnosticsRepository<T> : IDiagnosticsRepository
{
    public static Task<T> Get(object request = default(object))
    {
        var client = GetServiceStackClient();
        return client.PostAsync(request);
    }
}

-The below is unconfirmed for your particular library, but based on my quick read of the documentation, this should work-
With the above minimized repository, if you like, you could go even further and swap your requests to anoymous types to reduce the amount of classes you are generating -- which is not uncommon especially for JSON requests. For example:

string storedProcedure = "...";
object request = new { StoredProcedureName = storedProcedure, Data = DateTime.Today };
var response = DiagnosticsRepository<DiagnosticoDataResponse>.Get(request);
\$\endgroup\$
  • \$\begingroup\$ I've not got spurce here... btw i was thinking of a Func<TResponse> in the base class...your approach of a static method is the same? Unfortunately I don't have CRUD operation... and access is 90% via StoredProcedures \$\endgroup\$ – advapi Aug 4 '17 at 20:11
  • \$\begingroup\$ I don't think you will make your code any easier to understand by adding more layers into your classes. I'd take a look at how to pass the generic types into .PostAsync<T>()and refactor based on that rather than using all these helper methods like XyzRequest() \$\endgroup\$ – Svek Aug 4 '17 at 20:16
  • \$\begingroup\$ xyzRequest are POCO used by ServiceStack to perform calls \$\endgroup\$ – advapi Aug 4 '17 at 20:18
  • \$\begingroup\$ @advapi - I'm certain it can be refactored... Have you tried sending an anonymous type on the request? Ex: new { Prop = val } instead of new XyzRequest { Prop = val }? -- If I am right, we just saved you from at least double the classes you're writing. \$\endgroup\$ – Svek Aug 4 '17 at 20:29
  • \$\begingroup\$ no Ive not... the advantage of this is that I've the POCO on the server side \$\endgroup\$ – advapi Aug 4 '17 at 20:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.