JavaRush /Java блогы /Random-KK /Java тілінде рефакторинг қалай жұмыс істейді

Java тілінде рефакторинг қалай жұмыс істейді

Топта жарияланған
Бағдарламалауды үйрену кезінде code жазуға көп уақыт кетеді. Жаңадан бастаған әзірлеушілердің көпшілігі бұл олардың болашақ қызметі деп санайды. Бұл ішінара дұрыс, бірақ бағдарламашының міндеттеріне codeты сақтау және рефакторинг кіреді. Бүгін біз рефакторинг туралы сөйлесетін боламыз. Java тілінде рефакторинг қалай жұмыс істейді - 1

JavaRush курсында рефакторинг

JavaRush курсы екі рет рефакторинг тақырыбын қамтиды: Үлкен тапсырманың арқасында іс жүзінде нақты рефакторингпен танысу мүмкіндігі бар, ал IDEA-дағы рефакторинг бойынша лекция өмірді керемет жеңілдететін автоматты құралдарды түсінуге көмектеседі.

Рефакторинг дегеніміз не?

Бұл code құрылымын оның функционалдығын өзгертпей өзгерту. Мысалы, 2 санды салыстыратын және біріншісі үлкен болса ақиқат мәнін , ал кері жағдайда жалған мәнін қайтаратын әдіс бар :
public boolean max(int a, int b) {
    if(a > b) {
        return true;
    } else if(a == b) {
        return false;
    } else {
        return false;
    }
}
Нәтиже өте қиын code болды. Тіпті жаңадан бастағандар мұндай нәрсені сирек жазады, бірақ мұндай қауіп бар. if-elseЕгер сіз әдісті 6 жолға қысқарта жазсаңыз, неге мұнда блок бар сияқты :
public boolean max(int a, int b) {
     return a>b;
}
Енді бұл әдіс қарапайым және талғампаз болып көрінеді, бірақ ол жоғарыдағы мысалмен бірдей әрекет етеді. Рефакторинг осылай жұмыс істейді: ол codeтың құрылымын оның мәніне әсер етпей өзгертеді. Көптеген рефакторинг әдістері мен әдістері бар, біз оларды толығырақ қарастырамыз.

Неліктен рефакторинг қажет?

Мұның бірнеше себептері бар. Мысалы, codeтың қарапайымдылығы мен қысқалығына ұмтылу. Бұл теорияны жақтаушылар codeты түсіну үшін бірнеше ондаған жолдар түсініктеме қажет болса да, мүмкіндігінше қысқа болуы керек деп есептейді. Басқа әзірлеушілер codeты түсініктемелердің ең аз санымен түсінуге болатындай етіп қайта өңдеу керек деп санайды. Әрбір команда өз позициясын таңдайды, бірақ біз рефакторинг қысқарту емес екенін есте ұстауымыз керек . Оның негізгі мақсаты – code құрылымын жетілдіру. Осы жаһандық мақсатқа бірнеше мақсаттарды қосуға болады:
  1. Рефакторинг басқа әзірлеуші ​​жазған codeты түсінуді жақсартады;
  2. Қателерді табуға және түзетуге көмектеседі;
  3. Бағдарламалық қамтамасыз етуді әзірлеу жылдамдығын арттыруға мүмкіндік береді;
  4. Жалпы бағдарламалық құрал құрамын жақсартады.
Егер рефакторинг ұзақ уақыт бойы жүргізілмесе, жұмыстың толық тоқтауына дейін даму қиындықтары туындауы мүмкін.

«Код иісі»

Код рефакторингті қажет еткенде, олар «иіс» дейді. Әрине, сөзбе-сөз емес, бірақ мұндай code шынымен де жақсы көрінбейді. Төменде біз бастапқы кезеңдегі негізгі рефакторинг әдістерін қарастырамыз.

Қажетсіз үлкен элементтер

Үлкен өлшемдеріне байланысты тиімді жұмыс істеу мүмкін емес ауыр сыныптар мен әдістер бар.

