쳇,2020 인 데 왜 아직도 단순히 if-else 를 사용 하 는 거 야?

12665 단어 if-else쓰다
고급 언어 에 서 는 기본적으로if-elseswitch-case와 같은 조건 문 구 를 제공 하여 모두 가 판단 하 는 데 편리 하 다―절차 의 방향 을 인도 한다.우 리 는 프로그램 을 쓸 때 항상 두 가지 또는 더 많은 실행 경 로 를 가리 키 고 프로그램 이 실 행 될 때 그 중의 한 가지 경 로 를 선택 하여 해당 하 는 문 구 를 집행 하여 해당 하 는 결 과 를 만들어 야 한다.이것 도 조건문 이 프로그램 에서 의 역할 이다.
if-else 의 예
여러분 은 C 언어 를 처음 배 울 때 이런 프로그램 을 쓴 적 이 있 을 것 입 니 다.출력 매달 일수:

//C      
int Days(int months, int years){
	int days;
	if(months==1 || months==3 || months==5 || months==7 || months==8 || months==10 || months==12){
		days=31;
	}else if(months==2){
		if((years%4==0 && years%100!=0) || years%400==0){
			days=29;
		}else{
			days=28;
		}
	}else if(months==4 || months==6 || months==9 || months==11){
		days=30;
	}else{
		printf("    !     :
"); Days(months,years); } return days; }
이 프로그램 은 비록'귀 에 익 고 상세 하 다'는 것 이지 만 나중에 보면 약간[번거롭다]는 느낌 을 받 을 수 밖 에 없다.다 층 if-else 의 내장 은 가 독성 을 떨 어 뜨 릴 뿐만 아니 라 프로그램 운행 의 효율 에 도 큰 영향 을 줄 수 있다.
질문
위 에서 알 수 있 듯 이 if-else 판단 문 구 는 사용 하기에 매우 간단 하지만 약간 복잡 한 논리 장면 에서 if-else 에 대한 빈번 한 사용(또는 남용)은 전체 프로젝트 의 가 독성 과 유지 가능성 을 크게 낮 출 수 있다.
프로젝트 에 새로운 상황 이 발생 하면 기 존의 코드 를 바탕 으로 if-else 를 계속 추가 해 야 한 다 는 것 을 생각해 볼 수 있 습 니 다.하지만 수 요 는 줄 지 않 을 것 이다.이렇게 악순환 이 계속 되면 원래 의 if-else 몇 개 는 몇 가지 버 전 을 업데이트 한 후에 몇 십 개 로 변 했 을 것 이다.이것 은 정말 웃 을 수 없 는 일이 다.
(물론,지금 당신 의 회사 가 딱딱 한 요 구 를 하거나 템 플 릿 을 개발 할 지도 모 르 니 축하합니다...)
디자인 모델 의 측면 에서 볼 때 if-else 는'나 쁜'코드 가 가 진 모든 것 을 가지 고 있다.
  • 데이터 와 논리 적 강 한 결합 실현
  • 확장 이 번 거 롭 고 유지 보수 성 이 낮 음
  • if-else 개선
    if-else 는 모든 것 을 대체 해 야 하 는 것 이 아니다.정확히 말 하면 우 리 는 지금 그것 을 계속 개선 하여 그 가 더욱 원활 하 게 운행 하도록 할 수 밖 에 없다.
    단락 기호 와 삼원 표현 식
    며칠 전에 필 자 는 단체 에서 이 두 가 지 를 말 했다.단락 기호 이자'논리 연산 자'라 고도 부 르 는데 간단 한 장면 에서 우 리 는 이 를 통 해 if-else(특히'몇 가지 조건 이 동시에 만족'해 야 하 는 장면 에서)를 대체 할 수 있다.
    예 를 들 어 이것―한 수의 옳 고 그 름 을 판단 하 는 멱:
    
    //c++    
    class Solution {
    public:
      bool isPowerOfTwo(int n) {
      	//       2       ,              1,     0 ,
      	//          1   ,        ,    0          1,
      	//         ,     0
        return (n > 0) && (!(n & (n - 1)));
      } 
    };
    우 리 는 또한 3 원 기호 로 if-else 를 대체 할 수 있다.그것 은 거의 가장 적합 한 컴퓨터 판단 기호 이다(필 자 는 스스로 생각한다!).특히 다 조건 복합 판단 에 적합 하 다.그러나 주의해 야 할 것 은 대량의 3 원 연산 자 는 코드 의 가 독성 에 영향 을 주기 쉽다 는 것 이다.
    판단 n!결과 끝자리 의 0 수량:
    
    //java    
    public class Solution {
      public int trailingZeroes(int n) {
      	//    
        return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
      }
    }
    물론 우 리 는 또 하나의 개선 방법 이 있다.만약 에 모든 조건 에서 코드 논리 가 비교적 많 으 면 미리 튀 어 나 와 서 끝 내 는 함수 도 고려 할 수 있다.이것 은 for 순환 을 참고 한 것 이다.
    switch-case 말 해 봐.
    switch-case 는 언어 자체 가 제공 하 는 또 다른 조건문 으로 if 와 본질 적 으로 다 를 것 이 없 으 며 코드 만 더욱 간결 해 보일 뿐이다.예 를 들 어 나 이 를 판단 한다.
    
    goodswitch(age){
    	case 10:
    		break;
    	case 20:
    		break;
    	case 30:
    		break;
    	//...
    }
    그러나 switch-case 는 여러 가지 비슷 한 조건 에서 여러 번 반복 되 어야 하 는 문 제 를 근본적으로 해결 할 수 없다.
    표 구동 법
    이것 은 필자 가 가장 추앙 하 는 기법 으로 빅 데이터 양 판단,범위 차이 처리 등 문제 에 있어 모두 해결 방안 이 있다!
    이제 문장 첫머리 의 그 문 제 를 다시 봅 시다.출력 은 매달 며칠 입 니까?
    우 리 는 생각 을 바 꿔 보 자.매달 하나의 숫자 에 대응 하고 달 은 순서대로 배열 되 어 있 기 때문에 우 리 는 하나의 배열 로 일 수 를 저장 한 다음 에 아래 표 시 를 통 해 방문 할 수 있 습 니까?
    
    //javascript     
    const month=new Date().getMonth(),
    	year=new Date().getFullYear(),
    	isLeapYear=year%4==0 && year%100!=0 || year%400==0;
    
    const monthDays=[31,isLeapYear ? 29 : 28,31,30,31,30,31,31,30,31,30,31];
    const days=monthDays[month];
    아,이 코드 는 실행 하기 가 훨씬 간단 해 요.적어도 이렇게 보 여요.
    그리고 위 에서 나 이 를 판단 하 는 코드 도 있 습 니 다.우 리 는 이렇게 쓸 수 있 습 니 다.
    
    //JavaScript     
    ages=[10,20,...];
    funs=['a1','a2',...];
    for(let i in ages){
    	if(age==ages[i]){
    		funs[i]();
    	}
    }
    function a1(){
    }
    function a2(){
    }
    //...
    두 가지 예 를 보 니 너 는[표 구동 법]에 대해 알 게 되 었 을 것 이다.
    표 구동 법 은 논리 문 구 를 사용 하지 않 고 표 에서 정 보 를 찾 는 프로 그래 밍 모델 이다.사실 논리 문 구 를 통 해 선택 할 수 있 는 모든 것 은 표를 찾 아 선택 할 수 있다.간단 한 경우 에는 논리 문 구 를 사용 하 는 것 이 더 쉽 고 직 설 적 이다.그러나 논리 체인 이 갈수 록 복잡 해 지면 서 차 트 법 도 더욱 매력 적 으로 보인다.코드 대전
    시계 구동 을 사용 하 는 것 은 if-else 처럼'가 볍 지 않다'.우 리 는 먼저 두 가지 문 제 를 생각해 야 한다.
    어떻게 표 에서 데 이 터 를 조회 합 니까?만약 if-else 가 판단 한 것 이 범위 라면 어떻게 조사해 야 합 니까?뭘 찾 아?데이터색인
    이 두 가지 문 제 를 바탕 으로 누군가가 표 에 따라 구동 되 는 조 회 를 세 가지 로 나 누 었 다.
    직접 접근 색인 접근 계단 접근
    1.직접 방문 표
    필 자 는 최근 어머니 의 뜻 에 따라 보험 회 사 를 다 녀 왔 는데 이 보험료 율 이 매우 번 거 로 운 것 을 발견 했다.나이,성별,혼인 상태 등에 따라 달라 질 수 있다.위의 출력 날 짜 를 보 는 프로그램 을 보면 서 논리 적 제어 재 구성(if or switch)으로 서로 다른 비용 율 을 표시 하면 얼마나 번 거 로 울 지 생각해 보 세 요!(사실 당신 의 코드 는 낙지 처럼...)
    우 리 는 이곳 의[나이]가 범위 라 는 것 을 알 수 있다!배열 이나 대상 으로 맵 을 만 들 수 없습니다.이것 은 두 가지 해결 방안 이 있 습 니 다.직접 방문 표 or 계단 방문 표 입 니 다.필 자 는 먼저'직접 방문 표'의 방식 을 시험 해 보고 두 가지 방법 을 찾 았 다.
    정 보 를 복사 하여 키 값 을 직접 사용 할 수 있 습 니 다.우 리 는 1-17 연령 대의 모든 연령 대 에 정 보 를 복사 한 다음 에 age 로 직접 방문 할 수 있 습 니 다.마찬가지 로 다른 연령 대 에 도 마찬가지 입 니 다.이런 방법 은 조작 이 매우 간단 하고 표 의 구조 도 매우 간단 하 다 는 데 있다.그러나 공간 을 낭비 하 는 단점 이 있다.왜냐하면 많은 불필요 한 정 보 를 만 들 었 기 때문이다.)키 값 을 바 꾸 는 것 을 권장 하지 않 습 니 다.만약 우리 가 연령 범 위 를 키 로 바꾼다 면?이렇게 하면 직접 방문 할 수 있다.유일 하 게 고려 해 야 할 문 제 는 어떤 상황 에서 나이 가 어떻게 키 값 으로 바 뀌 는 지 하 는 것 이다.
    두 번 째 방법 에 대해 서 는 if-else 로 전환 해 야 한 다 는 의혹 이 있 을 수 있다.그럼요.앞에서 말 했 듯 이 간단 한 if-else 는 문제 가 없 을 것 이다.표 구동 은 복잡 한 논리 적 판단 을 최적화 시 켜 더욱 유연 하고 확장 하기 쉽다.
    
    //TypeScript     
    const Age={
    	0:"unadult",
    	1:"adult"
    }
    const Gender={
    	0:"female",
    	1:"male"
    }
    const Marry={
    	0:"unmarried",
    	1:"married"
    }
    
    const rateMap={
    	[Age[0]+Gender[0]+Marry[0]]:0.1,
    	[Age[0]+Gender[0]+Marry[1]]:0.2,
    	[Age[0]+Gender[1]+Marry[1]]:0.3,
    	[Age[0]+Gender[1]+Marry[0]]:0.4,
    	[Age[1]+Gender[0]+Marry[0]]:0.5,
    	[Age[1]+Gender[0]+Marry[1]]:0.6,
    	[Age[1]+Gender[1]+Marry[1]]:0.7,
    	[Age[1]+Gender[1]+Marry[0]]:0.8
    }
    const isAdult=(age:number)=>age>=18 ? 1: 0
    const getDate=(age,hasMarried,gender)=>{
    	age=isAdult(age)
    	return rateMap[Age[age]+Gender[gender]+Marry[marry]]
    }
    그래 야 제대로 열 리 는 거 잖 아!
    아,맞아요.방금 또 한 가지 방법 을 말 한 것 같 아 요.
    2.계단 방문 표
    마찬가지 로 위의 연령 대 문 제 를 해결 하기 위해 계단 방문 은 색인 없 이 직접 방문 하지만 공간 을 더욱 절약 할 수 있다.
    계단 방법 을 사용 하기 위해 서 는 각 구간 의 상한 선 을 한 장의 표 에 기록 한 후 순환 을 통 해 연령 이 있 는 구간 을 검사 해 야 하기 때문에 계단 을 이용 하여 방문 할 때 구간 의 단점 을 반드시 검사 해 야 한다.
    
    //TypeScript     
    const ageRanges:number[]=[17,65,100],
    	keys:string[]=['<18','18-65','>65'];
    const getKey=(age:number):string=>{
    	for(let i in keys){
    		//console.log(i);
    		//console.log(ageRanges[i]);
    		if(age<=ageRanges[i]){
    			return keys[i];
    		}
    	}
    	return keys[keys.length-1];
    }
    3.색인 접근 표
    실제 보험료 율 문 제 는 연령 대 를 처리 할 때 머리 가 아프다.이런 범 위 는 위의 첫 번 째 방법 에서'키'를 쉽게 얻 을 수 있 는 것 이 아니다.
    우 리 는 당시 에 정 보 를 복사 해서 키 값 을 직접 사용 할 수 있다 고 언급 했 지만,이러한 방법 은 모든 연령 대 에 하나의 데 이 터 를 저장 하기 때문에 많은 공간 을 낭비 했다.
    그러나 우리 가 색인 만 저장 하고 이 색인 을 통 해 데 이 터 를 조회 한다 면?
    사람 이 갓 태 어 난 것 이 0 살 이 고 최대 100 살 까지 살 수 있다 고 가정 하면 우 리 는 길이 가 101 인 배열 을 만들어 야 한다.배열 의 아래 표 시 는 사람의 나이 에 해당 한다.그러면 0-17 의 모든 연령 에 우 리 는'18'을 저장 하고 18-65 에'18-65'를 저장 하 며 65 이상 에'>65'를 저장 해 야 한다.이렇게 하면 우 리 는 나 이 를 통 해 해당 하 는 색인 을 얻 고 색인 을 통 해 해당 하 는 데 이 터 를 조회 할 수 있다.
    이러한 방법 은 위의 직접 방문 표 보다 더 복잡 해 보이 지만 키 값 을 바 꾸 기 어렵 고 데이터 가 공간 을 많이 차지 하 는 장면 에서 색인 을 통 해 접근 해 볼 수 있 습 니 다.
    
    //Typescript     
    const ages:string[]=['<18','<18','<18',...'18-65','18-65','18-65',...'>65','>65','>65',...'>65'];
    const ageKey:string=ages[age];
    이렇게 하면 시 계 를 만 들 때 약간 번 거 롭 지만 데 이 터 를 처리 할 때 매우 간편 합 니 다!
    표 구동 의 전형 적 인 응용
    표 구동 의 가장 큰 의 미 는 조건 판단(데이터)과 논 리 를 분리 하고 조건 을 설정 가능 한 표(대상 or 배열)로 관리 하 는 것 이다.
    0-360°를 8 개의 서로 다른 공간 으로 나 누 지만 항상 if-else 로 실현 하지 마 세 요.
    
    //JavaScript     
    const keys=['A','B','C','D','E','F','G','H'],
    	range=[45,90,135,180,225,270,315,360];
    const degreeTkey=(rage)=>{
    	for(let i in range){
    		if(rage<=range[i]){
    			return keys[i];
    		}
    	}
    }
    const map={
    	'A':()=>{
    		//...
    	},
    	'B':()=>{
    		//...
    	},
    	//...
    }
    
    //   :
    map[degreeTkey(46)]();
    if-else 대응 관계 복잡 한 문제 매 거 해결
    어떤 캐릭터 가 무슨 일 을 하 는 지,이것 은 매우 뚜렷 한 대응 관계 이기 때문에 배 운'매 거'는 왜 사용 하지 않 습 니까?
    사실은 위 에서 언급 한[표 검색]과 비슷 합 니 다.우 리 는'시스템 관리자 의 조작 권한'문 제 를 들 었 습 니 다.
    먼저 공용 인터페이스 Role Operation 을 정의 하고 서로 다른 캐릭터 가 할 수 있 는 동작 을 표시 합 니 다.
    
    public interface RoleOperation {
      String op();//           op  
    }
    그 다음 에 우 리 는 서로 다른 캐릭터 의 상황 을 모두 매 거 진 유형 에 맡 기 고 서로 다른 캐릭터 가 서로 다른 권한 을 가 진 매 거 진 유형RoleEnum을 정의 한다.
    
    public enum RoleEnum implements Role0peration {
      //     ( A    )
    	ROLE_ ROOT_ _ADMIN {
    		@Override
    		public String op() {
    			return "ROLE_ ROOT_ ADMIN:" + " has AAA permission";
    		}
    	},
    	//     ( B    )
    	ROLE_ ORDER_ ADMIN {
    		@override
    		public String op() {
    			return "ROLE_ ORDER_ _ADMIN:" + " has BBB permission";
    		}
    	},
    	//    ( C    )
    	ROLE_ NORMAL {
    	@Override
    		public String op() {
    			return "ROLE_ NORMAL:" + "has CCC permission";
    		}
    	};
    }
    그리고 이렇게 되면 앞으로 만약 에 제 가 조건 을 확대 하고 싶다 면 매 거 진 유형 에 코드 를 추가 하면 됩 니 다.예전 의 코드 를 고 치 는 것 이 아니 라 안정 적 이지 않 습 니까?
    
    public class JudgeRole {
    	public String judge( String roleName ) {
    		//      !   if/else  !
    		return RoleEnum.va1ue0f(roleName).op();
    	}
    }
    공장 모드 해결 if-else"분기 과 다"문제
    서로 다른 지점 에서 서로 다른 일 을 하 는 것 은 공장 모델 을 사용 하 는 계 기 를 제공 하 는 것 이 분명 하 다.우 리 는 서로 다른 상황 을 단독으로 정의 한 다음 에 공장 류 에 가서 집합 하면 된다.
    우선,서로 다른 역할 에 대해 업무 유형 을 따로 정의 할 수 있 습 니 다.
    
    //     ( A    )
    public class RootAdminRole implements Role0peration {
    	private String roleName ;
    	public RootAdminRole( String roleName){
    		this.roleName = roleName ;
    	}
    	@Override
    	public String op() {
    		return roleName + "has AAA permission" ;
    	}
    }
    
    //     ( B    )
    public class OrderAdminRole implements RoleOperation {
    	private String roleName ;
    	public OrderAdminRole( String roleName ) {
    		this.roleName = roleName ;
    	} 
    	@Override
    	public String op() {
    		return roleName + "has BBB permission";
    	}
    }
    
    //    ( C    )
    public class NormalRole implements RoleOperation {
    	private String roleName ;
    	public NormalRole( String roleName){
    		this.roleName = roleName;
    	}
    	@Override
    	public String op() {
    		return roleName + "has CCC permission";
    	}
    }
    다음은 공장 류RoleFactory를 하나 더 써 서 위의 서로 다른 역할 을 취 합 한다.
    
    public class RoleFactory {
    	static Map<String, Role0peration> roleOperationMap = new HashMap<>();
    	//                
    	static {
    		role0perationMap.put( "ROLE_ ROOT_ ADMIN", new RootAdminRole("ROLE_ _ROOT_ ADMIN") ) :
    		roleOperationMap.put( "ROLE_ ORDER_ ADMIN", new OrderAdminRole("ROLE_ ORDER_ ADMIN") );
    		role0perationMap.put( "ROLE_ NORMAL", new NormalRole("ROLE_ NORMAL") );
    	}
    	pub1ic static RoleOperation getOp( String roleName ) {
    		return roleOperationMap.get( roleName ) ;
    	}
    }
    그 다음 에 위의 이 공장 을 통 해 업무 코드 호출 도 한 줄 의 코드 만 필요 합 니 다.if/else 역시 제거 되 었 습 니 다.
    
    public class JudgeRole {
    	public String judge(String roleName){
    		//      !     if/else   !
    		return RoleFactory.get0p(roleName).op();
    	}
    }
    이렇게 되면 앞으로 조건 을 확장 하 는 것 도 쉬 워 집 니 다.새로운 코드 만 추가 하고 예전 의 업무 코드 를 움 직 이지 않 아 도 됩 니 다.'개폐 원칙'에 매우 부합 합 니 다.
    이제 2020 인 데 왜 단순히 if-else 를 사용 하 는 지 에 대한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 if-else 사용 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기