Глава 11. Хитрости и хакове

В настоящата глава ще разгледаме някои хитрости, хакове и техники, които ще улеснят работата ни с езика Java в средата за разработка IntelliJ IDEA. По-специално ще се запознаем:

  • Как правилно да форматираме код
  • С конвенции за именуване на елементи от код
  • С някои бързи клавиши (keyboard shortcuts)
  • С някои шаблони с код (code snippets)
  • С техники за дебъгване на код

Форматиране на кода

Правилното форматиране на нашия код ще го направи по-четим и разбираем, в случай че се наложи някой друг да работи с него. Това е важно, защото в практиката ще ни се наложи да работим в екип с други хора и е от голямо значение дали пишем кода си така, че колегите ни да могат бързо да се ориентират в него.

Има определени правила за правилно форматиране на кода, които събрани в едно се наричат конвенции. Конвенциите са група от правила, общоприети от програмистите на даден език, и се ползват масово. Тези конвенции помагат за изграждането на норми в дадени езици - как е най-добре да се пише и какви са добрите практики. Приема се, че ако един програмист ги спазва, то кодът му е лесно четим и разбираем.

Програмният език Java е създаден от Sun Microsystems (технологична компания, погълната по-късно от Oracle) и Sun са тези, които създават една от първите конвенции за Java. Трябва да знаете, че дори да не спазвате общоприетите конвенциите, кодът ви ще работи (стига да е написан правилно), но просто няма да бъде лесно разбираем от останалите програмисти. Това, разбира се, не е фатално на основно ниво, но колкото по-бързо свикнете да пишете качествен код, толкова по-добре.