Үлкен сынып

Мұндай сыныпта code жолдарының көп саны және көптеген әртүрлі әдістер бар. Әдетте әзірлеушіге жаңасын жасаудың орнына бар сыныпқа мүмкіндікті қосу оңайырақ, сондықтан ол өседі. Әдетте, бұл сыныптың функционалдығы шамадан тыс жүктеледі. Бұл жағдайда функцияның бір бөлігін бөлек сыныпқа бөлу көмектеседі. Бұл туралы толығырақ рефакторинг әдістері бөлімінде айтатын боламыз.

Үлкен әдіс

Бұл «иіс» әзірлеуші ​​әдіске жаңа функционалдылықты қосқанда пайда болады. «Егер мен оны осында жаза алатын болсам, неге мен параметрді тексеруді бөлек әдіске қоюым керек?», «Неге массивтегі максималды элементті табу әдісін бөлу керек, оны осында қалдырайық. Осылайша code түсінікті болады» және басқа да қате түсініктер. Үлкен әдісті қайта өңдеудің екі ережесі бар:
  1. Егер әдісті жазғанда codeқа түсініктеме қосқыңыз келсе, бұл функцияны бөлек әдіске бөлу керек;
  2. Егер әдіс codeтың 10-15 жолынан көп болса, ол орындайтын тапсырмалар мен ішкі тапсырмаларды анықтап, ішкі тапсырмаларды бөлек әдіске бөліп көріңіз.
Үлкен әдісті жоюдың бірнеше жолы:
  • Әдістің функционалдық бөлігін бөлек әдіске бөлу;
  • Жергілікті айнымалылар функцияның бір бөлігін шығаруға мүмкіндік бермесе, бүкіл нысанды басқа әдіске беруге болады.

Көптеген қарапайым деректер түрлерін пайдалану

Әдетте, бұл мәселе сыныпта деректерді сақтауға арналған өрістер саны уақыт өте келе өскенде пайда болады. Мысалы, деректерді (валюта, күн, телефон нөмірлері және т.б.) сақтау үшін шағын нысандардың орнына қарабайыр типтерді немесе кез келген ақпаратты codeтау үшін тұрақтыларды пайдалансаңыз. Бұл жағдайда өрістерді логикалық топтастыру және оларды бөлек сыныпқа орналастыру (сынып таңдау) жақсы тәжірибе болады. Бұл деректерді өңдеу әдістерін сыныпқа да қосуға болады.

Опциялардың ұзақ тізімі

Өте жиі кездесетін қате, әсіресе үлкен әдіспен үйлескенде. Әдетте бұл әдістің функционалдығы шамадан тыс жүктелсе немесе әдіс бірнеше алгоритмдерді біріктірсе пайда болады. Параметрлердің ұзын тізімдерін түсіну өте қиын, мұндай әдістерді пайдалану ыңғайсыз. Сондықтан бүкіл нысанды ауыстырған дұрыс. Егер нысанда деректер жеткіліксіз болса, ол логикалық байланысты деректерді өңдейтіндей жалпы нысанды пайдалану немесе әдістің функционалдығын бөлу керек.

Деректер топтары

Логикалық байланысты деректер топтары жиі codeта пайда болады. Мысалы, дерекқорға қосылу параметрлері (URL, пайдаланушы аты, құпия сөз, схема атауы және т.б.). Егер элементтер тізімінен бірде-бір өрісті алып тастау мүмкін болмаса, онда тізім жеке класқа (сынып таңдауы) орналастырылуы тиіс деректер тобы болып табылады.

OOP тұжырымдамасын бұзатын шешімдер

«Иістің» бұл түрі әзірлеуші ​​OOP дизайнын бұзған кезде пайда болады. Егер ол осы парадигманың мүмкіндіктерін толық түсінбесе, оларды толық немесе дұрыс қолданбаса, бұл орын алады.

Мұрадан бас тарту

Егер ішкі сынып ата-аналық класс функцияларының ең аз бөлігін пайдаланса, ол дұрыс емес иерархия сияқты иіс шығарады. Әдетте, бұл жағдайда қажет емес әдістер жай ғана жойылмайды немесе ерекшеліктер тасталады. Егер класс басқасынан мұраланған болса, бұл оның функционалдығын толық дерлік пайдалануды білдіреді. Дұрыс иерархияның мысалы: Java тілінде рефакторинг қалай жұмыс істейді - 2 дұрыс емес иерархияның мысалы: Java тілінде рефакторинг қалай жұмыс істейді - 3

ауысу мәлімдемесі

Операторда не қате болуы мүмкін switch? Оның дизайны өте күрделі болған кезде жаман. Бұған көптеген кірістірілген блоктар да кіреді if.

Әртүрлі интерфейстері бар балама сыныптар

Бірнеше сыныптар негізінен бірдей нәрсені жасайды, бірақ олардың әдістері басқаша аталады.

Уақытша өріс

Егер сыныпта an object тек анда-санда ғана қажет болатын уақытша өріс болса, ол мәндермен толтырылған болса және қалған уақытта бос болса немесе, Құдай сақтасын, nullонда code «иіс шығарады», және мұндай дизайн күмәнді. шешім.

Өзгертуді қиындататын иістер

Бұл «иістер» әлдеқайда ауыр. Қалғандары негізінен codeты түсінуді нашарлатады, ал олар оны өзгертуге мүмкіндік бермейді. Кез келген мүмкіндіктерді енгізген кезде әзірлеушілердің жартысы жұмыстан шығып, жартысы есінен танып қалады.

Параллель мұра иерархиялары

Кластың ішкі сыныбын жасағанда, басқа сынып үшін басқа ішкі сыныпты жасау керек.

Тәуелділіктің біркелкі таралуы

Кез келген модификацияларды орындаған кезде осы класстың барлық тәуелділіктерін (пайдалануларын) іздеп, көптеген шағын өзгерістер енгізуге тура келеді. Бір өзгерту - көптеген сыныптарда өңдеулер.

Күрделі модификация ағашы

Бұл иіс алдыңғыға қарама-қарсы: өзгерістер бір сыныптың көптеген әдістеріне әсер етеді. Әдетте, мұндай codeтағы тәуелділік каскадты болып табылады: бір әдісті өзгерткеннен кейін, басқасында бірдеңені түзету керек, содан кейін үшіншіде және т.б. Бір сынып - көптеген өзгерістер.

«Қоқыс иісі»

Бас ауруын тудыратын иістердің өте жағымсыз санаты. Пайдасыз, қажетсіз, ескі code. Бақытымызға орай, қазіргі заманғы IDE және линтерлер мұндай иістерді ескертуді үйренді.

Әдістегі пікірлердің үлкен саны

Әдісте әр жолға дерлік көптеген түсіндірме түсініктемелері бар. Бұл әдетте күрделі алгоритммен байланысты, сондықтан codeты бірнеше кішірек әдістерге бөліп, оларға мағыналы атаулар берген дұрыс.

Кодтың қайталануы

Әртүрлі сыныптар немесе әдістер бірдей code блоктарын пайдаланады.

Жалқау сынып

Класс өте аз функционалдылықты алады, дегенмен оның көп бөлігі жоспарланған.

Пайдаланылмаған code

Класс, әдіс немесе айнымалы codeта пайдаланылмайды және «өлі салмақ» болып табылады.

Шамадан тыс қосылу

Иістердің бұл санаты codeтағы қажетсіз қосылымдардың көптігімен сипатталады.

Үшінші тарап әдістері

Әдіс басқа нысанның деректерін өз деректеріне қарағанда әлдеқайда жиі пайдаланады.

Сәйкес емес жақындық

Класс басқа сыныптың қызмет өрістері мен әдістерін пайдаланады.

Ұзақ сынып қоңыраулары

