Шлях Junior’а

Що варто вивчити більшості юних програмістів

SEClub
6 min readJan 16, 2015

За останні 7.5 років я керував більш ніж десятьма стажерами-програмістами в Ronimo та бачив сотні портфоліо студентів та випускників. Майже в усіх я бачив одні й ті ж речі, яким їм потрібно було навчитися. Дехто може очікувати, що я вважаю, що їм потрібно вивчити певні методи, алгоритми або математику, або інші форми спеціальних знань. Звісно, потрібно, але, на мою думку, це ніколи не головне. Головне, чому їм потрібно навчитися, це самодисципліна. Дисциплінованість завжди створювати якомога чистіший код, дисциплінованість здійснювати рефакторингу коду, якщо він стає брудним через зміни, що згодом відбулися під час розробки, дисциплінованість видаляти код, що не використовується, та додавати коментарі.

Велика частина часу, що я витрачаю, керуючи інтернами-програмістами, йде саме на це. Не на пояснення складних технологій або деталей нашого движка, а на те, щоб взагалі навчити їх писати кращий код. Я завжди питаю кандидатів, що вони вважають важливим для гарного програміста, і вони зазвичай відповідають, що код має бути чистим, зрозумілим та легким у супроводі. Це дійсно те, що я хочу почути, але дуже рідко трапляється, щоб юний програміст насправді послідовно дотримувався цих тверджень.

Щоб дотримуватися цих тверджень, необхідна самодисципліна, тому що вони означають продовження написання після моменту, коли “воно запрацювало”. Якщо усі змінні матимуть неправильні імена, код все одно функціонуватиме ідеально, але притому буде страшенно заплутаним. Крок від функціонуючого коду до чистого коду дає дуже малу винагороду за короткий термін: він вже працював і після очищення він все одно працює. Ось чому для цього кроку необхідна дисципліна. Це також причина, чому проходити стажування так корисно: гарний керівник буде уважним до якості коду (навіть якщо визначення “гарного коду” відрізняється для кожного програміста), а тому змушуватиме стажера або джуніора робити цей наступний крок.

Дозвольте навести декілька прикладів речей, які я часто бачу у коді програмістів-початківців:

Оманливі функції/змінні/класи

Це функції, класи або змінні, які роблять щось, що відрізняється від підказки у їх імені. Їхнє ім’я — брехня. Дуже очевидно, що імена мають бути правильними, але, на моє здивування, досить часто трапляється, що імена виявляються абсолютно недоречними.

Наприклад, нещодавно я наткнувся на 2 класи у коді, написаному колишнім інтерном: EditorGUI та EditorObjectCreatorGUI. Це код, який обробляє інтерфейс наших редакторів. На моє здивування, виявилося, що код, який опрацьовував кнопку для створення нових об’єктів, знаходився у EditorGUI, в той час як EditorObjectCreatorGUI всього лише опрацьовував навігацію по різних об’єктах. Абсолютно протилежне тому, що вказано у назві! Навіть незважаючи на те, що код був відносно простим, мені довелося витратити певний час, щоб це зрозуміти, просто тому що я розпочав із абсолютно невірного припущення на основі імен класів. У цьому випадку рішення є досить простим: переіменувати EditorObjectCreatorGUI на EditorObjectNavigationGUI, і все одразу стане значно, значно зрозуміліше.

Це те, що я часто бачу: неправильні імена. Я думаю, що це часто трапляється, оскільки код розвивається під час роботи над ним. У момент, коли було обрано ім’я, воно могло бути правильним., але до моменту, коли код було завершено, воно могло стати недоречним. Хитрість полягає у тому, щоб постійно тримати назву у голові. Ви маєте постійно думати, чи підходить те, що ви додаєте, імені функції або класу.

Брудні класи

Інша проблема, з якою я зіштовхнувся, — брудні класи: класи, що роблять багато непов’язаних речей. Знову ж таки, це трапляється по мірі того, як ви продовжуєте працювати над тим самим кодом. Нові функції додаються у найлегші місця, і в деякий момент класи роздуваються від усіх видів непов’язаної поведінки. Інколи ця роздутість проявляється навіть не у розмірі класів: клас може мати лише пару сотень рядків, але все одно містити код, що не має там знаходитися.

Це може статися, наприклад, якщо за певних причин клас GUI має аналізувати, які текстури доступні (можливо, тому що є кнопка для вибору текстури). Якщо клас GUI є єдиним класом, що потребує цього аналізу, тоді доречно робити це у класі GUI. Тим не менш, згодом якийсь абсолютно непов’язаний клас гри з певних причин теж потребує цю інформацію. Тому ви використовуєте клас GUI для запиту інформації про текстури у цьому ігровому класі. У цей момент клас GUI переріс у дещо більше: він також є класом TextureAnalyser. Рішення є простим: відділіть клас TextureAnalyser у окремий клас, що може бути використаний як класом GUI, та цим ігровим класом.

Головне правило для уникнення цієї проблеми — завжди задавати питання: чи досі підходить назві класу той функціонал, що я додаю? Якщо ні, тоді необхідно або перейменувати клас, або розділити на декілька окремих класів, або код має вирушити у окремий клас.

Зазвичай дурним знаком є те, що ви не можете придумати відповідну назву для свого класу. Якщо ви не можете описати, що робить клас, у його назві, тоді, можливо, його функціонал надто брудний. Можливо, його потрібно розділити на частини, що будуть більш зрозумілими та, власне, будуть описані власними іменами.

Надто великі класи

Це дуже схоже на брудні класи, описані вище: з часом у клас додається все більше і більше, і він стає роздутим. Тим не менш, у цьому випадку всі ці речі все ще доречно тримати у одному класі, але клас просто стає надто великим. Гігантські класи є надто громіздкими, щоб з ними працювати. Якщо багато коду маніпулює одними й тими ж приватними змінними, запросто можуть з’явитися баги, оскільки є багато деталей, які можна не помітити.

Поділ класу, який став надто великим, — це досить нудна робота. Вона також може бути проблемною, якщо код у класі сильно пов’язаний. Додайте до цього той факт, що він вже працює, і його виправлення не додає ніякого нового функціоналу. Результатом знов є те, що поділ класу у випадку, коли він став надто великим, вимагає серйозної самодисципліни.

Як головне правило у Ronimo, ми намагаємося тримати у класах менше 500 рядків, а у функціях — менше 50 рядків. Інколи це просто неможливо або нерозумно, але в основному ми шукаємо метод рефакторингу та поділу класу на менші частинки, як тільки він перетинає цю межу. (Це змушує мене поцікавитись: а яка межа у вас? Розкажіть у коментарях!)

Код у коментарях

Майже всі зразки коду, які надсилають нам кандидати, містять закоментовані фрагменти, без жодної інформації про причини. Це непрацюючий код, який потрібно виправити? Старий код, який потрібно замінити? Чому цей код знаходиться тут? Зазвичай кандидати знають про те, що закоментований код збиває з пантелику, якщо їх про це запитати, але чомусь все одно мають такий у своєму.

Паралельна логіка та повторення коду

Інша проблема, яку я часто бачу, — однакова логіка у декількох місцях.

Наприклад, можливо, що назва текстури дає певну інформацію про її призначення, на зразок “TreeBackground.dds”. Щоб дізнатися, чи може текстура бути використана для дерева, ми перевіряємо ім’я файлу, щоб побачити, чи починається воно зі слова “Tree”. Можливо, у SDK, що ми використовуємо, можливо виконати цю перевірку дуже швидко, просто використавшки filename.beginsWith(“Tree”). Цей код настільки короткий, що якщо нам потрібно використати його у різних місцях, ми можемо просто вставити його там. Звісно, це повторення коду, і кожен знає, що повторення коду потрібно уникати, але якщо повторюваний код настільки короткий, то заманливо просто його скопіювати. Проблема, з якою ми зіштовхнулися, очевидна: можливо, пізніше спосіб перевірки, чи підходить текстура, зміниться. Тоді нам потрібно виправляти код окремо у кожному місці.

Головне правило тут: якщо код є досить специфічним, тоді потрібно не копіювати його, а створити окрему функцію. Навіть якщо він дуже короткий, і виклик функції вимагає більше коду, ніж виконання цієї дії напряму.

Усі речі, які обговорювалися у цій статті, є досить очевидними. Більшості із цих речей навіть вчать на першому курсі університету. Проблема у тому, щоб перейти від знання до, власне, витрати часу на постійне їх дотримування. Ось чому найважливіша річ, якій стажери-програмісти вчаться у Ronimo, — не знання, а самодисципліна.

Автор зображень: Electric Art
Оригінальна стаття

--

--