How to refactor two classes with very similar methods but using different types











up vote
0
down vote

favorite












I'm trying to master the refactoring for a project I'm working on right now. Basically I have two classes which each extend from an interface.



If you take a look at my code, you can observe that there is a lot of code duplication, as the methods' implementations across each class are almost exactly the same - they just use different object types (Though InvestmentRequests and FundingRequests also both implement the same interface).



So what would be the ideal approach for refactoring this code? Can it be done from the interface level? I've tried to do it by declaring the objects in my interface like so:



RequestsData allRequests = null;
RequestsData fixedRequests = null;
RequestsData trackerRequests = null;


but that doesn't look like what I'm trying to do, and I'm unsure of the syntax.



Interface



public interface RequestDataBase<E,T> {

T getAllRequests();

T getFixedRequests();

T getTrackerRequests();

void add(E newRequest);

void addAll(List<E> accounts);
}


Class A



public class FundingRequestData implements RequestDataBase<FundingRequest,FundingRequestData.FundingRequests> {

private static FundingRequests fundingRequests;
private static FundingRequests fixedFundingRequests;
private static FundingRequests trackerFundingRequests;

private static FundingRequestData instance = new FundingRequestData();

public static FundingRequestData getInstance() {
return instance;
}

private FundingRequestData() {
fundingRequests = new FundingRequests();
fixedFundingRequests = new FundingRequests();
trackerFundingRequests = new FundingRequests();
}

@Override
public FundingRequests getAllRequests() {
return fundingRequests;
}

@Override
public FundingRequests getFixedRequests() {
return fixedFundingRequests;
}

@Override
public FundingRequests getTrackerRequests() {
return trackerFundingRequests;
}

private void listSpecifier(FundingRequest request) {
if (request.getType().equals("FIXED")) {
fixedFundingRequests.add(request);
} else {
trackerFundingRequests.add(request);
}
}

@Override
public void add(FundingRequest newRequest) {
fundingRequests.add(newRequest);
listSpecifier(newRequest);
}

@Override
public void addAll(List<FundingRequest> accounts) {
fundingRequests.getRequests().addAll(accounts);
for (FundingRequest request : accounts) {
listSpecifier(request);
}
}


Class B



public class InvestmentRequestData implements RequestDataBase<InvestmentRequest,InvestmentRequestData.InvestmentRequests> {
private static InvestmentRequests investmentRequests;
private static InvestmentRequests fixedInvestmentRequests;
private static InvestmentRequests trackerInvestmentRequests;

private static InvestmentRequestData instance = new InvestmentRequestData();

public static InvestmentRequestData getInstance() { return instance; }

private InvestmentRequestData() {
investmentRequests = new InvestmentRequests();
fixedInvestmentRequests = new InvestmentRequests();
trackerInvestmentRequests = new InvestmentRequests();
}

public void investAll() {
for (InvestmentRequest request : investmentRequests.getUnfulfilledRequests()) {
request.investAll();
}
}

public InvestmentRequests getAllRequests() {
return investmentRequests;
}

public InvestmentRequests getFixedRequests() { return fixedInvestmentRequests; }

public InvestmentRequests getTrackerRequests() {
return trackerInvestmentRequests;
}

private void listSpecifier(InvestmentRequest newRequest) {
if(newRequest.getType().equals("FIXED")) {
fixedInvestmentRequests.add(newRequest);
} else {
trackerInvestmentRequests.add(newRequest);
}
}

public void add(InvestmentRequest newRequest) {
investmentRequests.add(newRequest);

listSpecifier(newRequest);
}

public void addAll(List<InvestmentRequest> newRequests) {
for (InvestmentRequest request : newRequests) {
listSpecifier(request);
}
}









share|improve this question


















  • 3




    What about an abstract superclass?
    – Glains
    Nov 9 at 16:11










  • @Glains I didn't think that would work when the types I was using were different?
    – j panton
    Nov 9 at 16:13






  • 1




    No need to declare variables other then instance as static. Also you can have abstract class be parametrized just like you do with RequestDataBase.
    – tsolakp
    Nov 9 at 16:14