Най-широко възприетата съвременна Java код конвенция се нарича "Google Java Style Guide" (https://google.github.io/styleguide/javaguide.html) и в тази книга ще се ръководим основно от нея.

За форматиране на кода в Java света се препоръчва къдравите скоби {} да са в следното разположение - отварящата скоба да е на същия ред, а затварящата скоба да е точно под конструкцията, към която се отнасят, както е в примера по-долу.

if (someCondition) {
    System.out.println("Inside the if statement");
}

Вижда се, че командата System.out.println(…) в примера е 4 празни полета навътре (един таб), което е стандарта в Java. Без значение колко таба навътре започва определена конструкция с къдрави скоби (т.е. без значение колко влагания на различни оператори имаме), затварящата скоба трябва да е под началото на конструкцията, както е в примера по-долу:

if (someCondition) {
   if (anotherCondition) {
       System.out.println("Inside the if statement");
   }
}

Ето това е пример за лошо форматиран код спрямо общоприетите конвенции за писане на код на езика Java:

if(someCondition)
{
System.out.println("Inside the if statement");}

Първото, което се забелязва са къдравите скоби {}. Първата (отваряща) скоба трябва да е след if условието, a втората (затваряща) скоба - под командата System.out.println(…), на отделен празен ред. В допълнение, командата вътре в if конструкцията трябва да бъде 4 празни полета навътре (един таб). Веднага след ключовата дума if и преди условието на проверката и веднага след него преди { се оставя интервал.

Същото правило важи и за for цикли и всякакви други конструкции с къдрави скоби {}. Ето още няколко примера:

Правилно:

for (int i = 0; i < 5; i++) {
    System.out.println(i);
}

Грешно:

for(int i=0;i<5;i++)
{
System.out.println(i);
}

За ваше удобство има бързи клавиши в IntelliJ IDEA, за които ще обясним по-късно в настоящата глава, но засега ни интересуват две конкретни комбинации. Едната комбинация е за форматиране на кода в целия документ, а другата комбинация - за форматиране на част от кода. Ако искаме да форматираме целия код, то трябва да натиснем [CTRL + ALT + L]. В случай, че искаме да форматираме само част от кода, то ние трябва да маркираме частта, която искаме да форматираме, и да натиснем [Ctrl + Shift + Alt + L].

Нека използваме грешния пример от преди малко:

for(int i=0;i<5;i++)
{
System.out.println(i);
}

Ако натиснем [CTRL + ALT + L], което е нашата комбинация за форматиране на целия документ, ще получим код, форматиран според общоприетите конвенции за Java, който ще изглежда по следния начин:

for (int i = 0; i < 5; i++) {
    System.out.println(i);
}

Тази комбинация може да ни помогне, ако попаднем на лошо форматиран код.

Именуване на елементите на кода

В тази секция ще се фокусираме върху общоприетите конвенции за именуване на проекти, файлове и променливи в Java света.

Именуване на проекти и класове

За именуване на проекти и класове се препоръчва описателно име, което подсказва каква е ролята на въпросния клас / проект и в същото време се препоръчва PascalCase конвенцията. Tова е конвенция за именуване на елементи, при която всяка дума, включително първата, започва с главна буква, например ExpressionCalculator.

Пример: в този курс се започва с лекция на име First steps in coding и следователно едно примерно именуване на проекта за тази лекция може да бъде FirstStepsInCoding. Същата конвенция важи и за класовете в даден проект. Ако вземем за пример първата задача от лекцията First steps in coding, тя се казва Hello World и следователно нашият файл в проекта ще се казва HelloWorld.

Именуване на променливи

В програмирането променливите пазят някакви данни и за да е по-разбираем кода, името на една променлива трябва да подсказва нейното предназначение. Ето и още няколко препоръки за имената на променливите:

  • Името трябва да е кратко и описателно и да обяснява за какво служи дадената променлива.
  • Името трябва да се състои само от буквите a-z, A-Z, цифрите 0-9, както и символите '$' и '_'.
  • В Java е прието променливите да започват винаги с малка буква и да съдържат малки букви, като всяка следваща дума в тях започва с главна буква (това именуване е още познато като camelCase конвенция).
  • Трябва да се внимава за главни и малки букви, тъй като Java прави разлика между тях. Например age и Age са различни променливи.
  • Имената на променливите не могат да съвпадат със служебна дума (keyword) от езика Java, например int е невалидно име на променлива.
Въпреки че използването на символа _ в имената на променливите е разрешено, в Java това не се препоръчва и се счита за лош стил на именуване.

Ето няколко примера за добре именувани променливи:

  • firstName
  • age
  • startIndex
  • lastNegativeNumberIndex

Ето няколко примера за лошо именувани променливи, макар и имената да са коректни от гледна точка на компилатора на Java:

  • _firstName (започва с '_')
  • last_name (съдържа '_')
  • AGE (изписана е с главни букви, което е грешно име за променлива, но е правилно име за константа)
  • Start_Index (започва с главна буква и съдържа '_')
  • lastNegativeNumber_Index (съдържа '_')

Първоначално всички тези правила може да ни се струват безсмислени и ненужни, но с течение на времето и натрупването на опит ще видите нуждата от норми за писане на качествен код, за да може да се работи по-лесно и по-бързо в екип. Ще разберете, че е изключително досадна работата с код, който е написан без да се спазват никакви правила за качествен код.

Бързи клавиши в IntelliJ IDEA

В предната секция споменахме за две от комбинациите, които се отнасят за форматиране на код. Едната комбинация [Ctrl + Alt + L] беше за форматиране на целия код в даден файл, а втората [Ctrl + Shift + Alt + L] ни служеше в случай, че искаме да форматираме само дадена част от кода. Тези комбинации се наричат бързи клавиши и сега ще дадем по-подробна информация за тях.

Бързи клавиши са комбинации, които ни предоставят възможността да извършваме някои действия по-лесно и по-бързо, като всяка среда за разработка на софтуер си има своите бързи клавиши, въпреки че повечето се повтарят. Сега ще разгледаме някои от бързите клавиши в IntelliJ IDEA.

Комбинация Действие
[CTRL + F] Комбинацията отваря търсачка, с която можем да търсим в нашия код.
[CTRL + /] Закоментира част от кода. / Разкоментира код, който е вече закоментиран.
[CTRL + Z] Връща една промяна назад (т.нар. Undo).
[Ctrl + Shift + Z] Комбинацията има противоположно действие на [CTRL + Z] (т.нар. Redo).
[CTRL + ALT + L] Форматира кода според конвенциите по подразбиране.
[CTRL + Backspace] Изтрива думата вляво от курсора.
[CTRL + Del] Изтрива думата вдясно от курсора.
[CTRL + S] Запазва всички файлове в проекта.
[CTRL + D] Копира ред или маркирания фрагмент.
[CTRL + Y] Изтрива текущия ред.

Повече за бързите клавиши в IntelliJ IDEA може да намерите тук: https://www.jetbrains.com/help/idea/keyboard-shortcuts-by-category.html.

Шаблони с код (code snippets)

В IntelliJ IDEA съществуват т.нар. шаблони с код (code snippets), при изписването на които се изписва по шаблон някакъв блок с код. Примерно при изписването на sout + [Enter] се изписва кодът System.out.println();:

Да си направим собствен шаблон за код

В тази секция ще покажем как сами да си направим собствен шаблон. Ще разгледаме как се прави code snippet за scanner.nextLine();. Като за начало ще си създадем нов празен проект и ще отидем на [File → Settings → Editor → Live Templates], като избираме [+Live Template], както е показано на снимката по-долу.

Излиза нов прозорец, който изглежда както на следващата картинката.

Тук попълваме следната информация:

  • [Abbreviation] - тук се вписва code snippet-a, който ще използваме. В конкретния случай това е scnl.
  • [Description] - тук се попълва описание за snippet-a. В нашия случай това е scanner.nextLine().
  • [Template text] - тук въвеждаме кода, който ще се генерира при изписване на съкращението. В този случай, това е кода по-долу:
Scanner scanner = new scanner(Sysrtem.in);
String s = scanner.nextLine();

След това маркираме [Reformat according to style], a от [Define] избираме [Java], след което натискаме [OK], както е показано на картинката по-долу.

Вече когато напишем scnl в IntelliJ IDEA, нашият нов snippet се появява:

Техники за дебъгване на кода

Дебъгването играе важна роля в процеса на създаване на софтуер, която ни позволява постъпково да проследим изпълнението на нашата програма. С помощта на тази техника можем да следим стойностите на локалните променливи, тъй като те се променят по време на изпълнение на програмата, и да отстраним евентуални грешки (бъгове). Процесът на дебъгване включва:

  • Забелязване на проблемите (бъговете).
  • Намиране на кода, който причинява проблемите.
  • Коригиране на кода, причиняващ проблемите, така че програмата да работи правилно.
  • Тестване, за да се убедим, че програмата работи правилно след нанесените корекции.

IntelliJ IDEA ни предоставя вграден дебъгер (debugger), чрез който можем да поставяме точки на прекъсване (или breakpoints) на избрани от нас места. При среща на стопер (breakpoint), програмата спира изпълнението си и позволява постъпково изпълнение на останалите редове. Дебъгването ни дава възможност да вникнем в детайлите на програмата и да видим къде точно възникват грешките, както и каква е причината за това.

За да демонстрираме работа с дебъгера ще използваме следната програма:

public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
        System.out.println(i);
    }
}

