Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Организация кода в публичной библиотеке (https://javascript.ru/forum/misc/43311-organizaciya-koda-v-publichnojj-biblioteke.html)

Antonius 30.11.2013 23:30

Организация кода в публичной библиотеке
 
Здравствуйте.

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

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

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

Вариант первый — классическое прототипное наследование в чистом виде. Создаю конструктор, присваиваю прототипу объект с методами. Либо каждый метод в отдельности — Constructor.prototype.method = function() { ... }, чтобы не затереть уже имеющиеся поля, вроде conctructor. «Приватные» методы обозначаются символом в имени, по сути оставаясь публичными.

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

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

По результатам моих измерений прототипное наслделование дает прирост в производительности, в зависимости от браузера, либо незначительный (4—5%), либо ощутимый (10—20% и больше).

К недостаткам прототипного наследования могу отнести видимость приватных методов извне («захламление») и необходимость использовать new с конструктором (или определить функцию-обертку для этого).

При создании замыканий получаем в некоторых условиях более медленный код, однако более «чистый» объект на выходе, без видимых приватных методов, и более простой в использовании (не требуется new или обертка).

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

Спасибо.

Maxmaxmaximus3 01.12.2013 12:41

Цитата:

Сообщение от Antonius
К недостаткам прототипного наследования могу отнести видимость приватных методов извне

В чем недостаток? Рсскажи подробнее? Что мешает создать для них неймспейс префикс или постфикс например "_" ?

kobezzza 01.12.2013 13:03

Частая ошибка новичков изучающих ООП: модификаторы видимости private и protected созданы ИСКЛЮЧИТЕЛЬНО для увеличения уровня абстракции и банальной удобности, а не для "сокрытия от злых хакеров".

Я использую классическое соглашение:
_ private
__ protected

и всем советую

danik.js 01.12.2013 14:01

Помоему такого рода "приватные методы" (ввиде локальных функций) не оставляют возможности наследоваться от класса и перекрывать методы.

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

Кстати, никто не встречал использование вместо знака «_» знак «$» для приватных свойств/методов?

kobezzza 01.12.2013 14:06

Цитата:

Сообщение от danik.js (Сообщение 283765)
Помоему такого рода "приватные методы" (ввиде локальных функций) не оставляют возможности наследоваться от класса и перекрывать методы.

Ну приватные метода и не должны наследоваться, для этого есть протектед, хотя это конечно всё условности:) Прост по аналогии с Action Script 3 или C# и т.д.: модификатор "приватности" означает видимость в пределах класса, а модификатор "протектед" означает видимость также для его потомков.

Цитата:

Сообщение от danik.js (Сообщение 283765)
Кстати, никто не встречал использование вместо знака «_» знак «$» для приватных свойств/методов?

В ангуляре вроде так.

Maxmaxmaximus3 01.12.2013 14:55

Цитата:

Сообщение от danik.js
Помоему такого рода "приватные методы" (ввиде локальных функций) не оставляют возможности наследоваться от класса и перекрывать методы.

function Animal() {

  }

  Animal.prototype.say = function() {
    alert('i Animal')
  };



  Cat.prototype = Object.create(Animal.prototype); //наследуем
  function Cat() {

  }

  Cat.prototype.say = function() {
    this.constructor.prototype.say.call(this); //перекрытый метод
    alert('i Cat')
  };


  new Cat().say();



можно еще для простоты сделать так

Cat.prototype = Object.create(Animal.prototype); //наследуем
  Cat.prototype.parent = Cat.prototype;
  function Cat() {

  }

  Cat.prototype.say = function() {
    this.parent.say.call(this); //перекрытый метод
    alert('i Cat')
  };



Цитата:

Сообщение от kobezzza
В ангуляре вроде так.

кстати раз уж я пытаюсь копировать их апи и названия методов, я на всякий скопировал и эту традицию, теперь бесит =)

Antonius 02.12.2013 01:51

Цитата:

Сообщение от Maxmaxmaximus3 (Сообщение 283756)
В чем недостаток? Рсскажи подробнее? Что мешает создать для них неймспейс префикс или постфикс например "_" ?

Разумеется, если остановлюсь на этом варианте, то так и будет сделано.

Цитата:

