메서드에 많은 인수를 전달하는 모범 사례?
때때로, 우리는 많은 인수를받는 메소드를 작성해야합니다. 예를 들면 다음과 같습니다.
public void doSomething(Object objA , Object objectB ,Date date1 ,Date date2 ,String str1 ,String str2 )
{
}
이런 종류의 문제가 발생하면 종종 인수를지도에 캡슐화합니다.
Map<Object,Object> params = new HashMap<Object,Object>();
params.put("objA",ObjA) ;
......
public void doSomething(Map<Object,Object> params)
{
// extracting params
Object objA = (Object)params.get("objA");
......
}
이것은 좋은 습관이 아닙니다. 매개 변수를 맵으로 캡슐화하는 것은 완전히 효율성을 낭비하는 것입니다. 좋은 점은 깨끗한 시그니처이며 최소한의 수정으로 다른 매개 변수를 쉽게 추가 할 수 있다는 것입니다. 이런 종류의 문제에 대한 모범 사례는 무엇입니까?
에 효과적인 자바 , 7 장 (방법), 항목 40 (디자인 방법 서명 조심스럽게), 블로흐의 글 :
지나치게 긴 매개 변수 목록을 줄이는 세 가지 기술이 있습니다.
- 메서드를 여러 메서드로 나눕니다. 각 메서드에는 매개 변수의 하위 집합 만 필요합니다.
- 매개 변수 그룹 (일반적으로 정적 멤버 클래스)을 보유하기위한 도우미 클래스 생성
- 객체 생성에서 메소드 호출에 빌더 패턴을 적용합니다.
자세한 내용은 책을 구입하는 것이 좋습니다. 그만한 가치가 있습니다.
마법의 문자열 키가있는 맵을 사용하는 것은 나쁜 생각입니다. 컴파일 시간 검사를 잃고 필요한 매개 변수가 무엇인지 정말 불분명합니다. 이를 보완하려면 매우 완전한 문서를 작성해야합니다. 몇 주 안에 코드를 보지 않고도 문자열이 무엇인지 기억할 수 있습니까? 오타를 만들면 어떻게 되나요? 잘못된 유형을 사용하십니까? 코드를 실행하기 전까지는 알 수 없습니다.
대신 모델을 사용하십시오. 모든 매개 변수에 대한 컨테이너가 될 클래스를 만듭니다. 그렇게하면 Java의 유형 안전성을 유지할 수 있습니다. 해당 객체를 다른 메서드로 전달하거나 컬렉션에 넣을 수도 있습니다.
물론 매개 변수 집합이 다른 곳에서 사용되지 않거나 전달되지 않으면 전용 모델이 과도해질 수 있습니다. 쳐야 할 균형이 있으므로 상식을 사용하십시오.
선택적 매개 변수가 많으면 유창한 API를 만들 수 있습니다. 단일 메소드를 메소드 체인으로 대체
exportWithParams().datesBetween(date1,date2)
.format("xml")
.columns("id","name","phone")
.table("angry_robots")
.invoke();
정적 가져 오기를 사용하여 내부 유창한 API를 만들 수 있습니다.
... .datesBetween(from(date1).to(date2)) ...
"Introduce Parameter Object"라고합니다. 여러 위치에 동일한 매개 변수 목록을 전달하는 경우 모두를 보유하는 클래스를 작성하십시오.
XXXParameter param = new XXXParameter(objA, objB, date1, date2, str1, str2);
// ...
doSomething(param);
동일한 매개 변수 목록을 너무 자주 전달하지 않더라도 쉽게 리팩토링하면 코드 가독성이 향상되며 이는 항상 좋습니다. 3 개월 후 코드를 보면 버그를 수정하거나 기능을 추가해야 할 때 이해하기가 더 쉬울 것입니다.
It's a general philosophy of course, and since you haven't provided any details, I cannot give you more detailed advice either. :-)
First, I'd try to refactor the method. If it's using that many parameters it may be too long any way. Breaking it down would both improve the code and potentially reduce the number of parameters to each method. You might also be able to refactor the entire operation to its own class. Second, I'd look for other instances where I'm using the same (or superset) of the same parameter list. If you have multiple instances, then it likely signals that these properties belong together. In that case, create a class to hold the parameters and use it. Lastly, I'd evaluate whether the number of parameters makes it worth creating a map object to improve code readability. I think this is a personal call -- there is pain each way with this solution and where the trade-off point is may differ. For six parameters I probably wouldn't do it. For 10 I probably would (if none of the other methods worked first).
This is often a problem when constructing objects.
In that case use builder object pattern, it works well if you have big list of parameters and not always need all of them.
You can also adapt it to method invocation.
It also increases readability a lot.
public class BigObject
{
// public getters
// private setters
public static class Buider
{
private A f1;
private B f2;
private C f3;
private D f4;
private E f5;
public Buider setField1(A f1) { this.f1 = f1; return this; }
public Buider setField2(B f2) { this.f2 = f2; return this; }
public Buider setField3(C f3) { this.f3 = f3; return this; }
public Buider setField4(D f4) { this.f4 = f4; return this; }
public Buider setField5(E f5) { this.f5 = f5; return this; }
public BigObject build()
{
BigObject result = new BigObject();
result.setField1(f1);
result.setField2(f2);
result.setField3(f3);
result.setField4(f4);
result.setField5(f5);
return result;
}
}
}
// Usage:
BigObject boo = new BigObject.Builder()
.setField1(/* whatever */)
.setField2(/* whatever */)
.setField3(/* whatever */)
.setField4(/* whatever */)
.setField5(/* whatever */)
.build();
You can also put verification logic into Builder set..() and build() methods.
There is a pattern called as Parameter object.
Idea is to use one object in place of all the parameters. Now even if you need to add parameters later, you just need to add it to the object. The method interface remains same.
You could create a class to hold that data. Needs to be meaningful enough though, but much better than using a map (OMG).
Code Complete* suggests a couple of things:
- "Limit the number of a routine's parameters to about seven. Seven is a magic number for people's comprehension" (p 108).
- "Put parameters in input-modify-output order ... If several routines use similar parameters, put the similar parameters in a consistent order" (p 105).
- Put status or error variables last.
- As tvanfosson mentioned, pass only the parts of a structured variables ( objects) that the routine needs. That said, if you're using most of the structured variable in the function, then just pass the whole structure, but be aware that this promotes coupling to some degree.
* First Edition, I know I should update. Also, it's likely that some of this advice may have changed since the second edition was written when OOP was beginning to become more popular.
Good practice would be to refactor. What about these objects means that they should be passed in to this method? Should they be encapsulated into a single object?
Using a Map is a simple way to clean the call signature but then you have another problem. You need to look inside the method's body to see what the method expects in that Map, what are the key names or what types the values have.
A cleaner way would be to group all parameters in an object bean but that still does not fix the problem entirely.
What you have here is a design issue. With more than 7 parameters to a method you will start to have problems remembering what they represent and what order they have. From here you will get lots of bugs just by calling the method in wrong parameter order.
You need a better design of the app not a best practice to send lots of parameters.
Create a bean class, and set the all parameters (setter method) and pass this bean object to the method.
This is often an indication that your class holds more than one responsibility (i.e., your class does TOO much).
See The Single Responsibility Principle
for further details.
If you are passing too many parameters then try to refactor the method. Maybe it is doing a lot of things that it is not suppose to do. If that is not the case then try substituting the parameters with a single class. This way you can encapsulate everything in a single class instance and pass the instance around and not the parameters.
Look at your code, and see why all those parameters are passed in. Sometimes it is possible to refactor the method itself.
Using a map leaves your method vulnerable. What if somebody using your method misspells a parameter name, or posts a string where your method expects a UDT?
Define a Transfer Object . It'll provide you with type-checking at the very least; it may even be possible for you to perform some validation at the point of use instead of within your method.
참고URL : https://stackoverflow.com/questions/2432443/best-practice-for-passing-many-arguments-to-method
'Nice programing' 카테고리의 다른 글
TypeError : $ (…) .modal은 부트 스트랩 Modal이있는 함수가 아닙니다. (0) | 2020.09.25 |
---|---|
탐색 스택에서 뷰 컨트롤러 제거 (0) | 2020.09.25 |
Swift 3-날짜 객체 비교 (0) | 2020.09.25 |
.Net에서 창을 항상 맨 위에 유지하는 방법은 무엇입니까? (0) | 2020.09.25 |
jQuery의 숫자에 쉼표 추가 (0) | 2020.09.25 |