  • @tsolakp Yeah you're right, I'll change that.
    – j panton
    Nov 9 at 16:15















up vote
0
down vote

favorite












I'm trying to master the refactoring for a project I'm working on right now. Basically I have two classes which each extend from an interface.



If you take a look at my code, you can observe that there is a lot of code duplication, as the methods' implementations across each class are almost exactly the same - they just use different object types (Though InvestmentRequests and FundingRequests also both implement the same interface).



So what would be the ideal approach for refactoring this code? Can it be done from the interface level? I've tried to do it by declaring the objects in my interface like so:



RequestsData allRequests = null;
RequestsData fixedRequests = null;
RequestsData trackerRequests = null;


but that doesn't look like what I'm trying to do, and I'm unsure of the syntax.



Interface



public interface RequestDataBase<E,T> {

T getAllRequests();

T getFixedRequests();

T getTrackerRequests();

void add(E newRequest);

void addAll(List<E> accounts);
}


Class A



public class FundingRequestData implements RequestDataBase<FundingRequest,FundingRequestData.FundingRequests> {

private static FundingRequests fundingRequests;
private static FundingRequests fixedFundingRequests;
private static FundingRequests trackerFundingRequests;

private static FundingRequestData instance = new FundingRequestData();

public static FundingRequestData getInstance() {
return instance;
}

private FundingRequestData() {
fundingRequests = new FundingRequests();
fixedFundingRequests = new FundingRequests();
trackerFundingRequests = new FundingRequests();
}

@Override
public FundingRequests getAllRequests() {
return fundingRequests;
}

@Override
public FundingRequests getFixedRequests() {
return fixedFundingRequests;
}

@Override
public FundingRequests getTrackerRequests() {
return trackerFundingRequests;
}

private void listSpecifier(FundingRequest request) {
if (request.getType().equals("FIXED")) {
fixedFundingRequests.add(request);
} else {
trackerFundingRequests.add(request);
}
}

@Override
public void add(FundingRequest newRequest) {
fundingRequests.add(newRequest);
listSpecifier(newRequest);
}

@Override
public void addAll(List<FundingRequest> accounts) {
fundingRequests.getRequests().addAll(accounts);
for (FundingRequest request : accounts) {
listSpecifier(request);
}
}


Class B



public class InvestmentRequestData implements RequestDataBase<InvestmentRequest,InvestmentRequestData.InvestmentRequests> {
private static InvestmentRequests investmentRequests;
private static InvestmentRequests fixedInvestmentRequests;
private static InvestmentRequests trackerInvestmentRequests;

private static InvestmentRequestData instance = new InvestmentRequestData();

public static InvestmentRequestData getInstance() { return instance; }

private InvestmentRequestData() {
investmentRequests = new InvestmentRequests();
fixedInvestmentRequests = new InvestmentRequests();
trackerInvestmentRequests = new InvestmentRequests();
}

public void investAll() {
for (InvestmentRequest request : investmentRequests.getUnfulfilledRequests()) {
request.investAll();
}
}

public InvestmentRequests getAllRequests() {
return investmentRequests;
}

public InvestmentRequests getFixedRequests() { return fixedInvestmentRequests; }

public InvestmentRequests getTrackerRequests() {
return trackerInvestmentRequests;
}

private void listSpecifier(InvestmentRequest newRequest) {
if(newRequest.getType().equals("FIXED")) {
fixedInvestmentRequests.add(newRequest);
} else {
trackerInvestmentRequests.add(newRequest);
}
}

public void add(InvestmentRequest newRequest) {
investmentRequests.add(newRequest);

listSpecifier(newRequest);
}

public void addAll(List<InvestmentRequest> newRequests) {
for (InvestmentRequest request : newRequests) {
listSpecifier(request);
}
}









share|improve this question


















  • 3




    What about an abstract superclass?
    – Glains
    Nov 9 at 16:11










  • @Glains I didn't think that would work when the types I was using were different?
    – j panton
    Nov 9 at 16:13






  • 1