Сообщение от kobezzza (Сообщение 283758)
Частая ошибка новичков изучающих ООП: модификаторы видимости private и protected созданы ИСКЛЮЧИТЕЛЬНО для увеличения уровня абстракции и банальной удобности, а не для "сокрытия от злых хакеров".

Я использую классическое соглашение:
_ private
__ protected

и всем советую

Это очевидно же. Дело в другом. Если есть причины сделать метод приватным, то это же не просто так. Например, у него может в будущем поменяться набор или формат параметров или тип/формат возвращаемого значения, он может быть переименован или удален. Да и просто он может выполнять сугубо служебные функции, и «не надо хотеть» использовать его извне. Публично доступен стабильный (хочется надеяться) API,

Но для выбора в моем случае это всего лишь один из «недостатков». Также смущает необходимость использования new. В подобного рода скриптах, рассчитанных на массовое использование, мне подобное требование не встречалась (неопытность? такие библиотеки, скрипты существуют?)

Цитата:

Сообщение от danik.js (Сообщение 283765)
Помоему такого рода "приватные методы" (ввиде локальных функций) не оставляют возможности наследоваться от класса и перекрывать методы.

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

Кстати, никто не встречал использование вместо знака «_» знак «$» для приватных свойств/методов?

Наследоваться и перекрывать методы (публичные, разумеется), можно при использовании «паразитного», «фабричного» наследования, разве нет? А менять служебные приватные методы как минимум опасно — на их основе работает остальной код, для чего может потребоваться их изменение (а не доопределение новых)? Ко всем данным (приватным свойствам), которые имеют смысл за пределами объекта, должен быть обеспечен доступ средствами открытого API, не так ли? Что заодно позволит выполнять валидацию и коррекцию ошибочных данных (если это возможно) при доступе к ним. В моем случае геттеры-сеттеры я применять не планирую — поддержка у них для этой задачи неудовлетворительная пока что.

Да, и еще вопрос вдогонку. Те, кто использует классическое прототипное наследование, в каком формате вы присваиваете значение прототипу? Constructor.prototype = { … } или Constructor.prototype.field = …?

Maxmaxmaximus3 02.12.2013 02:10

Цитата:

Сообщение от Antonius
Это очевидно же. Дело в другом. Если есть причины сделать метод приватным, то это же не просто так. Например, у него может в будущем поменяться набор или формат параметров или тип/формат возвращаемого значения, он может быть переименован или удален. Да и просто он может выполнять сугубо служебные функции, и «не надо хотеть» использовать его извне.

ииииииииииии????

Цитата:

Сообщение от Antonius
Но для выбора в моем случае это всего лишь один из «недостатков».

В чем недостаток то?

Цитата:

Сообщение от Antonius
для чего может потребоваться их изменение

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

Цитата:

Сообщение от Antonius
Constructor.prototype.field

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

nerv_ 02.12.2013 02:21

Прототипы + соглашения + обертка для new. С другой стороны смотря для кого пишешь - можно и не оборачивать new. Тот, кто используют приватные методы извне - сам дурак :)

Antonius 02.12.2013 02:30

Цитата:

Сообщение от Maxmaxmaximus3 (Сообщение 283901)
ииииииииииии????

И если не надо хотеть его использовать извне — не надо давать возможность его использовать извне. Но дальше я уже понял, какие детали упускаю из виду.

Цитата:

Сообщение от Maxmaxmaximus3 (Сообщение 283901)
В чем недостаток то?

Потому и в кавычках. Не недостаток, просто некрасиво что-ли...

Цитата:

Сообщение от Maxmaxmaximus3 (Сообщение 283901)
Очевидно что когда говорится не поддерживается переопределение имеется ввиду нет удобного доступа к оригиналу из перекрытого. а зачем нужен доступ к оригиналу? потому что когда метод перекрывается, старый функционал сохраняется а новый нарасчивается. это к слову

Да, согласен.

Цитата:

Сообщение от Maxmaxmaximus3 (Сообщение 283901)
Потому что лучше сжимается мигификаторами =) при такой записи они могут вообще заинлайнить код функции то есть если его мало, то взять и подставить его в те места где метод вызывается.

Убедительно. И существующее не трогаем, и при минификации выигрываем. Спасибо.


Часовой пояс GMT +3, время: 10:49.