JavaRush /Java блогу /Random-KY /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. Эгерде ыкма 10-15 саптан ашык codeду талап кылса, анда ал аткарган тапшырмаларды жана кошумча тапшырмаларды аныктап, кошумча тапшырмаларды өзүнчө ыкмага бөлүүгө аракет кылышыңыз керек.
Чоң ыкманы жок кылуунун бир нече жолу:
  • Методдун функциялык бөлүгүн өзүнчө методго бөлүү;
  • Эгерде локалдык өзгөрмөлөр функциянын бир бөлүгүн чыгарууга мүмкүндүк бербесе, сиз бүт an objectти башка ыкмага өткөрө аласыз.

Көптөгөн примитивдүү маалымат түрлөрүн колдонуу

Адатта, бул көйгөй класстагы маалыматтарды сактоо үчүн талаалардын саны убакыттын өтүшү менен көбөйгөндө пайда болот. Мисалы, маалыматтарды (валюта, дата, телефон номерлери ж.б.) сактоо үчүн майда an objectтердин ордуна примитивдүү типтерди же кандайдыр бир маалыматты codeдоо үчүн константаларды колдонсоңуз. Бул учурда талааларды логикалык жактан топтоп, аларды өзүнчө класска жайгаштыруу (классты тандоо) жакшы тажрыйба болот. Сиз ошондой эле класста бул маалыматтарды иштетүү ыкмаларын камтый аласыз.

Опциялардын узун тизмеси

Айрыкча чоң ыкма менен айкалышканда, бир кыйла кеңири таралган ката. Адатта, эгерде методдун функционалдуулугу ашыкча жүктөлсө же метод бир нече алгоритмдерди бириктирсе пайда болот. Параметрлердин узун тизмелерин түшүнүү абдан кыйын жана мындай ыкмаларды колдонуу ыңгайсыз. Ошондуктан, бүт an objectти өткөрүп берүү жакшы. Эгерде an objectте маалымат жетишсиз болсо, анда ал логикалык жактан байланышкан маалыматтарды иштете тургандай, жалпы an objectти колдонуу же методдун функционалдуулугун бөлүү керек.

Маалымат топтору

Логикалык жактан байланышкан маалыматтардын топтору көбүнчө codeдо пайда болот. Мисалы, маалымат базасына туташуу параметрлери (URL, колдонуучу аты, сырсөз, схема аты ж.б.). Эгерде элементтердин тизмесинен бир да талааны алып салуу мүмкүн болбосо, анда тизме өзүнчө класска (класс тандоо) жайгаштырылууга тийиш болгон маалыматтардын тобу болуп саналат.

OOP түшүнүгүн бузган чечимдер

Мындай "жыт" түрү иштеп чыгуучу OOP дизайнын бузганда пайда болот. Эгерде ал бул парадигманын мүмкүнчүлүктөрүн толук түшүнбөсө, аларды толук эмес же туура эмес колдонсо болот.

Мурастан баш тартуу

Эгерде субкласс ата-эне классынын функцияларынын минималдуу бөлүгүн колдонсо, анда ал туура эмес иерархия сыяктуу жыттанып турат. Эреже катары, бул учурда, керексиз ыкмалар жөн гана жокко чыгарылbyte же өзгөчөлүктөр ыргытылат. Эгерде класс башка класстан тукум кууса, бул анын функционалдуулугун дээрлик толук пайдаланууну билдирет. Туура иерархиянын мисалы: Java'да рефакторинг кантип иштейт - 2 Туура эмес иерархиянын мисалы: Java'да рефакторинг кантип иштейт - 3

которуу билдирүүсү

Оператор эмне туура эмес болушу мүмкүн switch? Анын дизайны абдан татаал болгондо жаман. Бул көптөгөн уяланган блокторду да камтыйт if.

Ар кандай интерфейстери бар альтернативалуу класстар

Бир нече класстар бир эле нерсени аткарышат, бирок алардын методдору башкача аталат.

Убактылуу талаа

Эгерде класста an objectке кээде гана керек болгон убактылуу талаа камтылса, ал баалуулуктарга толгондо, ал эми калган убакытта ал бош же, Кудай сактасын, nullанда code "жыттанып", мындай дизайн шектүү болуп саналат. чечим.

Өзгөрүүнү кыйындаткан жыттар

Бул "жыттар" олуттуураак. Калгандары негизинен codeду түшүнүүнү начарлатат, ал эми булар аны өзгөртүүгө мүмкүндүк бербейт. Кандайдыр бир функцияларды киргизүүдө иштеп чыгуучулардын жарымы иштен чыгып, жарымы жинди болуп калышат.

Параллелдүү мурас иерархиялары

Класстын субклассын түзгөнүңүздө, башка класс үчүн башка классты түзүшүңүз керек.

Көз карандылыкты бирдей бөлүштүрүү

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

Комплекстүү модификация дарагы

