프로그래머로서 경력에서 겪은 최악의 반 패턴은 무엇입니까?
언어와 무관하지만 대부분 자바에 관여합니다.
나는 그것의 최악이 내가 주요 안티 패턴 이라고 생각합니다 . 그것은 모든 논리를 포함하는 매우 큰 단일 클래스 (때로는 작은 클래스 쌍과 함께 제공됨)로 구성된 프로그램을 의미합니다. 일반적으로 모든 비즈니스 로직이 포함되어 있고 때로는 수만 줄의 코드가 포함 된 큰 루프가 있습니다.
프로그래머로서 경력에서 겪은 최악의 반 패턴은 무엇입니까?
언어와 무관하지만 대부분 자바에 관여합니다.
나는 그것의 최악이 내가 주요 안티 패턴 이라고 생각합니다 . 그것은 모든 논리를 포함하는 매우 큰 단일 클래스 (때로는 작은 클래스 쌍과 함께 제공됨)로 구성된 프로그램을 의미합니다. 일반적으로 모든 비즈니스 로직이 포함되어 있고 때로는 수만 줄의 코드가 포함 된 큰 루프가 있습니다.
답변:
코드를 주석 처리했습니다. 그것의 블록, 아마도 수백 줄. 이론은, 그것은 논평되고, 아무런 해를 끼치 지 않으며 아마도 우리는 미래에 그것을 필요로 할 것입니다.
"복사 파스타"로 또 다른 분명한 것을 맞을 것입니다. 원하는 것과 거의 동일한 코드를 복사 한 다음 메소드로 추출하는 대신 몇 가지 사항을 변경하십시오.
이것은 90 년대 후반의 일부 기능 및 API 테스트 코드에서 특히 널리 퍼져 있습니다. 문자 그대로 수백 개 (또는 수천 개)의 거의 동일한 테스트 사례가 3 개 또는 4 개의 매개 변수를 취하는 몇 가지 함수로 나뉘어 질 수 있습니다. 데이터 중심의 무언가. 대학 밖에서의 첫 직업은 말 그대로 8 개월 동안 수천 줄의 카피 파스타를 다시 쓰고 리팩토링하는 것입니다. 테스트가 완료 될 때까지 테스트 파일은 원래 크기의 10 분의 1보다 작았으며 유지 관리가 쉽고 읽기 쉬웠습니다.
적은 노력으로 해결할 수있는 Pattern Mania 및 솔루션 에 대해 많이 쓸 수 있다고 생각 하지만 간단한 솔루션을 과도하게 복잡하게 만드는 방법에 대한 환상적인 예를 들어 최근에 읽은 훌륭한 기사를 가리키고 싶습니다. .
지역
C #에서는 IDE에서 축소 될 수있는 코드 영역을 정의 할 수 있으므로 해당 코드를 처리하지 않으려면 숨길 수 있습니다. 나는 지역이 수백 줄에 걸쳐있는 프로젝트에 있었고 (현재 내가 과장하고있다) 수천 개의 라인 기능으로 여러 지역이있었습니다 (내가 농담하고 싶습니다).
거꾸로, 지역을 만든 개발자는 지역 내에서 특정 기능을 식별하는 데 매우 효과적이었습니다. 그래서 그 지역에서 추출법을 사용하여 계속 진행할 수있었습니다.
지역은 개발자가 자신의 쓰레기를 눈에 잘 띄지 않도록 권장합니다.
DoNotUseRegions
입니다.
#region SQL Update
은 축소 가능하므로 스크롤이 덜 필요합니다.
루프 스위치 시퀀스
http://en.wikipedia.org/wiki/Loop-switch_sequence
그들은 나를 귀찮게하고 실제로 개발자가 얼마나 경험이 없었는지 보여줍니다.
대규모 체크인
개발자가 일주일 이상 체크인하지 않은 것을 싫어합니다. 그것은 그가 붙어서 도움을 구하지 않았거나 많은 기능을 하나의 큰 체크인으로 모으는 것을 의미합니다. (나는 최악의 시나리오를 배제했지만 그는 아무것도하지 않고있다. 해결하기 쉽습니다 ... 두 단어가 고용 된 것처럼 들립니다.)
큰 체크인을하는 경우 변경 집합을 특정 기능에 연결할 수있는 것처럼 SCM의 많은 이점을 잃게됩니다. 또한 많은 병합 작업을 수행 할 가능성이 높으며 반드시 올바르게 달성하기가 쉽지는 않습니다.
현재 레거시 코드로 작업하고 있으며 이전 코더가 목록의 첫 번째 요소를 얻는 방식을 좋아합니다.
String result;
for(int i = 0; i < someList.size(); i++) {
result = someList.get(i);
break;
}
그러나이 코드에서 본 최악의 상황은 클래스 인라인 JSP 페이지를 정의하고 scriptlet 및 out.println을 사용하여 모든 HTML, CSS 및 Javascript를 작성하는 것입니다.
문자열 리터럴에 잠금
synchronized("one") { /* block one A*/ }
synchronized("one") { /* block one B*/ }
매우 긴 수업 명. (JRE에서)
com.sun.java.swing.plaf.nimbus.
InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState
불쌍한 상속 구조
com.sun.corba.se.internal.Interceptors.PIORB extends
com.sun.corba.se.internal.POA.POAORB extends
com.sun.corba.se.internal.iiop.ORB extends
com.sun.corba.se.impl.orb.ORBImpl extends
com.sun.corba.se.spi.orb.ORB extends
com.sun.corba.se.org.omg.CORBA.ORB extends
org.omg.CORBA_2_3.ORB extends
org.omg.CORBA.ORB
그렇지 않은 예외.
public interface FlavorException { }
무의미하고 비밀스러운 오류 처리
if (properties.size() > 10000)
System.exit(0);
불필요한 객체 생성
Class clazz = new Integer(0).getClass();
int num = new Integer(text).intValue();
다른 목적으로 예외 던지기
try {
Integer i = null;
Integer j = i.intValue();
} catch (NullPointerException e) {
System.out.println("Entering "+e.getStackTrace()[0]);
}
정적 메서드에 인스턴스 객체 사용
Thread.currentThread().sleep(100);
비 최종 필드에서 동기화
synchronized(list) {
list = new ArrayList();
}
상수 문자열의 무의미한 사본
String s = new String("Hello world");
String.toString ()에 대한 무의미한 호출
String s = "Hello";
String t = s.toString() + " World";
일부 메모리를 확보하기 위해 System.gc ()를 호출합니다.
일부 메모리를 비우기 위해 로컬 변수를 null로 설정
// list is out of scope anyway.
list = null;
}
성능상의 이유로 (또는 다른 마이크로 마이크로 최적화) i ++ 대신 ++ i 사용
인형 반복자 :
Iterator iCollection = collection.iterator();
for(int i = 0 ; i < collection.size() ; i++ ){
if(collection.get(i) == something){
iCollection.remove();
}
}
싱글 토노 공장 :
public class SomeObject{
private SomeObject() {}
public static SomeObject getInstance(){
return new SomeObject();
}
}
if-else 중심 개발 (개방형 원칙이라고도 함-이해를 위해 수정 용으로 개방)
if (sth1){
...
}else if(sth2){
..
}
...
..
else if(sth1000000000000){
...
}
StringPattern (StringObject라고도 함) :
a) sendercode
if(sth1)
str+="#a";
if(sth2)
str+="#b";
...
if(sth1000)
str+="#n";
b) receiver
regexp testing if str contains #a, #b, ... #n
else if
종종 일을 끝내는 유일한 방법입니다. 나는 줄에 대해 생각하고있다; 스위치를 사용할 수 없습니다. 조건이 유용해야합니다.
나는 추상화 반전을 절대적으로 무시 하거나 높은 수준의 기본 요소 위에 낮은 수준의 기본 요소를 다시 발명합니다. 그러나 때때로 이것은 나쁜 프로그래머가 아닌 나쁜 언어 디자이너에 의해 발생합니다. 예 :
함수 포인터 대신 멤버 변수와 해당 인터페이스 (함수 포인터 테이블로 구현)가없는 단일 메서드 클래스를 사용합니다. Java와 같은 언어에서는 선택의 여지가 없습니다.
MATLAB과 R에서 모든 것이 기본 요소가 아닌 벡터 / 행렬이라는 주장.
우리는 MATLAB을 강타하고 있지만 정수가 없다는 사실은 어떻습니까? 따라서 정수가 필요할 때는 double을 사용해야합니다.
루프를 작성하기 위해 함수 호출을 사용해야하는 순수 기능 언어.
다중 사용 Java Bean-
몇 가지 다른 종류의 작업에 사용되는 변수가 많은 Java Bean입니다. 각 조작은 Bean 변수의 임의의 서브 세트를 사용하고 다른 변수는 무시합니다. GUI 상태에 대한 몇 가지 변수, 구성 요소 사이를 통과하기 위해 던져지는 몇 가지 변수, 더 이상 사용되지 않는 변수 모범 사례에는 문서가 없으므로 패턴의 감상을 방해합니다.
또한 사랑하는 사람을 잊을 수 없다
try{
... //many lines of likely dangerous operations
}
catch(Exception e){}
필자가 본 최악의 안티 패턴 중 하나는 컴퓨터 메모리 대신 데이터베이스 테이블을 임시 저장소로 사용하는 것입니다.
문제 영역은 독점적이므로 문제를 설명 할 수는 없지만 기본 문제를 이해할 필요는 없습니다. 이것은 백엔드 데이터베이스로 Java로 작성된 GUI 응용 프로그램입니다. 특정 입력 데이터를 가져 와서 조작 한 다음 처리 된 데이터를 데이터베이스에 커밋했습니다.
우리 프로젝트에는 나중에 처리하기 위해 중간 값을 저장하는 상당히 복잡한 알고리즘이 있습니다. 임시 객체를 객체로 캡슐화하는 대신 "t_object"와 같은 데이터베이스 테이블이 생성되었습니다. 값이 계산 될 때마다이 테이블에 추가되었습니다. 알고리즘이 작업을 마치면 모든 중간 값을 선택하여 하나의 큰 Map 객체에서 처리합니다. 모든 처리가 완료된 후에 저장되도록 표시된 나머지 값이 실제 데이터베이스 스키마에 추가되고 "t_object"테이블의 임시 항목이 삭제됩니다.
테이블은 또한 고유 목록처럼 사용되었으며 데이터는 한 번만 존재할 수있었습니다. 이것은 테이블에 제약 조건을 구현했을 때 디자인의 적절한 기능 일 수 있었지만 데이터가 존재하는지 여부를 확인하기 위해 전체 테이블을 반복했습니다. (아니오 우리는 CONTAINS와 함께 where 절을 사용한 쿼리조차 사용하지 않았습니다)
이 디자인으로 인해 발생한 문제 중 일부는 구체적으로 디버깅이었습니다. 이 응용 프로그램은 파이프 라인 데이터를 위해 작성되었으므로이 알고리즘에 도달하기 전에 데이터를 사전 처리하는 여러 GUI가 있습니다. 디버깅 프로세스는 테스트 케이스를 처리 한 다음 위 섹션을 완료 한 직후 일시 중지하는 것이 었습니다. 그런 다음이 테이블에 어떤 데이터가 포함되어 있는지 데이터베이스를 쿼리합니다.
우리가 발견 한 또 다른 문제는이 임시 테이블에서 데이터가 올바르게 삭제되지 않아 향후 실행을 방해한다는 것입니다. 예외가 올바르게 처리되지 않아서 애플리케이션이 올바르게 종료되지 않아서 제어중인 테이블의 데이터가 삭제되지 않았기 때문인 것으로 나타났습니다.
기본 객체 지향 설계를 사용하고 모든 것을 메모리에 보관했다면 위의 문제는 발생하지 않았을 것입니다. 첫째, 응용 프로그램에서 중단 점을 쉽게 설정 한 다음 스택 및 힙의 메모리를 검사 할 수 있으므로 디버깅이 간단했을 것입니다. 둘째, 응용 프로그램이 비정상적으로 종료되면 데이터베이스에서 삭제하는 것에 대해 걱정할 필요없이 Java 메모리가 자연스럽게 정리되었습니다.
참고 : 나는이 패턴이 본질적으로 나쁘다는 것을 말하지는 않지만이 예제에서는 기본 OO 원칙이 충분했을 때 불필요하다는 것을 알았습니다.
나는이 반 패턴의 이름을 확신하지 못한다. 이 패턴에 대해 좋은 이름을 생각할 수 있습니까?
내가 본 것 중 최악의 안티 패턴 IMO는 "우리는 어떤 종류의 패턴도 필요하지 않습니다"안티 패턴입니다. 디자인 패턴은 시간 낭비이며 코드를 함께 훑어 서 복사 / 복사하여 코드를 더 빨리 작성할 수 있다는 아이디어입니다. 필요에 따라 붙여 넣기.
오래된 VB6 스타일을 사용하여 데이터베이스에서 객체를로드하는 코드를 사용하는 것이 좋습니다.
Foobar oFoo = new Foobar();
oFoo.FooID = 42;
if (oFoo.Load()) {
// do something with oFoo
}
실제로 안티 패턴 자체는 아니지만 적절한 아키텍처와 관심사 분리를 활용하지 못합니다.
또한 다음과 같은 것들이 있습니다.
// this name is misleading, we may not always want to stand in fire,
// we may want to stand in slime or voidzones or ice patches...
public Foobar StandInFire() { }
// why is this here???
public string BeatWithNerfBat(string whom) { }
// ????
public int GivePony(string to) { }