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);
}
}
java oop types interface refactoring
add a comment |
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);
}
}
java oop types interface refactoring
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 theninstance
as static. Also you can have abstract class be parametrized just like you do withRequestDataBase
.
– tsolakp
Nov 9 at 16:14
@tsolakp Yeah you're right, I'll change that.
– j panton
Nov 9 at 16:15
add a comment |
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);
}
}
java oop types interface refactoring
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
java oop types interface refactoring
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 theninstance
as static. Also you can have abstract class be parametrized just like you do withRequestDataBase
.
– tsolakp
Nov 9 at 16:14
@tsolakp Yeah you're right, I'll change that.
– j panton
Nov 9 at 16:15
add a comment |
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 theninstance
as static. Also you can have abstract class be parametrized just like you do withRequestDataBase
.
– 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
add a comment |
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.
add a comment |
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.
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
|
show 1 more comment
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 9 at 16:19
Panda
163
163
add a comment |
add a comment |
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.
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
|
show 1 more comment
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.
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
|
show 1 more comment
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.
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.
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
|
show 1 more comment
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
|
show 1 more comment
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 withRequestDataBase
.– tsolakp
Nov 9 at 16:14
@tsolakp Yeah you're right, I'll change that.
– j panton
Nov 9 at 16:15