Бесплатно скачать Adobe Flash Player

Да здравствует гигиена кодирования насыщенных приложений!

Возникла идея обсудить важные вопросы, касающиеся чистоты кода. Как писать чистый код и как почистить код испачканный, какие средства ухода за кодом нам известны и как их применять, кто какие гайдлайны по форматированию кода знает и как их правильно использовать, и почему вообще важен вопрос чистоты кода — вот что хотелось бы обсудить всем вместе.

Итак, без недели месячник борьбы за чистоту кода объявляется открытым. Призываю вас к публичному обсуждению этих немаловажных вопросов! Как вам эта идея? Нравится? Сделаем? Обсуждение можно провести 16 августа в Киеве под лозунгом "За чистый код!"

Если вам есть, чем поделиться — предлагайте тему, или скажите, о чем хочется услышать.

И, конечно, не забывайте регистрироваться.

Писал: Rost, 25 Июль 2008 23:51

Комментарии:

идея хороша, но где накопать реальных примеров? по жизни, либо код подчищается с одновременным добавлением новых фич (= нового мусора), либо вообще переписывается.

makc - 26 Июль 2008 16:51

Очень распространённая дилемма...

В нескольких местах используется одинаковый код.
Выделяем его в отдельную функцию с мыслью: "если потребуется что-то поменять, то поменяем в одном месте, не надо будет лазить по всей портянке и в 10 местах менять одно и тоже".

А потом вдруг приходится внести такие изменения, что этот "одинаковый" код должен быть вовсе не одинаковым - в одном случае одна специфика, в другом - другая. Приходится вставлять в эту "универсальную" функцию кучу условий, чтобы она по прежнему подходила для всех случаев.

Вот и часто задумываюсь, что всё-таки лучше: оформлять повторяющийся код в виде функции или сперва копи-пастить.

Dan - 26 Июль 2008 18:34

" оформлять повторяющийся код в виде функции или сперва копи-пастить." ГоФ читать надо. СРОЧНО!!!

Mokus - 26 Июль 2008 23:22

Один из наиболее распространенных гайдлайнов от Фабио и компании:
"Adobe Flex programming coding style & guidelines at DClick"
http://blog.dclick.com.br/wp-content/uploads/adobe-flex-coding-guidelines-v12-english.pdf
Вроде как стараемся придерживаться его у себя на проекте. Насколько мне известно, у Adobe до сих пор нет концентрированного документа касающегося стиля и нюансов оформления кода. Интересно узнать об альтернативах или может кто-то использует самоварные варианты.

- 26 Июль 2008 23:45

Предлагаю придумать типовую задачу и пусть потом все, у кого есть уверенность, выскажутся какова должна быть структура проекта (чем подробнее тем лучше). Тоесть, где в таком случае нужно наследование, где функции, у кого какие полномочия и т.д.
Можно создать для этого отдельную страницу (самые продуманные версии), где можно будет обсудить каждый подход. И вопросы актуальные появятся (для докладов на встрече) и сами поучимся.

Xitri - 27 Июль 2008 0:16

ГоФ читать надо

Прочитал я эти три буквы. Несколько раз. Потом погуглил. Несколько раз.
Таки истина меня так и не накрыла.

Dan - 27 Июль 2008 1:37

http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions

Slon_vsapogah - 27 Июль 2008 2:29

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

tearaway_Tea - 27 Июль 2008 3:41

2Dan http://www.dofactory.com/Patterns/Patterns.aspx

Mokus - 27 Июль 2008 9:14

Slon_vsapogah: там тоже иногда весьма сомнительные примерчики:
var b:Button = new Button();
- хотя говорят не о наименовании переменных, но применять в таком документе однобуквенные переменные - противоречить самим себе.

iv - 27 Июль 2008 13:18

сначала холивар о Flex Framework, теперь вот это. Этот блог наверное скоро превратиться центр интеллегентных баталий.

Alexey - 27 Июль 2008 13:23

и есть такие, с которыми я категорически не согласен:
Do this:

if (flag)
doThing1();

Not this:

if (flag)
{
doThing1();
}

But if any branch has multiple statements, make all of them into blocks.
- т.е. если у меня добавилась строка, я тут же должен пробежаться и расставить фигурные скобочки. А как только убралась обратно, то фигурные скобочки нужно пробежаться и убрать. Ну типа "зато есть чем заняться".

iv - 27 Июль 2008 13:26

ГоФ - это банда четырех (Gang of four). Мне известна их книга про паттерны. Про рефакторинг есть книга Фаулера. Также важность стандартов в коде рассмотрена в книга Брюса Тейта "Горький вкус Java".

Андрей Горбатов - 27 Июль 2008 16:43

1. А, про паттерны слышал, но, увы, так и не прочёл. Какой конкретно паттерн решает дилемму копипаст vs функция?

2. Обсуждение Flex Coding Conventions (в том числе критику) можно найти здесь: http://gotoandflash.ru/forum/index.php?showtopic=3025

Dan - 27 Июль 2008 19:55

2 Все.
Ктото знает форматтеры для Еклипса, которые можно под АС наконфигать? Мне в голову приходить только наколбасить свой на еклипс манки.

2 Dan.
Прочитай обязательно. Дилемы "копипаста против функции" не существует. Копипаст ВСЕГДА ЗЛО. Если в проге есть копипаст - он должен быть уничтожен. А резолвается по разному - вынесением логики в базовый класс, в утилитный класс, в отдельный класс итд. Когда решение не предоставляет нужной гибкости - логика дополнительно структурируется и при этом часто юзаються паттерны.
Короч, если хочеш - приведи пример, я постараюсь пояснить какой патерн там заюзать и как и нужно ли.

Mokus - 27 Июль 2008 20:47

Mokus, если бы копипаст был злом, то его бы просто не сделали бы :) А вот прокладка между клавиатурой и стулом - вот это да...

Изучить 30-40 основных шаблонов не так-то сложно (все они с примерами приведены в книге "UML 2.0 и шаблоны проектирования"), но качество проектирования/программирования/разработки это не повысит. Вопрос именно в опыте. Когда его нет - шаблоны не помогут, когда они есть - они будут тормозить/ограничивать. А нужны они где-то посередине между отсутствием опыта и его наличием :)

А каждое такое пояснение на примерах - либо целая статья либо будет не понятно.

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

Alexey - 27 Июль 2008 21:50

А резолвается по разному - вынесением логики в базовый класс, в утилитный класс, в отдельный класс итд.

А если у меня внутри класса копипаст? :) Мне нужно будет создать intrenal класс? :)

Последний раз у мнея такая дилемма возникала не в AS, а в JS, но паттерны от языка не зависят, так что приведу этот пример.
Один человек (не я) делал юзерскрипт для оперы, позволяющий на строго определённом сайте скрывать некоторые ненужные блоки. Блоков, которые надо было скрыть много.
И автор скрипта примерно раз 8 написал:
blablabla.style.display = "none";

Мне показалось это некрасивым. Кроме того, если захотим не скрывать, а например выделять цветом, то придётся 8 раз подряд переправить на
blablabla.style.color = "#FF0000";
или типа того.

Поэтому я сделал отдельную функцию. Однако потом я решил, что лучше не полностью прятать блок, а делать "спойлер". И тут оказалось, что универсальную функцию сделать не так-то просто - в разных случаях она должна действовать по-разному.

А как надо было поступить по-умному, чтобы в последствии код был достаточно гибким?

Dan - 27 Июль 2008 23:03

2 Alexey.
true. Согласен. Если разработчик толковый, то книгу о патернах будет читать с мыслью "Так вот как называеться то, что я вчера написал". Но в любом случае книжка поможет структурировать знания и, возможно, упростить некоторые уже использованые решения. Другое дело, если ты решаеш уже 100 раз решенную задачу - например пишеш скриптовый движок для игры, физический движок, либу для создания моков.. че угодно. Тогда не разобратся с архитектурой уже готовых решений на других языках, и не почитать книгу с шаблонными решениями в этой области (если имеется, конечно) просто глупо.

2 Dan.
В описаном варианте хватит константу ввести...

Mokus - 27 Июль 2008 23:29

В описаном варианте хватит константу ввести...

Константу? Боюсь, если тут и можно прилепить константу с какого-то боку, то выглядить это будет страшно. Типа такого:
var MY_SUPER_DUPER_CODE = 'blablabla.style.display = "none"';
eval (MY_SUPER_DUPER_CODE);

Dan - 28 Июль 2008 0:00

ты прав. это страшно. даже более. ужас. зря я это наночь глядя прочитал. зачем ты так жестко с констатами?
var DISPLAY_STYLE_NONE = "none";
blablabla.style.display = DISPLAY_STYLE_NONE;

Mokus - 28 Июль 2008 0:10

если честно это не тот пример, где возникают какието вопросы и который можно разбирать по частя типа "как лучше"...

Mokus - 28 Июль 2008 0:15

А если я захочу, как упоминалось выше, что-нибудь типа такого:

blablabla.style.color = "#FF0000";

или, боже упаси, что-нить подлиннее?

О, а давайте правда всё делать константами:

var BLABLABLA= "blablabla";
var STYLE = "style";
var STYLE_DISPLAY = "display";
var DISPLAY_STYLE_NONE = "none";
var STYLE_COLOR = "color";
var STYLE_COLOR_RED = "#FF0000";

eval(BLABLABLA)[STYLE][STYLE_DISPLAY] = DISPLAY_STYLE_NONE;

Извините за нездоровый юмор.

Dan - 28 Июль 2008 0:20

2 Dan.
Если тебе нужна помощь - я как и раньше готов попробовать помочь.
Если тебе просто нехрен делать - сорри, это не ко мне. Удачных тебе поисков идеальной функции.

Mokus - 28 Июль 2008 9:24

iv: мне кажется, что не важно, как конкретно будет оформлен код - важно чтобы он везде был оформлен одинаково (даже до мелочей). Поэтому если проект пишется на Flex, то разумно использовать Адобовские конвеншены.

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

Slon_vsapogah - 28 Июль 2008 11:44

2Mokus
Если ты действительно хочешь помочь, то потрудись хотя бы внимательно читать, иначе помощь оказывается медвежьей.
Если же тебе просто хочется менторским голосом рассказывать про сферических коней в вакууме, но не хватает слушателей, то устройся на четвертьставки учителем/преподавателем.

Dan - 28 Июль 2008 13:48

Смысл?!
Возможно, я повторюсь, но все же.. http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions
И не надо ничего устраивать. Надо читать, запоминать, и писать.

Jloa - 28 Июль 2008 16:18

Да...
Тема, я смотрю, наболевшая

Xitri - 28 Июль 2008 18:39

2Dan:

var styleDisplayNone = [blah1, blah2, blah5 ....];
for (var i = 0; i styleDisplayNone [i].style.display = "none";

var styleColorRed = [blah1, blah3, blah4 ....];
for (var i = 0; i styleColorRed [i].style.color = "#FF0000";

makc - 29 Июль 2008 0:07

Apparently this blog does not love < but I hope you can reconstruct this in your mind.

makc - 29 Июль 2008 0:09

2 Dan.
Ок, извини за тон.
Думаю коменты не слишком удобное место чтоб чето пояснять. Если хош - пиши в мыло, я отпишу свой айди в скайпе - спишемся.

Mokus - 29 Июль 2008 13:12

Навіяло ілюстрацію по темі http://rtwots.blogspot.com/2008/07/blog-post_29.html

Anj - 29 Июль 2008 15:20

Dan:
в твоем описании проблемы недостаточно данных, чтобы рекомендовать что-то конкретное. К тому-же, JS не совсем тема данного блога.
Но, включив свои телепатические возможности, попробую предположить, что тебе просто требуется достаточно гибкий метод, позволяющий оптом задавать одинаковое значение свойства группе объектов.
Смею предположить, что вот такое решение (частично продемонстрированное makc, но побитое движком бложика) было-бы полезным:

var DISPLAY = "display";
var NONE = "none";

var hideArray = [blah1, blah2, blah5];

function setPropertyToObjects(property, value, objects) {
var length = objects.length;
for (var i = 0; i (знак меньше) length; i++) {
var obj = objects[i];
if (obj != null && obj.style != null) {
obj.style[property] = value;
}
}
}

// test:
setPropertyToObjects(DISPLAY, NONE, hideArray);

Но, если говорить о паттернах проектирования, то это не совсем то, что может помочь в решении данной конкретной задачи. Шаблоны нужны для решения задач более абстрактного уровня.

Другое дело, если на задачу посмотреть шире: к примеру, тебе требуется выключать/включать различные группы объектов, в зависимости от ситуации. В этом случае прекрасно может помочь шаблон State.
Хотя в итоге реализация State на JS может превратиться в веселую народную забаву из-за корявости и морального износа этого языка.

И да, JS - отстой, AS - мэйнстрим. Холиварр!

- 29 Июль 2008 19:01

Slon_vsapogah: а мне кажется, что не важно, как конкретно будет оформлен код - важно не писать его во Flex.
Адобовские конвеншены - сырой, смешной, непродуманный и неоконченный документ, который можно принять за основу для работы рашпилем.

Вспомни, совместную с тобой работу мы _начинали_ с внутрикорпоративных конвенций. Flex скоро выпустит 4-ю версию, а толковых конвенций у них до сих пор нет (а нужен-то 1 день работы специалиста). Что говорит об их общем отношении к этому вопросу, ну и результат, я бы сказал, всё еще соответствует.

iv - 29 Июль 2008 19:11

PS: "результат, я бы сказал, всё еще соответствует" - сам факт наличия сабжа предыдущего поста в этом блоге весьма красноречив.

iv - 29 Июль 2008 19:20

Пример на JS я действительно описал не очень хорошо. Там одинаковый код шёл не подряд, а вывзвался из разных мест и для разных объектов, которые динамически выдёргивались из DOM.
Вобщем, цикл там явно никак не подходит.

Вот сегодня появился новый примерчик, уже на AS3.
Есть некая самописная оболочка (почему не один их готовых прожекторов - это отдельная история и к делу не относится), предоставляющая флешу такие стандартные сишные функции, как fopen, fread, fseek и так далее.

Я делаю более высокоуровневый класс, который позволяет сделать из этих низкоуровневых функций что-то более красивое.

Например, нужно определить длину файла.
Делается это так:

var handle:uint = shell.open(path);
shell.fseek(handle, 0, 2);
var size:int = shell.ftell(handle);
shell.fclose(handle);

Вариант через копи-пастом: каждый раз, когда нужно определить размер файла, вставляем эти четыре строчки. Если необходимо, как-то их модифицируем или удаляем ненужные (например, первую и последнюю, если файл уже открыт и закрывать его не надо).
Но это ведь "грязно" и никуда не годится! Поэтому оформляем в виде геттера:

public function get size():uint {
var handle:uint = shell.fopen(path);
shell.fseek(handle, 0, 2);
var offset:uint = shell.ftell(handle);
shell.fclose(handle);
return offset;
}

Теперь у нас есть короткая функция, которую можно использовать где угодно! Гип-гип-ура!
Даже там, где файл уже открыт. Упс...

Придётся поменять:

public function get size():uint {
var needClose:Boolean = false;

// тут handle - поле. handle == null означает, что файл не открыт

if (!handle) {
handle = shell.fopen(path);
needClose = true;
}
shell.fseek(handle, 0, 2);
var offset:uint = shell.ftell(handle);
if (needClose) {
shell.fclose(handle);
handle = null;
}
return offset;
}

Ура! Теперь наша функция точно универсальна!
Правда, ломает указатель на текущую позицию в файле.
Надо сохранять...

public function get size():uint {
var oldPos:uint;
var needClose:Boolean = false;
if (!handle) {
handle = shell.fopen(path);
needClose = true;
} else {
oldPos = shell.ftell(handle);
}
shell.fseek(handle, 0, 2);
offset = shell.ftell(handle);
if (needClose) {
shell.fclose(handle);
handle = null;
} else {
shell.fseek(handle, oldPos, 0);
}
}

Ну теперь-то наша функция точно будет работать всегда. Правда вместо четырёх (или даже двух) строчек получили 18, и в любом случае проверяются различные условия (даже если мы заранее знаем, какой у них исход). Кроме того идёт сохранение и восстановления текущей позиции в файле даже если она нам не нужна. Да ещё и закрывается файл в конце. А если сразу после проверки размера файла мы захотим его открыть? Получаются лишние телодвижения.

Можно, конечно, отказаться от геттера и сделать это функцией, чтобы добавить дополнительные параметры:

function getSize(preservePosition:Boolean = true, closeFile:Boolean = true) { ... }
и навставлять ещё кучу условий.

Но добились ли мы при этом чистоты кода? Может всё-таки копипаст был бы чище?

Dan - 29 Июль 2008 22:54

2 Dan
я б предложил сваливать из коментов в этой теме - в скайпе или аське будет еффективнее.
Здесь я бы предложил просто сделать класс File
интерфейс приблизительно такой:

function get size() : uint;
function get currentPosition() : uint;
function get isOpen() : Boolean;
function open();
function seek(???);//не вкурсе че там у тя в параметрах
function read(???);

Если файл не открыт - а ктото пробует из него читать вообще хорошо кинуть ексепшен, но впринцыпе можно и форснуть открытие (вызов этого метода натыкай в файле где хош )
private function ensureOpen() : void
{
if(!isOpen)
open();
}

так, как проперти сайз импользуется оочень часто - можно при открытии сайз записать в прайват переменную и потом ее изменять в случае надобности.. итд. Детали реализации я не опишу - они будут ясны в процессе реализации, а я не сомневаюсь, что ты без проблем с этим справишся и будеш иметь красивый и реюзабельный класс File.

Еще, насколько я понял (я НЕ уверен - слишком неполная постановка задачи), если ты тотже файл юзаеш в нескольких местах, то должен юзаться тотже обьект файла (соответственно в разных местах ты сможеш узнать, что ктото файл открыл, что изменился сайз итд. - можеш евенты ввести если хош). Для того, чтоб везде для каждого файла ты получал тотже обьект надо будет сделать чето типа FileLocator (паттерн сервис локатор, может быть еще синглтоном), через который ты будеш создавать обьекты класса файл.

Даже если вышеописаное кажется громоздким - на самом деле кода будет фигня и економия сил, времени и строчек будет заметна даже в маленьком проекте, кроме того всегда приятно будет это реюзнуть.

Mokus - 29 Июль 2008 23:42

@Mokus, Dan тут правильно задвигает. Следуя твоей логике, идеальным паттерном был бы класс (с сопутствующими библиотеками на пару гигов), имплементирующий интерфейс типа

public interface IPanacea {
function solve (formalProblemDescription:String):void;
}

который всегда приятно зареюзить

makc - 30 Июль 2008 12:01

2 makc.
Да нет, для работы с файлом хорошее решение класс File с описаны выше интерфейсом. Я не понял, как ты из моей логики вывел какуюто бредятину. Можеш логическую цепочку продемонстрировать?

Dan задвигает проблемы, какие каждому кажутся важными на этапе обучения, а с опытом кажутся тривиальными.

В двух словах
1. всегда существует высший уровень абстракции.
2. уровень абстракции повышается столько сколько нужно, но никогда больше.


Mokus - 30 Июль 2008 12:14

Mokus++

iv - 30 Июль 2008 12:43

В том-то и дело, что проблему кажутся тривиальными.
На самом деле проблема коренная. Причём касается не только AS и вообще не только программирования.
Проблема заключается в зависимостях.
Объединяя повторяющийся код в функцию, создавая утилитарный класс, создавая движок или фреймворк и затем используя всё это мы создаём зависимости.
Один кусок кода завязан на другой.

Изменяя один кусок кода, мы можем повлиять (осознанно или по недосмотру) на зависимый кусок кода. Иногда это именно то, что там надо. А иногда это наоборот приводит к появлению багов, которых раньше не было.

Попробую проиллюстрировать это на примере графики (не смотря на риск, что меня опять посчитают начинающим флешером :)).

Есть некая графика. Мы можем объединить в группу, а можем - в библиотечный символ.
Если сделаем сто копий графики, то в одном случае получим 100 независимых групп, а в другом случае 100 инстансов одного и того же символа.

Редактирую одну группу, мы меняем только её. Редактируя один инстанс, мы меняем их все.
Соответственно, если нам нужно сделать абсолютно одинаковые изменения во всех 100 копиях, то вариант с символом более предпочтительный. Но если нам нужно поменять только одну копию, никак не повлияв на другие, то тут простые группы больше подходят.

Аналогично и с функциями, утилитарными классами и прочим.
Есть класс, используется в сотне мест. Если нужно исправить багу или добавиьт новую фичу, требуемую во всей сотне мест - нам достаточно просто внести изменения в классе, это будет иметь эффект на весь проект в целом (что нам и надо).

Если же необходимо сделать хирургически точную правку, которая повлияет только на один конкретный случай использования класса и никак не повлияет на все другие места, где данный класс используется, то тут придётся хорошенько подумать, навставлять проверок.
А потом тестировать, тестировать и ещё раз тестировать, чтобы убедиться, что вместе с изменениями мы не внесли новые баги туда, где их раньше не было.

Ещё раз говорю: завязки. Иногда они полезны, иногда наоборот вредны.

Копи-паст не создаёт завязок: каждая копия кода является самостоятельным куском, который можно редактировать независимо от остальных.

Объединение часто используемого кода в нечто реюзабельное, будь то функция, класс или библиотека, создаёт завязки и здесь уже надо внимательнее относится к любым изменениям.

Dan - 30 Июль 2008 15:54

Ну и в целом по поводу обсуждения.
Мне вовсе не хочется обсуждать какие-то мои конкретные задачи и какой-то мой конкретный код.
У вас всё равно недостаточно информации, чтобы посоветовать решение, а у меня нет полномочий предоставить больше информации.

Я хотел обсудить проблему в целом.

Как писать чистый код и как почистить код испачканный, какие средства ухода за кодом нам известны и как их применять, кто какие гайдлайны по форматированию кода знает и как их правильно использовать, и почему вообще важен вопрос чистоты кода — вот что хотелось бы обсудить всем вместе.

Если вам есть, чем поделиться — предлагайте тему, или скажите, о чем хочется услышать.

Вот я и предложил тему: "копи-паст vs структурирование".

Dan - 30 Июль 2008 16:13

Mokus, а тут цепочки нет, прямое умозаключение. Если есть готовность абстрагировать даже если это приводит к ненужному без абстрагирования коду, то где тормоза?

Твой пункт 2 мне напомнил историю из 5го класса, когда на уроке черчения учитель спросил, сколько нужно проекций. Когда все числа из первой 20ки были перебраны, он огласил правильный ответ: ровно столько, сколько нужно. Такое правило означает, что решение в каждом конкретном случае может быть принято произвольно, иными словами есть лишь видимость правила.

- 31 Июль 2008 18:14

мдя, забыл подписаться.

в качестве оправдания второго поста, вопрос мокусу, сколько ненужных дополнительных проверок допустимо повлечь за собой выделению некоего куска кода в функцию?

makc - 31 Июль 2008 18:19

2 makc
Ответ: 0.
Попробую обяснить еще раз.
Если единственная альтернатива копипасту, которую ты видиш - вынесение в функцию - это ТВОЯ проблема. Если устранение дублирования кода обязательно тянет у тебя за собой ЛИШНИЕ проверки в функциях - ты пишеш говнокод и это ТВОЯ проблема.
Выше был конкрентный пример, который Dan"у казался проблемным изза того, что это тянуло лишние проверки в функции get size(). Я предложил свой вариант, где НИ ОДНОЙ лишней проверки, кода в результате будет меньше чем при копипасте (даже если копипастим всего раз), а результат тотже. Чем он те не понравился?

Mokus - 31 Июль 2008 23:08

если мне не изменяет память, ты нарисовал там функцию "nsureOpen()", которой у Dan-а не было... хотя... с такой формой ответа спорить бесполезно. ты прав, там чисто 0, и тема закрыта.

makc - 31 Июль 2008 23:35

Если единственная альтернатива копипасту, которую ты видиш - вынесение в функцию - это ТВОЯ проблема.

В старину дома строили без единого гвоздя, теперь будем классы писать без единой функции :)

package {
   public class AlternativeSolution {
      {
         // we don't need no flippin' functions! classes are the keys to success!
         // let's code right here
      }
  }
}

Хотя и классы тоже не нужны - можно ведь и прямо в пекедже код писать.

Ага! Есть же ещё паттерн Command. Позволяет избавиться от такого устаревшего нубского понятия как функция, и заменить его современным и красивым понятием - команда. Соответственно, блоки кода тоже не нужны - их можно заменить очередью команд. Только ни в коем случае не массивом! Массивы - это опять же нубское понятие. Очередь - более высокоуровневый тип данных. А чтобы красиво бегать по очереди, используем паттерн Iterator.
Ну и чтобы совсем было хорошо, экземпляры самих команд будем создавать абстракной фабрикой, чтобы поставиьт жирную точку в деле борьбы с копи-пастом.

А теперь чуть-чуть серьёзнее.

Вот вам ещё один примерчик, до чего доводят абстракции...
Класс ExternalInterface. Замечательное изобретение! Мы передаём ему данные, относящиеся к стандартным типам, а он их сам сериализует, потом получает ответ и десериализует, переводя обратно в привычные нам типы!
Лепота! Высоченный уровень абстракции, позволяющий нам не смотреть вниз и не видеть всей этой хитрой механики!

До тех пор, пока однажды не захочется передать, скажем, ByteArray.
Вот тут нас ждёт разочарование. Если всё-таки посмотреть вниз, сквозь плотные слои абстракций, то можно обнаружить, что ExternalInterface использует простую методику для отделения мух от котлет, точнее массивов от объектов. Если есть свойство length - значит массив, если нету - значит рядовой объект.
ByteArray эту нехитрую проверку на вшивость легко проходит. А вот следующую проверку (уже на прочность) - coerce в простой Array - пройти не может.

Нам бы какую-нибудь лазеечку на тот нижний уровень, чтобы объяснить глупому ExternalInterface как следует обращаться с такими массивами-полукровками. Но увы - абстрагировали нас по полной программе. И единственный выход - соорудить поверх этой абстракции ещё одну абстракцию, которая будет конвертировать ByteArray в строку (например с помощью Base64) и так строкой и передавать. Ну и разумеется на этом нашем новом супер-высоком (а значит клёвом!) уровне абстракций надо как-то отличать просто строки от строк, содержащих бинарные данные. Поэтому мы завернём не просто в строку, а в объектик, который будет содержать и строчку, и бирочку: "Острожно, Base64! Перед употребление декодировать, но не взбалтывать". Ну и, разумеется, добрый ExternalInterface нам этот объектик сериализует (то есть просто допишет по бокам теги, увеличив и без того раздутый размер и скушав немало времени на перетаскивание байтиков с места на место), независимо от того, хотим мы этого или нет.

Но не всё так плохо.
Когда мы будем наслаивать очередной уровень абстрации над ExternalInterface'ом, мы воспользуемся паттерном Singleton! Это перевесит все недостатки и успокоит наши душевные муки, ибо если в коде используются паттерны, да ещё и к месту (а кто скажет, что Singleton тут не к месту?), то код уже никак нельзя говнокодом - пусть тормозит, зато всё как в книжке.

Dan - 1 Август 2008 2:41

Вот вам ещё один примерчик, до чего доводят абстракции...

гг. супер пример. это примерчик не до чего доводят абстракции, а до чего доводит отсутствие опыта/знаний.
Глянь ЛЮБОЙ опенсорс сериализатор - например xstream из мира java, или стандартный хмл сериализатор из .нет. ЛЮБОЙ такой солюшен екстендится. ВЕЗДЕ можно добавить кастомную де/сериализацию для своего типа. такчто проблема тут какраз в тупо хардкоде - отсутствии абстракции.

поэтому вывод:
1. Если тебе не хватает опыта, ума или еще чегото, то на архитектуру, паттерны, АОП, ЛОП итд ты будеш смотреть как на ненужные слишком высокоуровневые вещи.
2. Если у тебя есть опыт и ты пишеш хорошо и большые проекты в твоей команде не тормозят, не лагают и нормально развиваются/поддерживаются - ты УЖЕ это все используеш, даже если про это не знаеш.

Mokus - 1 Август 2008 9:08

Массивы - это опять же нубское понятие. Очередь - более высокоуровневый тип данных.

Это кстати ты какуюто несуразную хну сказал. Очередь никогда не была "более высокоуровневой".
Это разные типы, используются в разных ситуациях. Ты б еще Dictionary и Sprite сравнил...

Mokus - 1 Август 2008 9:10

А чтобы красиво бегать по очереди, используем паттерн Iterator.

Итератором по очереди пробежатся невозможно.
Такчто просьба - не пиши слова, которые не понимаеш. ок?

Mokus - 1 Август 2008 9:15

UPD: не возможно, не почистив очередь (чтоб еще про очередь холиваров не разводить).
короч. я в эту тему больше не пишу - если хочеш - мой скайп b-mokus. давай примеры и по каждому конкретно я тебе в скайп отвечу как там устраняется копипаст без вазелина.

Mokus - 1 Август 2008 9:38

Да, холивар, однако...

Но все-таки я сторонник разнообразия. На мой взгляд, все можно, но не все удобно представлять объектами. Вряд ли нужен copy-paste, это нехорошо, но и объектные паттерны применимы не везде, хотя для чисто объектных языков типа Java, это, вероятно, оптимальный вариант.

Говорю, как человек, который сдавал RUP и проектирование в Rational Rose, а также юзал Пролог и Лисп.
Если кто-то (обладающий опытом программирования на Прологе) со мной не согласен, можно подискутировать, лучше по e-mail.

Janvarev - 1 Август 2008 20:28

Вообще, одна меняющаяся время от времени строчка - не такой уж повод для функции.
И к тому же если есть что-то общее, но в тоже время что-то нада менять, по моему опыту - это намек на то, что можно и стоит обдумать и переделать :)

А на тему оптимизация vs. красивый код - это решается по критериям:
Пишешь в команде/один;
Если один то: фанат оптимизации/красивого кода;
Пишешь закрытую/открытую библиотеку;
Пиздец как мало/много ресурсов, ну и тд.

kononencheg - 2 Август 2008 1:42

Caps Lock - зло
Не переключённая во время расскладка - зло
Всплывающее окно, перехватывающее на себя фокус, когда только разогнался писать тонну кода - зло
Имена классов с маленькой буквы - зло
Отсутствие "this" - зло
А ещё лично я считаю, что
выделение отдельной строки под фигурные скобки:

function ...():void
{
if(...)
{

и пробелы по каждому случаю:

function someFunc(a : String , b : Number , c : Boolean) : void {

тоже зло

А копипаст - послушный зверь в хороших руках.

a_[w] - 3 Август 2008 1:49

двое предыдущих выступавших практически поставили точку в дискуссии. :)
Вывод такой, что нет идеального решения.
Даже в программировании.
Даже во FLASH

unodj - 3 Август 2008 21:54

unodj: Тема дискуссии не оптимальные алгоритмы, а то, как они оформлены.

a_[w]: Огромную роль в оформлении кода играют инструменты, с помощью которых этот код пишется.
К примеру, в FDT не существует проблемы отдельной строки под фигурные скобки или лишних пробелов, поскольку имеется волшебная комбинация клавиш, которая приводит код именно в тот вид, к которому ты привык. И, уж если сам редактор не в состоянии что-то сделать автоматически, то должен максимально облегчить процедуру приведения страшного кода в порядок.
К сожалению, инструменты для AS пока не так развиты как для языков постарше, но прогресс имеется и это радует.

Я до сих пор поражаюсь тому, что многие недооценивают важность правильного оформления кода и инструментов для его написания.
Время от времени меня выдергивают на помощь в решении проблем, так вот: в большинстве случаев людям достаточно установить FDT и попросить исправить ошибки, которые он обнаруживает. Затем попросить заменить все однобуквенные переменные на значимые слова и убрать сокращения в коде.
Следующий шаг - избавиться от методов, содержащих несвязанную логику, просто вынося связанные куски кода в отдельные методы. Затем аналогично поступить с классами. И в конце сделать AS доки.
После этого людям, как правило, ничего не нужно подсказывать - логические ошибки обнаруживаются невооруженным взглядом.

Вот и давайте делать выводы каким должен быть код.
Имеет ли значение как написано myMc или my_mc? Ни малейшего. Куда важнее то, что это имя ни о чем нам не говорит и стоило бы написать windowHeader (если это заголовок окна, разумеется).
Но, конечно, не WindowHeader, чтобы не конфликтовать с именем класса, если впоследствии этому мувиклипу потребуется навесить класс. Кстати, считаю хорошей практикой именовать экземпляры классов по имени класса, но с маленькой буквы, как в данном примере. А, если вдруг мне захочется по-старинке собрать окно руками во Flash IDE, то и назову этот мувик по старинке: window_header_mc, а в классе достучусь до него через квадратные скобки:
private static const WINDOW_HEADER:String = "window_header_mc";
....
windowHeader = this[WINDOW_HEADER];

По идее, в сухом остатке темы для обсуждений и разногласий не должно остаться: все логически взаимосвязано и взаимозависимо и имеет свое четкое и понятное объяснение почему так, а не так.
А рутинную часть работы типа расстановки пробелов и т.п. должна взять на себя среда разработки.

iv - 4 Август 2008 1:00

а в классе достучусь до него через квадратные скобки:
private static const WINDOW_HEADER:String = "window_header_mc";
....
windowHeader = this[WINDOW_HEADER];

Хммм... А если отключить опцию Automatically declare stage instances и описать так:

public var windowsHeader:Sprite;

Ну или так:

public var window_header_mc:Sprite;

Dan - 4 Август 2008 1:23

Dan: можно и так. Так даже лучше. Но я не знаю где отключить опцию Automatically declare stage instances :)

iv - 7 Август 2008 10:54

Publish Settings - Flash - Settings (для AS 3.0)

Если опция включена (а по умолчанию она всегда включена), то в классе ни в коем разе нельзя описывать свойства с теми же именами, что и у объектов помещённых на сцену в Flash IDE.
Т.е. если у нас есть мувик windowHeader, то выглядеть будет примерно так:

class Window {

   public function Window() {
      windowHeader.alpha = 50;
   }
}

Разумеется, FDT начнёт ругаться, что windowHeader не объявлен. Однако любая попытка добавить поле с именем windowHeader приведёт к исключению при запуске флешки (что-то типа "не могу создать поле, потому что оно уже есть").

Если же опцию Automatically declare stage instances отрубить, то сразу можно уже писать так:

class Window {
public var windowHeader:Sprite;

   public function Window() {
      windowHeader.alpha = 50;
   }
}

И FDT, и Flash Player будут довольны.

Однако тут тоже есть свои грабельки (как же во флеше без них?)
Подобные поля обязательно должны быть public.
Если описать windowHeader как private, то опять получим исключение при запуске (опять же что-то там про невозможность добавить поле).

Dan - 9 Август 2008 0:00

Вай-вай-вай. Конечно же:
class Window extends Sprite

Извиняюсь, торопился.

Dan - 9 Август 2008 0:04

Однако тут тоже есть свои грабельки (как же во флеше без них?)
Подобные поля обязательно должны быть public.

Да, так и есть. Но это - единственные грабельки, которые я нашел в таковом решении. Недавно сам открыл попробовал отключение автодекларации переменных - мегавещь.

Рост - 9 Август 2008 0:04

Афтор,
у тебя фид не работает.
Или это мой ридер таращит?

Alenka - 15 Август 2008 15:00

Провокационный пост. Поэтому такие и комментсы :)

Виконт - 26 Август 2008 4:07

Кстати,c радостью поздравляю всех-всех-всех подписчиков блога с первым сентября. (Автора наверное не стоит поздравлять, так как у Вас я думаю все первые сентября уже в прошлом ;)) Вчера забыла поздравить, не до этого было. Сейчас вот только отошла немного :)

Оксана - 2 Сентябрь 2008 22:20



Подписаться на новости (RSS)




Примечания:
Статус документа
: в процессе
   2002-2009 Производство: Ростислав Сирык · О проекте · Подписка на новости (RSS)