Бір сынып екіншісін шақырады, ол үшіншіден, төртіншіден және т.б. деректерді сұрайды. Мұндай ұзақ қоңыраулар тізбегі қазіргі сынып құрылымына тәуелділіктің жоғары деңгейін білдіреді.

Класс-тапсырма-дилер

Сынып тек тапсырманы басқа сыныпқа беру үшін қажет. Мүмкін оны алып тастау керек пе?

Рефакторинг техникасы

Төменде сипатталған code иістерін жоюға көмектесетін бастапқы рефакторинг әдістері туралы айтатын боламыз.

Сынып таңдау

Класс тым көп функцияларды орындайды, олардың кейбірін басқа сыныпқа ауыстыру қажет. Мысалы, Humanтұрғылықты мекенжайды және толық мекенжайды қамтамасыз ететін әдісті қамтитын сынып бар:
class Human {
   private String name;
   private String age;
   private String country;
   private String city;
   private String street;
   private String house;
   private String quarter;

   public String getFullAddress() {
       StringBuilder result = new StringBuilder();
       return result
                       .append(country)
                       .append(", ")
                       .append(city)
                       .append(", ")
                       .append(street)
                       .append(", ")
                       .append(house)
                       .append(" ")
                       .append(quarter).toString();
   }
}
Мекенжай туралы ақпарат пен әдісті (деректерді өңдеу тәртібі) бөлек сыныпқа орналастырған дұрыс:
class Human {
   private String name;
   private String age;
   private Address address;

   private String getFullAddress() {
       return address.getFullAddress();
   }
}
class Address {
   private String country;
   private String city;
   private String street;
   private String house;
   private String quarter;

   public String getFullAddress() {
       StringBuilder result = new StringBuilder();
       return result
                       .append(country)
                       .append(", ")
                       .append(city)
                       .append(", ")
                       .append(street)
                       .append(", ")
                       .append(house)
                       .append(" ")
                       .append(quarter).toString();
   }
}

Әдіс таңдау

Кез келген функционалдылықты әдісте топтастыру мүмкін болса, оны бөлек әдіске орналастыру керек. Мысалы, квадрат теңдеудің түбірлерін есептейтін әдіс:
public void calcQuadraticEq(double a, double b, double c) {
    double D = b * b - 4 * a * c;
    if (D > 0) {
        double x1, x2;
        x1 = (-b - Math.sqrt(D)) / (2 * a);
        x2 = (-b + Math.sqrt(D)) / (2 * a);
        System.out.println("x1 = " + x1 + ", x2 = " + x2);
    }
    else if (D == 0) {
        double x;
        x = -b / (2 * a);
        System.out.println("x = " + x);
    }
    else {
        System.out.println("Equation has no roots");
    }
}
Барлық үш мүмкін нұсқаны есептеуді бөлек әдістерге ауыстырайық:
public void calcQuadraticEq(double a, double b, double c) {
    double D = b * b - 4 * a * c;
    if (D > 0) {
        dGreaterThanZero(a, b, D);
    }
    else if (D == 0) {
        dEqualsZero(a, b);
    }
    else {
        dLessThanZero();
    }
}

public void dGreaterThanZero(double a, double b, double D) {
    double x1, x2;
    x1 = (-b - Math.sqrt(D)) / (2 * a);
    x2 = (-b + Math.sqrt(D)) / (2 * a);
    System.out.println("x1 = " + x1 + ", x2 = " + x2);
}

public void dEqualsZero(double a, double b) {
    double x;
    x = -b / (2 * a);
    System.out.println("x = " + x);
}

public void dLessThanZero() {
    System.out.println("Equation has no roots");
}
Әрбір әдіс үшін code әлдеқайда қысқа және түсінікті болды.

Бүкіл нысанды тасымалдау

Параметрлері бар әдісті шақырған кезде сіз кейде келесідей codeты көре аласыз:
public void employeeMethod(Employee employee) {
    // Некоторые действия
    double yearlySalary = employee.getYearlySalary();
    double awards = employee.getAwards();
    double monthlySalary = getMonthlySalary(yearlySalary, awards);
    // Продолжение обработки
}