Бул жыт мурункусуна карама-каршы келет: өзгөртүүлөр ошол эле класстын көптөгөн ыкмаларына таасир этет. Эреже катары, мындай codeдогу көз карандылык каскаддуу болуп саналат: бир ыкманы өзгөрткөндөн кийин, башка бир нерсени оңдоо керек, андан кийин үчүнчүсүндө ж.б.у.с. Бир класс - көп өзгөрүүлөр.

"Таштанды жыттанып жатат"

Баш ооруну пайда кылган жыттардын бир кыйла жагымсыз категориясы. Пайдасыз, керексиз, эски code. Бактыга жараша, заманбап IDE жана линтерлер мындай жыттар жөнүндө эскертүүгө үйрөнүштү.

Методдо көп сандагы комментарийлер

Метод дээрлик ар бир сапта көптөгөн түшүндүрмө комментарийлерге ээ. Бул, адатта, татаал алгоритм менен байланышкан, ошондуктан ал бир нече майда ыкмаларды codeду бөлүп, аларга маанилүү аттарды берүү жакшы.

Кодду кайталоо

Ар кандай класстар же методдор бир эле code блокторун колдонушат.

Жалкоо класс

Класс өтө аз функцияны алат, бирок анын көбү пландаштырылган.

Колдонулбаган code

Класс, ыкма же өзгөрмө codeдо колдонулbyte жана "өлүк салмак" болуп саналат.

Ашыкча туташтыруу

Жыттардын бул категориясы codeдогу көп сандагы керексиз байланыштар менен мүнөздөлөт.

Үчүнчү тарап ыкмалары

Метод өзүнүн маалыматтарына караганда башка an objectтин маалыматтарын көп колдонот.

Туура эмес жакындык

Класс башка класстын тейлөө талааларын жана ыкмаларын колдонот.

Узун класстык чалуулар

Бир класс башкасын чакырат, ал үчүнчүдөн, төртүнчүдөн жана башкалардан маалыматтарды сурайт. Чакырыктардын мындай узун тизмеги азыркы класстык түзүлүшкө көз карандылыктын жогорку деңгээлин билдирет.

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

Класс тапшырманы башка класска өткөрүү үчүн гана керек. Балким, аны алып салуу керек?

Рефакторинг ыкмалары

Төмөндө биз сүрөттөлгөн 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у бир топ кыскараак жана түшүнүктүү болуп калды.

Бүтүндөй an objectти өткөрүп берүү

Параметрлери бар ыкманы чакырганда, кээде мындай 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ду талдоо тозокко айланbyte, бирок бир нече күн бою жагымдуу иш. . Программаны нөлдөн баштап кайра жазуу оңой болсо, рефакторинг колдонулбашы керек. Мисалы, команда codeду талдоо, анализдөө жана рефакторинг үчүн эмгек чыгымдарын бир эле функцияны нөлдөн баштап ишке ашырууга караганда жогору деп эсептейт. Же рефакторациялоо керек болгон codeдо мүчүлүштүктөрдү оңдоо кыйын болгон көптөгөн каталар бар. Коддун структурасын кантип жакшыртууну билүү программисттин ишинде милдеттүү. Ооба, JavaRush программасында Java программалоону үйрөнүү жакшы - практикага басым жасаган онлайн курс. Ыкчам текшерүү менен 1200+ тапшырмалар, 20га жакын мини-долбоорлор, оюн тапшырмалары - мунун баары codeдоодо өзүңүздү ишенимдүү сезүүгө жардам берет. Азыр баштоо үчүн эң жакшы убакыт :) Как устроен рефакторинг в Java - 4

Рефакторингге андан ары киришүү үчүн ресурстар

Рефакторинг жөнүндө эң белгилүү китеп – “Рефакторинг. Бар болгон codeекстин дизайнын өркүндөтүү” Мартин Фаулердин. Ошондой эле мурунку китебинин негизинде жазылган рефакторинг боюнча кызыктуу басылма бар - Жошуа Киревскийдин "Үлгүлөр менен рефакторинг". Калыптар жөнүндө айтсак. Рефакторингде тиркеменин дизайнынын негизги үлгүлөрүн билүү ар дайым абдан пайдалуу. Бул улуу китептер буга жардам берет:
  1. "Дизайн үлгүлөрү" - Эрик Фриман, Элизабет Фриман, Кэти Сиерра, Берт Бейтс, Баш биринчи сериясынан;
  2. "Окулуучу code же искусство катары программалоо" - Дастин Босвелл, Тревор Фаучер.
  3. Стив МакКоннеллдин "Perfect Code", кооз жана жарашыктуу codeдун принциптерин чагылдырган.
Рефакторинг жөнүндө бир нече макалалар:
  1. Тапшырма: келгиле, эски codeду рефакторингден баштайлы ;
  2. Рефакторинг ;
  3. Ар бир адам үчүн рефакторинг .
    Комментарийлер
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION