вівторок, 23 листопада 2010 р.

Як правильно писати код

От так глобально, да )))

Скільки про це вже писано-переписано, і толку. Одні кажуть "оптимізуй!" "коментуй!" "рефакторинг!" "ооп!" "інжекція!" "не дублюй", інші - не оптимізуй, не коментуй і так далі - і будь тут мудрий. От а я спробую ))) - бути мудрою )))

Головне в цьому ділі, взагалі-то, пам'ятати: цвяхи треба забивати молотком, ями копати - лопатами, а сокирою рубати дрова.

Давним-давно інтернети були повільні, процесори слабенькі, пам'ять маленька, вінти тісненькі, кожен байт графіки важив як золото, кожен процес треба було оптимізувати - видумуючи як можна хитріші алгоритми і спрощення. Навіть розмір імені змінної в деяких випадках потрібно було враховувати. Малювання кодом, оптимізаційні фішки - це все було актуальним. БУЛО. Ні, ну зараз теж є задачі, в яких потрібно мінімізувати розмір, об'єм, швидкість сортування масива, кількість запитів до сервера... Але раніше це потрібно було робити незалежно від постановки задачі, комп'ютери/інтернети у всіх були однакові. Але ж зараз ситуація змінилась! Самий простенький домашній канал дає можливість дивитись серіали онлайн, паралельно чатитись у всяких аськах/гтоках, перевіряти пошту і коментувати блоги, яка кому різниця, чи буде ваш клієнт важити на 400 кілобайт більше?
Зараз куди не сунься - важливою стала підтримуваність коду, його повторне використання, легка розширюваність, а значить - читабельність, простота і продуманість. Навіть коли тобі потрібно писати маленькі іграшки, або ж і взагалі якісь не подібні один на інший дрібні проекти - там все одно будуть спільні речі, які не потрібно кожен раз робити заново (якщо взагалі потрібно видумувати велосипед) - люба аплікація має дизайн і взаємодію з користувачем, з'єднання зі сервером. Чому тоді не написати один раз якийсь свій фреймворк, в якому чітко розділений дизайн і код, код при тому мінімально зав'язаний на тому, що саме малює дизайнер, наплодити свою бібліотеку стандартних контролів (при чому не обов'язково там зразу писати всі можливі елементи, зі всіма можливими варіаціями) або освоїти вже існуючу, в якій народ вже за роки назбирав всі можливі граблі під різними осями і девайсами. Чому не писати код акуратно, іменувати змінні по-людськи, щоб особливо і коментувати не прийшлось? Ти ж сам вже за місяць уявлення найменшого не будеш мати, що ти там і для чого написав. Не використовуй колбеків, функцій у функціях - заплутаєшся, не дублюй код - замахаєшся його всюди фіксити, розділяй дані, логіку і візуалізацію, не пиши основний функціонал в хендлерах і конструкторах - з ймовірністю 80% цей код потрібно буде викликати ще раз... І так далі і тому подібне. Люди роками писали тонни коду, написали не одну пачку рекомендацій, б'ються над методиками, описують свої граблі - не треба думати, що ти будеш розумніший за всіх них і тобі це не потрібно.

Починати треба зі занудного - код конвеншин. Взяти за основу якийсь стандарт, підкоригувати під себе, банально завести доку і шаблони - класів, подій. Поступово розширювати його правилами.
Про код конвеншин я, мабуть, напишу окремо - і для чого воно і які мої правила напрацювались довгими роками боротьби з граблями ))

Зіткнувся з якоюсь проблемою - гуглани, вже давно існує купа готових ліб для роботи з коліщатком мишки під маками, міні- і повноцінні 3D, криптування даних, обхід адобівських багів, робота зі шрифтами...
При тому, звісно ж, треба розібратись що воно там, як і для чого - але не потрібно тратити час на винайдення велосипеду зараз і його постійний ремонт потім - google oriented programming рулить )))

Читай методи оптимізації, але пам'яй, що одна ініціалізація масива, яка виконається один раз за всю аплікацію, погоди цій аплікації не зробить, а прогон циклу, який викликається всю дорогу, і в який впихнули оголошення тимчасових змінних - ось те місце, яке треба зразу написати чисто. Не фанатично оптимізувати, а просто чисто написати. Не викликати кожен раз один і той самий запит, який протягом всього виконання аплікації нічого нового не викличе, але і не грузити всю аплікацію кешуваннями даних, які всеодно постійно міняються і їх постійно запитують з параметром reload=true. І взагалі просаджує проц складна прозора графіка і меморіліки, в більшості звичайних аплікух всі інші дрібні оптимізації мало на що вплинуть.

Словом, це все можна послухати-подивитись тут, а я ще хіба опишу один з прикладів як писати потрібно, а як - ні.

От є така проста функція:

static public function zerofy(v: int, u: int = 10): String {
  return String(Math.pow(10, String(u).length - String(v).length)).slice(1) + String(
}


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

Вот скажіть мені, для чого так взагалі писати? Чому не написати просто, хоч і не так вичурно:


static public function zerofy(num: int, lenMarker: int = 10): String {
  var result: String = String(num);
  var len: int = String(lenMarker).length;

  while(result.length < len) {
    result = "0" + result;
  }

  return result;
}


Плоско, тупо, зато акуратно, ясно що робить і як, і без непередбачуваних багів.