public double getMonthlySalary(double yearlySalary, double awards) {
     return (yearlySalary + awards)/12;
}
Әдісте employeeMethodмәндерді алу және оларды қарабайыр айнымалыларда сақтау үшін 2 жолға дейін бөлінеді. Кейде мұндай дизайн 10 жолға дейін созылады. Нысанның өзін әдіске беру әлдеқайда оңай, ол жерден қажетті деректерді шығаруға болады:
public void employeeMethod(Employee employee) {
    // Некоторые действия
    double monthlySalary = getMonthlySalary(employee);
    // Продолжение обработки
}

public double getMonthlySalary(Employee employee) {
    return (employee.getYearlySalary() + employee.getAwards())/12;
}
Қарапайым, қысқа және қысқа.

Өрістерді логикалық топтастыру және оларды жеке сыныпқа орналастыру

Жоғарыда келтірілген мысалдар өте қарапайым және оларға қараған кезде көбісі «Мұны кім жасайды?» Деген сұрақ қоюы мүмкін екеніне қарамастан, көптеген әзірлеушілер назар аудармау, codeты қайта өңдеуді қаламау немесе жай ғана «Бұл жасайды» ұқсас құрылымдық қателер.

Неліктен рефакторинг тиімді

Жақсы рефакторингтің нәтижесі - codeы оңай оқылатын бағдарлама, бағдарлама логикасына өзгертулер қауіп төндірмейді, ал жаңа мүмкіндіктерді енгізу codeты талдау тозаққа айналмайды, бірақ бірнеше күн бойы жағымды әрекет. . Бағдарламаны нөлден қайта жазу оңайырақ болса, рефакторинг қолданбауы керек. Мысалы, топ codeты талдау, талдау және рефакторингке жұмсалатын еңбек шығындарын бірдей функционалдылықты нөлден енгізуге қарағанда жоғары деп бағалайды. Немесе қайта өңдеуді қажет ететін codeта жөндеу қиын болатын көптеген қателер бар. Код құрылымын жақсарту жолын білу программист жұмысында міндетті болып табылады. JavaRush-те Java бағдарламалауды үйренген дұрыс - бұл тәжірибеге назар аударатын онлайн курс. Жедел тексеруі бар 1200+ тапсырма, 20-ға жуық шағын жоба, ойын тапсырмалары - мұның бәрі codeтауда сенімді сезінуге көмектеседі. Бастау үшін ең жақсы уақыт - қазір :) Как устроен рефакторинг в Java - 4

Рефакторингке одан әрі сүңгу үшін ресурстар

Рефакторинг туралы ең танымал кітап «Рефакторинг. Қолданыстағы code дизайнын жетілдіру» Мартин Фаулер. Сондай-ақ, Джошуа Киревскидің «Үлгілермен рефакторинг» алдыңғы кітабының негізінде жазылған рефакторинг туралы қызықты басылым бар. Шаблондар туралы айтатын болсақ. Рефакторинг кезінде қолданбаның негізгі дизайн үлгілерін білу әрқашан өте пайдалы. Бұл керемет кітаптар бұған көмектеседі:
  1. «Дизайн үлгілері» - Эрик Фриман, Элизабет Фриман, Кэти Сьерра, Бас бірінші сериясынан Берт Бейтс;
  2. «Оқылатын code немесе бағдарламалау өнер ретінде» - Дастин Босвелл, Тревор Фаучер.
  3. Әдемі және талғампаз codeтың принциптерін сипаттайтын Стив МакКоннеллдің «Мінсіз code».
Рефакторинг туралы бірнеше мақалалар:
  1. Тапсырма: бұрынғы codeты рефакторингке бастайық ;
  2. Рефакторинг ;
  3. Барлығына арналған рефакторинг .
    Пікірлер
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION