Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Каких возможностей не хватает в PHP?


Автор: lukas 7.3.2011, 21:31
Приветствую всех.

Меня волнует один вопрос, как видно из названия. Дело в том, что я занимаюсь разработкой интерпретатора php-подобного языка. Я сам программирую на пхп уже более 2х лет и сейчас (правда не так часто). Язык мне полюбился своей гибкостью, конечно он не идеален. В нем не хватает множества вещей, в нем есть множество логических нестыковок.

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

И так, начнем.

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

Код

const {
    MY_X = 10;
    MY_Y = 20;
    MY_Z = 30;
}
// или для одной константы
const MY_X = 10;

// эквивалентна этому:
define('MY_X',10);
define('MY_Y',20);
define('MY_Z',30);


2. Глобальные переменные и видимость локальных. На мой взгляд в пхп непонятная система видимости переменных, совершенно запутанная, локальная переменная может оказаться глобальной, а может и нет. Также есть SuperGlobals, но нельзя добавлять своих. А как вам такая возможность:

Код

@var = 20; // глобальная переменная var
$local = 30; // локальная переменная local

global $var; // тоже объявляется глобальная переменная

// и тогда $_GET станет @_GET и т.д.

Конечно, теперь символ @ служит не для заглушки сообщений об ошибках, а для обращения к глобальным переменным. И к тому же, есть жесткое ограничение, если вы объявили переменную как $<...>, то она будет всегда локальной. 

3. Регистрозависимость отменяется для всего!, для переменных, констант и прочего, где она есть в php

Код

$Var = 20;
echo $vAr; // выведет 20


4. Теперь "::" и "->" это бинарные операторы, где слева класс или объект, а справа название метода/свойства и т.д. Чем это светит? Отменяются костыли вроде:

Код

$obj->{$prop} = 20;
// а так уже нельзя
$obj->{$prop.'_val'} = 20;


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

Код

$obj->($prop) = 20;
$obj->($prop . '_val') = 20;
$obj->(... любое выражение ..) = 20;

('Class' . 'Name')::('Met'.'od')( ... ); // вызов метода класса, некрасиво, я просто показал возможность



ООП.


5. Пользовательские свойства с сеттерами и геттерами. Замена костылям __get и __set. Во многих языках (где нормальная поддержка ООП) можно объявлять свойство, у которых есть get функция и set функция, первая возвращает значение свойства, а вторая задает значение свойства.
В орионе эти свойства объявляются так:

Код

class MyClass {
  
   protected $_prop;
   function propGet(){ return $this->_prop; }
   function propSet($val){ $this->_prop = $val; }

   public $prop(get propGet, set propSet);
}

$obj = new MyClass;
$obj->prop = 'Yes!';
echo $obj->prop; // выведет 'Yes!'


Пользовательское свойство может не иметь сеттера, тогда оно будет только для чтения и его нельзя будет изменять.

6. Перегрузка операторов для объектов. Для объектов можно перегружать операторы + - / * и т.п., вплоть до присваивания. Как вам? Сразу же представляются классы вроде Matrix, BigInteger или даже искусственный UnicodeString. Конструкцию обращения к объекту как к массиву [ ... ] можно также перегружать вплоть до set и get (как волшебные свойства __get и __set).

Код

class Matrix {

     function oper:plus($m){ return .. }
     function oper:minus($m){ return .. }
     function oper:mul($m){ return .. }
     function oper:div($m){ return .. }
     function oper:not($m){ return .. }
     // ... и так далее
     function oper:assign($m){ ... }
}  

$obj = new Object; // создаем объект, у которого определен метод oper:plus и oper:tovalue, oper:assign
$x    = $obj; // вызов метода oper:tovalue, $x будет равен результату, который вернет метод
$obj = 'abcd'; // вызов метода oper:assign($value), передается один параметр - что присваиваем.

$x = $obj + $obj; 
// что будет в этом случае:
/*
   у левого $obj будет вызван oper:plus метод, в который передается один параметр $value
   параметр $value в нашем случае будет уже правый $obj, но так как у него есть метод oper:tovalue,
   то произойдет вызов oper:tovalue и результат вызова передастся в oper:plus вместо $value.
*/

// это выглядит примерно так:
$x = $obj->oper:plus( $obj->oper:tovalue() );  



7. На закуску, короткое объявление массивов.
 Сколько раз я писал array, и сколько раз мне это надоедало, то там то тут. Почему в пхп нет возможности коротко объявить массив без этого пресловутого array. В орионе есть такая возможность:

Код

$arr = [1,2,3,4,5];
// все равно что
$arr = array(1,2,3,4,5);

//Или сложнее
$arr = ['x'=>[1,2], 'y'=>[2,3]];


Т.е. поддерживается любой уровень вложенности. В качестве десерта оператор IN вместо функции in_array и в результате получается красивая и понятная конструкция.

Код

if ($x in [1,2,3,4,5]){

}

//все равно что
if (in_array($x, array(1,2,3,4,5))){

}


И кстати конец кривому strpos(...)!==false, оператор in подходит и для строк:
Код

$x = 'cd';
if (!($x in 'ab cd xy z')){ // если $x подстрока не входит в ab cd xy z
   ...
}

//все равно что:
if(strpos('ab cd xy z', $x)!==false){
  ...
}



8. Рефлексия для классов и объектов через общий класс Object, все классы в Орионе неявно унаследованы от класса Object, который имеет методы для рефлексии класса и объекта, что не влияет даже на производительность ООП. Т.е. вы из любого класса или объекта сможете узнать - какие методы у него есть, константы и т.д.



9. Динамически изменяемые методы для классов. 
В орионе такое возможно. И очень просто. Как это делается? Очень просто, объявляется статическое свойство класса, и этому свойству присваивается анонимная функция. Хочу заметить, что в отличии от php 5.3, в такой метод будет прекрасно передан $this и self, parent. 

Код

class Ura {
   static $method;
}

Ura::$method = function(){ echo 'test' }
Ura::method(); // выведет 'test'
// кстати можно писать без $, он оставлен для поддержки совместимости с пхп
Ura::method = function(){ echo 'Ky' }
Ura::method(); // выведет 'Ky';


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



P.S. Все возможности, которые я перечислил уже поддерживаются Орионом на 90%. Движок ориона это компилятор в байт-код и виртуальная машина, это не интерпретатор. Очень хочется почитать мнения людей, которые программируют на пхп профессионально. Также хочу отметить, что это не форк официального php, это разработка с нуля, ссылка доступна в моей подписи.

Автор: SneG0K 7.3.2011, 21:57
1, 6, 7, 8
9 - это альфа-функции

Остальное лишее.
Регистрозависимость лучше не отменять.

Автор: lukas 7.3.2011, 22:02
Цитата(SneG0K @  7.3.2011,  21:57 Найти цитируемый пост)
1, 6, 7, 8
9 - это альфа-функции

Остальное лишее.
Регистрозависимость лучше не отменять.


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


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


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

Автор: Muerto 7.3.2011, 22:25
3. Регистрозависимость отменяется для всего не стоит, плюсов в этом не вижу

Автор: solenko 7.3.2011, 22:30
Похоже, вы пишете Ruby )

Автор: lukas 7.3.2011, 22:43
Цитата(solenko @  7.3.2011,  22:30 Найти цитируемый пост)
Похоже, вы пишете Ruby ) 


Похоже ruby использовал те парадигмы, которые уже давно придуманы и есть в других более старших языках и вы наверно плохо знакомы с ruby. Ну я раби так иногда посматриваю, и питон, и луа и многие редкие языки. Тем более в раби и питоне все является объектами, а операторы это в неявном виде методы.


Цитата(Muerto @  7.3.2011,  22:25 Найти цитируемый пост)
3. Регистрозависимость отменяется для всего не стоит, плюсов в этом не вижу 


Я не вижу плюсов в регистрозависимости. Программист не должен отвлекаться на регистр букв, он должен держать в голове более полезную информацию.

Автор: SneG0K 7.3.2011, 22:46
Регистрозависимость - это очень удобная штука, позволяет использовать удобные правила написания кода.
Терпеть не могу паскале-подобный синтаксис только из-за отсутствия регистрозависимости.

Так я не понял, ваш Орион наследует С-подобный синтаксис или где?

Автор: lukas 7.3.2011, 22:53
Цитата(SneG0K @  7.3.2011,  22:46 Найти цитируемый пост)
Регистрозависимость - это очень удобная штука, позволяет использовать удобные правила написания кода.
Терпеть не могу паскале-подобный синтаксис только из-за отсутствия регистрозависимости.


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

Ну то что регистрозависимость помогает контролировать общий стиль, оно понятно, кто ж вам без него не позволяет соблюдать этот стиль. Тут есть как огромные плюсы, так и минусы. Я например не люблю регистрозависимость, потому-что когда левый разработчик пишет библиотеку, ты должен в добавок еще запомнить регистр названий классов и функций, а каждый разработчик либы использует свой стиль. В итоге бардак и неудобство, отсюда унылые именования функций, вроде my_func_name_this_call, чтобы уж точно никто не ошибался.


P.S. Хотел бы добавить, что php 5.2 не способен уничтожать циклические ссылки, в php 5.3 добавили сборщик мусора для циклических ссылок, но вроде он не включен по-умолчанию, а также он может влиять на производительность.
Вот скрипт, который приводит к колоссальной утечке памяти в php 5.2

Код

class Y {
    var $val;
}

class X {
   var $val;
}

$mem = memory_get_usage();

while($i++ < 100000){
   $y = new Y;
   $d = new X;
   $d->val = $y;
   $y->val = $d;
}

echo memory_get_usage() - $mem;


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

Автор: SneG0K 7.3.2011, 23:06
Для кого ориентирван твой язык? Умеет ли он работать в перемешку с html например?
Сколько памяти жрет?
Пробовал его сравнивать с PHP по производительности?
Сделай его совместимым с PHP, но + твои новые фичи.
Кстати, как обстоят дела с ООП? Неймспейсы?

Автор: lukas 8.3.2011, 06:41
Цитата(SneG0K @  7.3.2011,  23:06 Найти цитируемый пост)
Для кого ориентирван твой язык? Умеет ли он работать в перемешку с html например?
Сколько памяти жрет?
Пробовал его сравнивать с PHP по производительности?
Сделай его совместимым с PHP, но + твои новые фичи.
Кстати, как обстоят дела с ООП? Неймспейсы?


Язык изначально создается для десктоп приложений и как скриптовой движок в играх. По производительности не могу дотянуть до скорости работы массивов в пхп. Операторы, там + - * и т.п. работают немного медленнее, но например вызов функций работает на 40% быстрее, и вызов нативных функций тоже быстрее. Вот тесты: http://code.google.com/p/orionphp/wiki/Orion_Speed_Test и вот http://code.google.com/p/orionphp/source/browse/#svn%2Ftrunk%2Fdemos%2FSpeedTests

Жрет памяти столько же как пхп, ну на начальном запуске он жрет только 1 мб памяти, но например большой массив на 1 млн элементов жрет примерно столько же памяти, что и в пхп.

ООП поддерживается - наследование, все что я описал выше, protected, private, public, static поддерживается в полной мере, а также конструкторы, деструкторы, некоторые волшебные методы __get, __set. Namespace полноценных нет, ну т.е. есть, просто не до конца сделанные:

Код

module Math {

   const PI = 3.1416;
   const E  = 2.7;
   
    function test($i){
   
        echo $i;
    }
    
    class URa {
        const MY_X = 20;
    }
}

echo Math:PI, Math:E;
Math:test('My string');
echo Math:URa::MY_X;


Не сделана для namespace'ов зона ограничения видимости.

На счет веба, там будет видно, все зависит от того на сколько удастся популяризировать движок, будут ли третьи разработчики писать расширения для языка. Кстати, официальная страница языка будет находится тут: http://orion-lang.org/. Я хотел написать модуль для апачи, но пока рано, язык еще тестится и разрабатывается. Кстати, можно глянуть на юнит-тесты и примерно прикинуть - на сколько язык готов: http://code.google.com/p/orionphp/source/browse/#svn%2Ftrunk%2Ftest

Есть еще отличия, echo и print и isset это функции нативные функции.

Автор: SamDark 9.3.2011, 00:47
1. Более-менее, хотя и с define более-менее.
2. Не нужно. С видимостью переменных всё и так нормально. Особенно в 5.3.
3. Плохое предложение.
4. Такое нужно крайне редко.
5. Нормально. Это есть в C# и в компонентах Yii.
6. Слишком магично. Путаницы будет много.
7. Хорошая штука.
Десерт про in_array как-то не очень.
8. Рефлексия вроде и сейчас поддерживается. Чем плоха?
9. Интересная возможность, похожая на mixin. Есть в Ruby, реализована для компонент Yii.

Вообще не ожидал, что кто-то подобным займётся…

Автор: lukas 9.3.2011, 10:12
Цитата(SamDark @  9.3.2011,  00:47 Найти цитируемый пост)
1. Более-менее, хотя и с define более-менее.


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


Цитата(SamDark @  9.3.2011,  00:47 Найти цитируемый пост)
2. Не нужно. С видимостью переменных всё и так нормально. Особенно в 5.3.


Сталкивался я со многими CMS у которых была явная путаница с глобальными переменными, иногда приходилось писать global $var, я понимаю когда модель MVC там этих проблем нет, отсутствует сама причина. 


Цитата(SamDark @  9.3.2011,  00:47 Найти цитируемый пост)
4. Такое нужно крайне редко.


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


Цитата(SamDark @  9.3.2011,  00:47 Найти цитируемый пост)
6. Слишком магично. Путаницы будет много.


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


Цитата(SamDark @  9.3.2011,  00:47 Найти цитируемый пост)
8. Рефлексия вроде и сейчас поддерживается. Чем плоха?


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


Цитата(SamDark @  9.3.2011,  00:47 Найти цитируемый пост)
9. Интересная возможность, похожая на mixin. Есть в Ruby, реализована для компонент Yii.


Вообще она не задумывалась изначально, задумывалась абстрактная возможность изменения поведения класса во время выполнения, которые будут влиять на созданные объекты. Но так получилось, что движок стал универсальным и такая возможность появилась практически автоматически.

Автор: ksnk 9.3.2011, 10:42
Цитата(lukas @  7.3.2011,  21:31 Найти цитируемый пост)
const 
    MY_X = 10,
    MY_Y = 20,
    MY_Z = 30;

// или для одной константы
const MY_X = 10;

а чем не нравится С-шное объявление констант? Через запятую. 
Вообще - нужно приблизится по синтаксису к какому-нибудь языку- С, Java? но желательно только одному и не мастерить своих примочек. Дело в том, что язык нужен не только разработчику, а новый писатель на этом языке вероятнее всего будет иметь опыт программирования на Java или С

Автор: lukas 9.3.2011, 10:59
Код

const 
    MY_X = 10,
    MY_Y = 20,
    MY_Z = 30;


Так сделать не проблема.
Код

const MY_X = 10, MY_Y = 20, MY_Z =30;


Одно и тоже. Ну вообще очень спорный вопрос, т.к. константы внутри класса можно объявлять и так:
Код

class My {

     const { 
        private MY_X = 10;
        public MY_Y = 20;
        protected MY_Z = 30;
     }
}

// или
class My {

     private const { 
        MY_X = 10;
        MY_Y = 20;
        MY_Z = 30;
     }
}

В этих случаях как то понятнее со скобками, дальше можно продолжать:

Код

class My {

    public {

            function ...
            function ...
    }
}


Скобки используются и для объявления модулей, я написал выше этот код. Все таки во многих местах используются скобки. 

Автор: ksnk 9.3.2011, 11:39
lukas, скобки "интуитивно" очерчивают область видимости. Или описывают структуры данных. Описывать "внешние" констаны внутри скобок - непривычно, а значит неправильно.

Тут нужно думать о людях, которые придут писать на этом языке. Будет ли он им интуитивно понятен?
Достаточно написать пару алгоритмов на новом языке и показать любому другому человеку с опытом программироания, чтобы понять какие куски будут непонятны.
В принципе - любой язык (за исключением форта, перла местами и лиспа с наследниками  smile ) интуитивно понятен (на уровне - читаю, пишу со словарем) любому, имеющему паскальное-сишное программистское образование. Язык, который базируется на синтаксисе PHP должен обладать этим свойством. 

Цитата(lukas @  7.3.2011,  21:31 Найти цитируемый пост)
если вы объявили переменную как $<...>, то она будет всегда локальной.

Это-ж почти Бейсик  smile. У него тоже тип переменной определяется по первой букве идентификатора.
Глобальные переменные - это не зло и не добро. Это просто веревка, которой связываются кусочки кода, и на которой некоторые деятели умудряются повесится. Нужно эту веревку сделать покороче, как в обычных языках программирования, чтобы вешаться было сложнее, а работать это мешало бы не очень сильно. Так что надо не упрощать определение глобальных переменных, а наоборот - ограничить их.


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

Автор: lukas 9.3.2011, 11:54
Цитата(ksnk @  9.3.2011,  11:39 Найти цитируемый пост)
Это-ж почти Бейсик  smile. У него тоже тип переменной определяется по первой букве идентификатора.


Ну мне казалось это из перла, я слышал когда-то в бейсике по названию переменной определялся ее тип  smile 
В ruby например @ это переменные объекта, если я не ошибаюсь. 