Ще сложим стопер (breakpoint) на функцията System.out.println(…). За целта трябва да преместим курсора на реда, който печата на конзолата, и да натиснем [Ctrl + F8] или да кликнем с десния бутон на мишката от дясно на номера на реда. Появява се точка на прекъсване, където програмата ще спре изпълнението си.

За да стартираме програмата в режим на дебъгване, избираме [Run] → [Debug <име на класа>] или натискаме [SHIFT + F9].

След стартиране на програмата виждаме, че тя спира изпълнението си на ред 8, където сложихме стопера (breakpoint). Кодът на текущия ред се маркира в допълнителен цвят и можем да го изпълняваме постъпково. За да преминем на следващ ред използваме клавиш [F8]. Забелязваме, че кодът на текущия ред все още не е изпълнен. Изпълнява се, когато преминем на следващия ред. В зелено се показва текущата стойност на променливата, на снимката по-долу i = 0.

От прозореца [Variables] можем да наблюдаваме промените по локалните променливи.

Справочник с хитрости

В тази секция ще припомним накратко хитрости и техники от програмирането с езика Java, разглеждани вече в тази книга, които ще са ви много полезни, ако ходите на изпит по програмиране за начинаещи:

Форматиран изход с printf()

За отпечатването на дълги и сложни поредици от елементи можем да използваме метода printf(…). Този метод е съкращение на "Print Formatted". Основната идея на printf(…) е да приеме специален стринг, форматиран със специални форматиращи символи и списък със стойностите, които трябва да се заместят на мястото на "форматните спецификатори".

printf(<formatted string>, <param1>, <param2>, <param3>, …)

Пример:

String str = "some text";
System.out.printf("%s", str);
// Tова ще отпечата на конзолата "some text"

Първият аргумент на метода printf(…) е форматиращият стринг. В случая %s означава, че трябва да се разпечата стринг str, на мястото на %s.

String str1 = "some text";
int number = 5;
String str2 = "some more text";
System.out.printf("%s %d %s \n", str1, number, str2);
// Tова ще отпечата на конзолата "some text 5 some more text"

В този пример забелязваме, че можем да подаваме не само текстови променливи. Първият аргумент е форматиращият низ. Следва поредица от аргументи, които се заместват на местата, където има процент, следван от буква (%s или %d). Първият %s означава да се постави на негово място първия аргумент, подаден след форматиращия низ, в случая str1. Следва %d, което означава да се замести с първото целочислено число, подадено в аргументите. Последният специален символ е отново %s, което означава да се замести със следващия по ред символен низ str2. Следва \n, което е специален символ, който указва преминаване на нов ред. Можем да използваме дадена променлива няколко пъти.

String str = "some text";
int number = 5;
System.out.printf("%s %d %s \n", str, number, str);
// Tова ще отпечата на конзолата "some text 5 some text"

Закръгляне на числа с плаваща запетая

Реалните типове с плаваща запетая, които използваме в Java, са float и double.

double number = 5.432432;
System.out.println(Math.round(number));
// Tова ще отпечата на конзолата "5"

Ако първата цифра след десетичния знак е по-малкa от 5, както в примера по-горе, то закръглянето е надолу, но ако е 5 или по-голяма - закръглянето е нагоре, както е в примера по-долу:

double number = 5.543;
System.out.println(Math.round(number));
// Tова ще отпечата на конзолата "6"

Други методи за закръгляне

В случай, че искаме винаги да закръгляме надолу можем вместо Math.round(…) да използваме друг метод - Math.floor(…), който винаги закръгля надолу. Например, ако имаме числото 5.99 и използваме Math.floor(5.99), ще получим числото 5.0.

Можем и да направим точно обратното - винаги да закръгляме нагоре, използвайки метода Math.ceil(…). Отново, ако имаме число, примерно 5.11 и използваме Math.ceil(5.11), ще получим 6.0. Ето и няколко примера:

double numberToFloor = 5.99;
System.out.println(Math.floor(numberToFloor));
// Tова ще отпечата на конзолата 5.0

double numberToCeiling = 5.11;
System.out.println(Math.ceil(numberToCeiling));
// Tова ще отпечата на конзолата 6.0

Форматиране с две цифри след десетичния знак

double number = 5.432432;
System.out.printf("%.2f%n", number);
// Tова ще отпечата на конзолата 5.43

В случая използваме форматиращият стринг %.2f, което ще ограничи числовата променлива до 2 цифри след десетичния знак. Tрябва да имаме предвид, че числото пред буквата f означава до колко цифри след десетичния знак да е закръглено резултата (т.е. може да е %.3f или %.5f). Препоръчително е с printf() като символ за нов ред да използваме %n, вместо /n.

Как се пише условна конструкция?

Условната if конструкция се състои от следните елементи:

  • Ключова дума if
  • Булев израз (условие)
  • Тяло на условната конструкция
  • Незадължително: else клауза
if (условие) {
    // тяло
} else (условие) {
    // тяло
}

За улеснение може да използваме code snippet за if конструкция:

  • if + [Enter]

Как се пише for-цикъл?

За for цикъл ни трябват няколко неща:

  • Инициализационен блок, изпълнява се само веднъж преди да се провери условието за повторение. Най-често се декларира променливата-брояч (int i) и се задава нейна начална стойност.
  • Условие за повторение (i <= 10).
  • Обновяване на брояча (i++).
  • Тяло на цикъла.
for (int i = 0; i <= 10; i++) {
    // тяло
}

Важно е да знаем, че и трите части на for цикъла са незадължителни и могат да се пропуснат. for(; ; ) { … } е валиден пример за for цикъл.

За улеснение може да използваме code snippet за for цикъл:

  • fori + [Enter]

Какво научихме от тази глава?

В настоящата глава се запознахме как правилно да форматираме и именуваме елементите на нашия код, някои бързи клавиши (shortcuts) за работа в IntelliJ IDEA, шаблони с код (code snippets) и разгледахме как се дебъгва код.

results matching ""

    No results matching ""