    No need to declare variables other then instance as static. Also you can have abstract class be parametrized just like you do with RequestDataBase.
    – tsolakp
    Nov 9 at 16:14










  • @tsolakp Yeah you're right, I'll change that.
    – j panton
    Nov 9 at 16:15













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm trying to master the refactoring for a project I'm working on right now. Basically I have two classes which each extend from an interface.



If you take a look at my code, you can observe that there is a lot of code duplication, as the methods' implementations across each class are almost exactly the same - they just use different object types (Though InvestmentRequests and FundingRequests also both implement the same interface).



So what would be the ideal approach for refactoring this code? Can it be done from the interface level? I've tried to do it by declaring the objects in my interface like so:



RequestsData allRequests = null;
RequestsData fixedRequests = null;
RequestsData trackerRequests = null;


but that doesn't look like what I'm trying to do, and I'm unsure of the syntax.



Interface



public interface RequestDataBase<E,T> {

T getAllRequests();

T getFixedRequests();

T getTrackerRequests();

void add(E newRequest);

void addAll(List<E> accounts);
}


Class A



public class FundingRequestData implements RequestDataBase<FundingRequest,FundingRequestData.FundingRequests> {

private static FundingRequests fundingRequests;
private static FundingRequests fixedFundingRequests;
private static FundingRequests trackerFundingRequests;

private static FundingRequestData instance = new FundingRequestData();

public static FundingRequestData getInstance() {
return instance;
}

private FundingRequestData() {
fundingRequests = new FundingRequests();
fixedFundingRequests = new FundingRequests();
trackerFundingRequests = new FundingRequests();
}

@Override
public FundingRequests getAllRequests() {
return fundingRequests;
}

@Override
public FundingRequests getFixedRequests() {
return fixedFundingRequests;
}

@Override
public FundingRequests getTrackerRequests() {
return trackerFundingRequests;
}

private void listSpecifier(FundingRequest request) {
if (request.getType().equals("FIXED")) {
fixedFundingRequests.add(request);
} else {
trackerFundingRequests.add(request);
}
}

@Override
public void add(FundingRequest newRequest) {
fundingRequests.add(newRequest);
listSpecifier(newRequest);
}

@Override
public void addAll(List<FundingRequest> accounts) {
fundingRequests.getRequests().addAll(accounts);
for (FundingRequest request : accounts) {
listSpecifier(request);
}
}


Class B



public class InvestmentRequestData implements RequestDataBase<InvestmentRequest,InvestmentRequestData.InvestmentRequests> {
private static InvestmentRequests investmentRequests;
private static InvestmentRequests fixedInvestmentRequests;
private static InvestmentRequests trackerInvestmentRequests;

private static InvestmentRequestData instance = new InvestmentRequestData();

public static InvestmentRequestData getInstance() { return instance; }

private InvestmentRequestData() {
investmentRequests = new InvestmentRequests();
fixedInvestmentRequests = new InvestmentRequests();
trackerInvestmentRequests = new InvestmentRequests();
}

public void investAll() {
for (InvestmentRequest request : investmentRequests.getUnfulfilledRequests()) {
request.investAll();
}
}

public InvestmentRequests getAllRequests() {
return investmentRequests;
}

public InvestmentRequests getFixedRequests() { return fixedInvestmentRequests; }

public InvestmentRequests getTrackerRequests() {
return trackerInvestmentRequests;
}

private void listSpecifier(InvestmentRequest newRequest) {
if(newRequest.getType().equals("FIXED")) {
fixedInvestmentRequests.add(newRequest);
} else {
trackerInvestmentRequests.add(newRequest);
}
}

public void add(InvestmentRequest newRequest) {
investmentRequests.add(newRequest);

listSpecifier(newRequest);
}

public void addAll(List<InvestmentRequest> newRequests) {
for (InvestmentRequest request : newRequests) {
listSpecifier(request);
}
}









share|improve this question













I'm trying to master the refactoring for a project I'm working on right now. Basically I have two classes which each extend from an interface.



If you take a look at my code, you can observe that there is a lot of code duplication, as the methods' implementations across each class are almost exactly the same - they just use different object types (Though InvestmentRequests and FundingRequests also both implement the same interface).



So what would be the ideal approach for refactoring this code? Can it be done from the interface level? I've tried to do it by declaring the objects in my interface like so:



RequestsData allRequests = null;
RequestsData fixedRequests = null;
RequestsData trackerRequests = null;


but that doesn't look like what I'm trying to do, and I'm unsure of the syntax.



Interface



public interface RequestDataBase<E,T> {

T getAllRequests();

T getFixedRequests();

T getTrackerRequests();

void add(E newRequest);

void addAll(List<E> accounts);
}


Class A



public class FundingRequestData implements RequestDataBase<FundingRequest,FundingRequestData.FundingRequests> {

private static FundingRequests fundingRequests;
private static FundingRequests fixedFundingRequests;
private static FundingRequests trackerFundingRequests;

private static FundingRequestData instance = new FundingRequestData();

public static FundingRequestData getInstance() {
return instance;
}

private FundingRequestData() {
fundingRequests = new FundingRequests();
fixedFundingRequests = new FundingRequests();
trackerFundingRequests = new FundingRequests();
}

@Override
public FundingRequests getAllRequests() {
return fundingRequests;
}

@Override
public FundingRequests getFixedRequests() {
return fixedFundingRequests;
}

@Override
public FundingRequests getTrackerRequests() {
return trackerFundingRequests;
}

private void listSpecifier(FundingRequest request) {
if (request.getType().equals("FIXED")) {
fixedFundingRequests.add(request);
} else {
trackerFundingRequests.add(request);
}
}

@Override
public void add(FundingRequest newRequest) {
fundingRequests.add(newRequest);
listSpecifier(newRequest);
}

@Override
public void addAll(List<FundingRequest> accounts) {
fundingRequests.getRequests().addAll(accounts);
for (FundingRequest request : accounts) {
listSpecifier(request);
}
}


Class B



public class InvestmentRequestData implements RequestDataBase<InvestmentRequest,InvestmentRequestData.InvestmentRequests> {
private static InvestmentRequests investmentRequests;
private static InvestmentRequests fixedInvestmentRequests;
private static InvestmentRequests trackerInvestmentRequests;

private static InvestmentRequestData instance = new InvestmentRequestData();

public static InvestmentRequestData getInstance() { return instance; }

private InvestmentRequestData() {
investmentRequests = new InvestmentRequests();
fixedInvestmentRequests = new InvestmentRequests();
trackerInvestmentRequests = new InvestmentRequests();
}

public void investAll() {
for (InvestmentRequest request : investmentRequests.getUnfulfilledRequests()) {
request.investAll();
}
}

public InvestmentRequests getAllRequests() {
return investmentRequests;
}

public InvestmentRequests getFixedRequests() { return fixedInvestmentRequests; }

public InvestmentRequests getTrackerRequests() {
return trackerInvestmentRequests;
}

private void listSpecifier(InvestmentRequest newRequest) {
if(newRequest.getType().equals("FIXED")) {
fixedInvestmentRequests.add(newRequest);
} else {
trackerInvestmentRequests.add(newRequest);
}
}

public void add(InvestmentRequest newRequest) {
investmentRequests.add(newRequest);

listSpecifier(newRequest);
}

public void addAll(List<InvestmentRequest> newRequests) {
for (InvestmentRequest request : newRequests) {
listSpecifier(request);
}
}






java oop types interface refactoring






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 9 at 16:07









j panton

907




907








  • 3




    What about an abstract superclass?
    – Glains
    Nov 9 at 16:11










  • @Glains I didn't think that would work when the types I was using were different?
    – j panton
    Nov 9 at 16:13






  • 1




    No need to declare variables other then instance as static. Also you can have abstract class be parametrized just like you do with RequestDataBase.
    – tsolakp
    Nov 9 at 16:14










  • @tsolakp Yeah you're right, I'll change that.
    – j panton
    Nov 9 at 16:15














  • 3




    What about an abstract superclass?
    – Glains
    Nov 9 at 16:11










  • @Glains I didn't think that would work when the types I was using were different?
    – j panton
    Nov 9 at 16:13






  • 1




    No need to declare variables other then instance as static. Also you can have abstract class be parametrized just like you do with RequestDataBase.
    – tsolakp
    Nov 9 at 16:14










  • @tsolakp Yeah you're right, I'll change that.
    – j panton
    Nov 9 at 16:15








3




3




What about an abstract superclass?
– Glains
Nov 9 at 16:11




What about an abstract superclass?
– Glains
Nov 9 at 16:11












@Glains I didn't think that would work when the types I was using were different?
– j panton
Nov 9 at 16:13




@Glains I didn't think that would work when the types I was using were different?
– j panton
Nov 9 at 16:13




1




1




No need to declare variables other then instance as static. Also you can have abstract class be parametrized just like you do with RequestDataBase.
– tsolakp
Nov 9 at 16:14




No need to declare variables other then instance as static. Also you can have abstract class be parametrized just like you do with RequestDataBase.
– tsolakp
Nov 9 at 16:14












@tsolakp Yeah you're right, I'll change that.
– j panton
Nov 9 at 16:15




@tsolakp Yeah you're right, I'll change that.
– j panton
Nov 9 at 16:15












2 Answers
2






active

oldest

votes

















up vote
1
down vote













You won't be able to refractor the generic objects on the interface level otherwise you would be refractoring both FundingRequest(s) and InvestmentRequest(s) to the same object, which I don't think is what you intend.



I would refractor the objects within class A and B. However, the general design can probably be improved. Something like having InvestmentRequest and FundingRequest implementing a Request interface, so instead of using generics E and T in the RequestDataBase interface, you can use Request and Requests objects.






share|improve this answer




























    up vote
    1
    down vote













    If FundingRequest and InvestmentRequest both implement the same interface (Request) then you should only ever deal with Requests.



    If you code your class to only interact with Requests, I'm guessing you encounter some cases where you have to treat the two types differently (otherwise you'd already be done!)



    If you have to treat them differently, I suggest a two-step refactor (Run unit tests between each step!)



    First use if(x instanceof FundingRequest) to choose one code path or the other. This lets you make a minimum refactor that should work. The goal of this part is to condense the two classes you are discussing into a single class.



    Do not stop there though, After you get it all refactored like that, now you need to push those instanceofs into the two request classes. Possibly add a new method to the interface that calls an implementation and put one path of that if() statement into FundingRequest and the other into InvestmentRequest.



    When you are done with this part of the refactor your class should only refer to "Requests", never FundingRequest or InvestmentRequest.






    share|improve this answer





















    • I really like that solution. As my InvestmentRequests and my FundingRequests have some attributes and methods specific to each - is this information not lost when I generify them into a request?
      – j panton
      Nov 9 at 17:26










    • Where they are different they still have the different information inside the objects. If you the need the "Different" information for, say, a report you might call Request.createReport() and the two different classes would have their implementation fill out the report correctly using the hidden information that only that implementation knows. You may need to implement a few more methods in your interface before you can completely hide the differences between the two classes.
      – Bill K
      Nov 9 at 19:02












    • Oh also if you really have to you can use something like this: if(request instanceof InvestmentRequest){ ((InvestmentRequest)request).methodSpecificToInvestmentRequest();} But this is considered bad form--try to find ways to avoid it if you can.
      – Bill K
      Nov 9 at 19:16










    • Would your solution not mean a lot of casting, either way? How do I start treating the Request object like a FundingRequest or InvestmentRequest without casting
      – j panton
      Nov 9 at 21:04












    • Additionally, I have methods which I need public but specific to one class - does that not make the combination into a single class, bad design?
      – j panton
      Nov 9 at 21:12











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53229324%2fhow-to-refactor-two-classes-with-very-similar-methods-but-using-different-types%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote













    You won't be able to refractor the generic objects on the interface level otherwise you would be refractoring both FundingRequest(s) and InvestmentRequest(s) to the same object, which I don't think is what you intend.



    I would refractor the objects within class A and B. However, the general design can probably be improved. Something like having InvestmentRequest and FundingRequest implementing a Request interface, so instead of using generics E and T in the RequestDataBase interface, you can use Request and Requests objects.






    share|improve this answer

























      up vote
      1
      down vote













      You won't be able to refractor the generic objects on the interface level otherwise you would be refractoring both FundingRequest(s) and InvestmentRequest(s) to the same object, which I don't think is what you intend.



      I would refractor the objects within class A and B. However, the general design can probably be improved. Something like having InvestmentRequest and FundingRequest implementing a Request interface, so instead of using generics E and T in the RequestDataBase interface, you can use Request and Requests objects.






      share|improve this answer























        up vote
        1
        down vote










        up vote
        1
        down vote









        You won't be able to refractor the generic objects on the interface level otherwise you would be refractoring both FundingRequest(s) and InvestmentRequest(s) to the same object, which I don't think is what you intend.



        I would refractor the objects within class A and B. However, the general design can probably be improved. Something like having InvestmentRequest and FundingRequest implementing a Request interface, so instead of using generics E and T in the RequestDataBase interface, you can use Request and Requests objects.






        share|improve this answer












        You won't be able to refractor the generic objects on the interface level otherwise you would be refractoring both FundingRequest(s) and InvestmentRequest(s) to the same object, which I don't think is what you intend.



        I would refractor the objects within class A and B. However, the general design can probably be improved. Something like having InvestmentRequest and FundingRequest implementing a Request interface, so instead of using generics E and T in the RequestDataBase interface, you can use Request and Requests objects.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 9 at 16:19









        Panda

        163




        163
























            up vote
            1
            down vote













            If FundingRequest and InvestmentRequest both implement the same interface (Request) then you should only ever deal with Requests.



            If you code your class to only interact with Requests, I'm guessing you encounter some cases where you have to treat the two types differently (otherwise you'd already be done!)



            If you have to treat them differently, I suggest a two-step refactor (Run unit tests between each step!)



            First use if(x instanceof FundingRequest) to choose one code path or the other. This lets you make a minimum refactor that should work. The goal of this part is to condense the two classes you are discussing into a single class.



            Do not stop there though, After you get it all refactored like that, now you need to push those instanceofs into the two request classes. Possibly add a new method to the interface that calls an implementation and put one path of that if() statement into FundingRequest and the other into InvestmentRequest.



            When you are done with this part of the refactor your class should only refer to "Requests", never FundingRequest or InvestmentRequest.






            share|improve this answer





















            • I really like that solution. As my InvestmentRequests and my FundingRequests have some attributes and methods specific to each - is this information not lost when I generify them into a request?
              – j panton
              Nov 9 at 17:26










            • Where they are different they still have the different information inside the objects. If you the need the "Different" information for, say, a report you might call Request.createReport() and the two different classes would have their implementation fill out the report correctly using the hidden information that only that implementation knows. You may need to implement a few more methods in your interface before you can completely hide the differences between the two classes.
              – Bill K
              Nov 9 at 19:02












            • Oh also if you really have to you can use something like this: if(request instanceof InvestmentRequest){ ((InvestmentRequest)request).methodSpecificToInvestmentRequest();} But this is considered bad form--try to find ways to avoid it if you can.
              – Bill K
              Nov 9 at 19:16










            • Would your solution not mean a lot of casting, either way? How do I start treating the Request object like a FundingRequest or InvestmentRequest without casting
              – j panton
              Nov 9 at 21:04












            • Additionally, I have methods which I need public but specific to one class - does that not make the combination into a single class, bad design?
              – j panton
              Nov 9 at 21:12















            up vote
            1
            down vote













            If FundingRequest and InvestmentRequest both implement the same interface (Request) then you should only ever deal with Requests.



            If you code your class to only interact with Requests, I'm guessing you encounter some cases where you have to treat the two types differently (otherwise you'd already be done!)



            If you have to treat them differently, I suggest a two-step refactor (Run unit tests between each step!)



            First use if(x instanceof FundingRequest) to choose one code path or the other. This lets you make a minimum refactor that should work. The goal of this part is to condense the two classes you are discussing into a single class.



            Do not stop there though, After you get it all refactored like that, now you need to push those instanceofs into the two request classes. Possibly add a new method to the interface that calls an implementation and put one path of that if() statement into FundingRequest and the other into InvestmentRequest.



            When you are done with this part of the refactor your class should only refer to "Requests", never FundingRequest or InvestmentRequest.






            share|improve this answer





















            • I really like that solution. As my InvestmentRequests and my FundingRequests have some attributes and methods specific to each - is this information not lost when I generify them into a request?
              – j panton
              Nov 9 at 17:26










            • Where they are different they still have the different information inside the objects. If you the need the "Different" information for, say, a report you might call Request.createReport() and the two different classes would have their implementation fill out the report correctly using the hidden information that only that implementation knows. You may need to implement a few more methods in your interface before you can completely hide the differences between the two classes.
              – Bill K
              Nov 9 at 19:02












            • Oh also if you really have to you can use something like this: if(request instanceof InvestmentRequest){ ((InvestmentRequest)request).methodSpecificToInvestmentRequest();} But this is considered bad form--try to find ways to avoid it if you can.
              – Bill K
              Nov 9 at 19:16










            • Would your solution not mean a lot of casting, either way? How do I start treating the Request object like a FundingRequest or InvestmentRequest without casting
              – j panton
              Nov 9 at 21:04












            • Additionally, I have methods which I need public but specific to one class - does that not make the combination into a single class, bad design?
              – j panton
              Nov 9 at 21:12













            up vote
            1
            down vote










            up vote
            1
            down vote









            If FundingRequest and InvestmentRequest both implement the same interface (Request) then you should only ever deal with Requests.



            If you code your class to only interact with Requests, I'm guessing you encounter some cases where you have to treat the two types differently (otherwise you'd already be done!)



            If you have to treat them differently, I suggest a two-step refactor (Run unit tests between each step!)



            First use if(x instanceof FundingRequest) to choose one code path or the other. This lets you make a minimum refactor that should work. The goal of this part is to condense the two classes you are discussing into a single class.



            Do not stop there though, After you get it all refactored like that, now you need to push those instanceofs into the two request classes. Possibly add a new method to the interface that calls an implementation and put one path of that if() statement into FundingRequest and the other into InvestmentRequest.



            When you are done with this part of the refactor your class should only refer to "Requests", never FundingRequest or InvestmentRequest.






            share|improve this answer












            If FundingRequest and InvestmentRequest both implement the same interface (Request) then you should only ever deal with Requests.



            If you code your class to only interact with Requests, I'm guessing you encounter some cases where you have to treat the two types differently (otherwise you'd already be done!)



            If you have to treat them differently, I suggest a two-step refactor (Run unit tests between each step!)



            First use if(x instanceof FundingRequest) to choose one code path or the other. This lets you make a minimum refactor that should work. The goal of this part is to condense the two classes you are discussing into a single class.



            Do not stop there though, After you get it all refactored like that, now you need to push those instanceofs into the two request classes. Possibly add a new method to the interface that calls an implementation and put one path of that if() statement into FundingRequest and the other into InvestmentRequest.



            When you are done with this part of the refactor your class should only refer to "Requests", never FundingRequest or InvestmentRequest.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 9 at 17:22









            Bill K

            52.9k1385137




            52.9k1385137












            • I really like that solution. As my InvestmentRequests and my FundingRequests have some attributes and methods specific to each - is this information not lost when I generify them into a request?
              – j panton
              Nov 9 at 17:26










            • Where they are different they still have the different information inside the objects. If you the need the "Different" information for, say, a report you might call Request.createReport() and the two different classes would have their implementation fill out the report correctly using the hidden information that only that implementation knows. You may need to implement a few more methods in your interface before you can completely hide the differences between the two classes.
              – Bill K
              Nov 9 at 19:02












            • Oh also if you really have to you can use something like this: if(request instanceof InvestmentRequest){ ((InvestmentRequest)request).methodSpecificToInvestmentRequest();} But this is considered bad form--try to find ways to avoid it if you can.
              – Bill K
              Nov 9 at 19:16










            • Would your solution not mean a lot of casting, either way? How do I start treating the Request object like a FundingRequest or InvestmentRequest without casting
              – j panton
              Nov 9 at 21:04












            • Additionally, I have methods which I need public but specific to one class - does that not make the combination into a single class, bad design?
              – j panton
              Nov 9 at 21:12


















            • I really like that solution. As my InvestmentRequests and my FundingRequests have some attributes and methods specific to each - is this information not lost when I generify them into a request?
              – j panton
              Nov 9 at 17:26










            • Where they are different they still have the different information inside the objects. If you the need the "Different" information for, say, a report you might call Request.createReport() and the two different classes would have their implementation fill out the report correctly using the hidden information that only that implementation knows. You may need to implement a few more methods in your interface before you can completely hide the differences between the two classes.
              – Bill K
              Nov 9 at 19:02












            • Oh also if you really have to you can use something like this: if(request instanceof InvestmentRequest){ ((InvestmentRequest)request).methodSpecificToInvestmentRequest();} But this is considered bad form--try to find ways to avoid it if you can.
              – Bill K
              Nov 9 at 19:16










            • Would your solution not mean a lot of casting, either way? How do I start treating the Request object like a FundingRequest or InvestmentRequest without casting
              – j panton
              Nov 9 at 21:04












            • Additionally, I have methods which I need public but specific to one class - does that not make the combination into a single class, bad design?
              – j panton
              Nov 9 at 21:12
















            I really like that solution. As my InvestmentRequests and my FundingRequests have some attributes and methods specific to each - is this information not lost when I generify them into a request?
            – j panton
            Nov 9 at 17:26




            I really like that solution. As my InvestmentRequests and my FundingRequests have some attributes and methods specific to each - is this information not lost when I generify them into a request?
            – j panton
            Nov 9 at 17:26












            Where they are different they still have the different information inside the objects. If you the need the "Different" information for, say, a report you might call Request.createReport() and the two different classes would have their implementation fill out the report correctly using the hidden information that only that implementation knows. You may need to implement a few more methods in your interface before you can completely hide the differences between the two classes.
            – Bill K
            Nov 9 at 19:02






            Where they are different they still have the different information inside the objects. If you the need the "Different" information for, say, a report you might call Request.createReport() and the two different classes would have their implementation fill out the report correctly using the hidden information that only that implementation knows. You may need to implement a few more methods in your interface before you can completely hide the differences between the two classes.
            – Bill K
            Nov 9 at 19:02














            Oh also if you really have to you can use something like this: if(request instanceof InvestmentRequest){ ((InvestmentRequest)request).methodSpecificToInvestmentRequest();} But this is considered bad form--try to find ways to avoid it if you can.
            – Bill K
            Nov 9 at 19:16




            Oh also if you really have to you can use something like this: if(request instanceof InvestmentRequest){ ((InvestmentRequest)request).methodSpecificToInvestmentRequest();} But this is considered bad form--try to find ways to avoid it if you can.
            – Bill K
            Nov 9 at 19:16












            Would your solution not mean a lot of casting, either way? How do I start treating the Request object like a FundingRequest or InvestmentRequest without casting
            – j panton
            Nov 9 at 21:04






            Would your solution not mean a lot of casting, either way? How do I start treating the Request object like a FundingRequest or InvestmentRequest without casting
            – j panton
            Nov 9 at 21:04














            Additionally, I have methods which I need public but specific to one class - does that not make the combination into a single class, bad design?
            – j panton
            Nov 9 at 21:12




            Additionally, I have methods which I need public but specific to one class - does that not make the combination into a single class, bad design?
            – j panton
            Nov 9 at 21:12


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53229324%2fhow-to-refactor-two-classes-with-very-similar-methods-but-using-different-types%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Xamarin.form Move up view when keyboard appear

            Post-Redirect-Get with Spring WebFlux and Thymeleaf

            Anylogic : not able to use stopDelay()