Есть идея сделать глобальные переменные вообще без первого символа, так:

Код

GLOBAL_VAR = 20; // глобальная переменная


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

Автор: Ant0ha 9.3.2011, 12:25
Простите, что не совсем в тему. Но зачем вы тратите бесценное время на создание нового языка? Неужели вы считаете, что он сможет конкурировать с тем же php? Хобби?

Добавлено через 14 минут и 25 секунд
То, чего сейчас в php не хватает, скорее всего, добавят позже. Имхо, это же проще, чем всё с нуля переделывать...
Да, и если даже этого и не добавят, я сомневаюсь, что кто-то из-за таких мелочей бросит php...

Автор: lukas 9.3.2011, 13:02
Цитата(Ant0ha @  9.3.2011,  12:25 Найти цитируемый пост)
о, чего сейчас в php не хватает, скорее всего, добавят позже. Имхо, это же проще, чем всё с нуля переделывать...
Да, и если даже этого и не добавят, я сомневаюсь, что кто-то из-за таких мелочей бросит php... 


Я видел исходники пхп, любые структурные изменения в них могут обернуться настоящим fail'ом. Они настолько убоги по мне, что их стоило бы переписать с нуля. А они это уже делали. Я просто сравниваю с lua и angel script исходниками.

Да отчасти это мое хобби. ПХП не бросят, но с удовольствием будут использовать его в других областях, кроме веб-а (game scripting, десктоп приложения). Я же еще планирую сделать специальное расширение GUI для языка, и интеграцию с 2D движком http://code.google.com/p/zengl/ (для инди игр). (все кроссплатформенное).

Автор: lukas 22.4.2011, 13:47
Прошу прощения, но появилась интересная идея. Такого я не видел ни в одном языке.

Язык Орион (аналог PHP).

Во многих языках есть возможность указать тип передаваемого параметра в функцию. В php и орионе такая возможность тоже имеется.

Код

// $x - должен быть типа int
function test(int $x){
}


Также можно в качестве типа указывать класс объекта.
Код

// $x - должен быть объектом типа TMatrix
function test(TMatrix $x){
}



В орионе можно будет указывать обобщенные типы для скалярных значений, например:

number - можно передавать только int или double значение
scalar - можно передавать только скалярные значения, int, double, bool, string, null
mixed - можно передавать все, кроме объектов


Автоматическое приведение к типу аргументов функции

На данный момент, я не знаю, придумал ли я что-то новое или такая возможность имеется в каких-то других языках. Я не знаю ни один язык, где есть похожая возможность.

Все понимают, что приведение к типу это рутинная операция, повторяющаеся постоянно. Но это позволяет вылавливать многие ошибки до выполнения. Язык Orion, как и пхп динамический, в котором отсутствует типизация. НО! То что отсутствует типизация, еще не означает что в языке отсутствуют инструменты контроля типов.

Итак, перейдем к теме:
В Орионе вы можете указать к какому типу приводить передаваемое значение в функцию. Т.е. интерпретатор за вас будет приводить переданное значение к нужному типу. Сейчас все поймете:

Код

function test(->int $x){
    // $x будет всегда типа int
}

test("20"); // "20" - строка, которая будет приведена для функции test к типу int


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

Код

class TPoint {
  
    public $x;
    public $y;
   
    function oper:typed($val){
       if ( is_array($val) ){
         $this->x = $val[0];
         $this->y = $val[1];
      } else
        return false;   
    }
}

function MoveTo(->TPoint $point){
    // goto $point... работаем с объектом $point
}

// самое вкусное...
// где-то в коде
MoveTo(array(100,200)); 


Как мы видим, в функцию MoveTo в конце был передан массив, а функция требует объект класса TPoint. Не беда, мы указали, что нужно привести аргумент $point к объекту класса TPoint автоматически. Т.е. мы передали массив, далее будет создан объект TPoint (т.е. мы передали не того типа), у нового объекта будет вызван метод ->oper:typed( $point ), в котором мы инициализируем объект, где $point аргумент функции, т.е. массив array(200,300). 

В итоге, в функцию будет все равно передан объект TPoint, даже если мы передадим массив, массив преобразуется в объект TPoint. А если мы передадим не массив, тогда произойдет фатальная ошибка, т.к. в методе ->oper:typed() мы намеренно поставили условие, что только массив можно конвертировать в TPoint, в остальных условиях возвращать false.



Заключение.

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)