Софтуерно Инженерство
Loading...
+ Нов въпрос
kasskata avatar kasskata 492 Точки

[Useful Info] Class Creator and Propety Creator in JavaScript ?! WT*?

Здравейти, колеги.

Първо спрете да воутвате , искам да пишете благодарности и оплаквания и подобрения :) Така ми е самотно, сам да си отговарям :D

Има Updates/Patch на кода от този коментар малко по-надолу в темата, погледнете го задължително, има подобрения и чистене на грешки!

Отдавна не съм писал в форума, защото не се сещам нещо съществено и днес докато си говорех с колегата г-н Инков, се сетих че мога да споделя с вас, как си олесних живота за ООП JS.
Целта ми е да репрезентирам как си направих сам LiveTemplates, които ми създават САМИ клас и пропърти. Естествено, отворен съм за подобрения. Споделяйте, за да покажем на г-н Наков, че копи пейст не е най-добрата практика... :D

Warning:

Аз използвам PHPStorm, но като всички продукти на jetBrains работят идентично, може спокойно да си работите и на WebStorm и на InteliJ по същия начин. Който ползва VS с Resharper може да покаже неговия начин за създаване на темплейт, за да обогатим темата,но аз няма да го показвам,защото е съм го правил.

Ако трудно ми се разбира, ще направя и видео туториъл за да стане по-ясно.

Нека започваме...

I. Създаване на Class template:

1. Отваряме Storma

2. Създаваме файл с extension ".js". В Storma може да го направите int.maxValue различни начини, така че няма да обеснявам как, ВАЖНО е да спомена, че името на вашия файл ще се използва за наименоване на класа. Аз съм го кръстил "tomato.js", както е по конвенция с малка буква. След малко ще обясня за голямата буква на класа.

3. Отваряме Настройките, като това става най-лесно с комбинацията "Ctrl+Alt+S". В търсачката пишете "Live template" и ще ви излезне таб Live Template. (picture 1).

ctor

Намирате JavaScript expand таба отдясно (има лист със всички езици, които се поддържат). Цъкате да се покажат всички темплейти. Най-вдясно има знак Плюс(зеленото), цъкате и създавате нов "Live template".

4. Долу , в таба "Abriviation" напишете командата, чрез която ще извикате темплейта, в случая аз ползвам най-близкото, което се сетих "ctor".

5. До него има таб "Description", където пишете описание на вашия темплейт, аз съм написал "Create new Class and Inheritance", защото в кода(по-долу) има и закоментирано наследяване.

6. Копирайте този код в таб "Template text":

// Object.prototype.inherits = function inherits(parent) {
// this.prototype = Object.create(parent.prototype);
// this.prototype.constructor = this;
// }
var $CLASS$ = (function () {
function $CLASS$() {
// $BASE$.apply(this, arguments);
}
// $CLASS$.inherits($BASE$);
$CLASS$.prototype.toString = function () {
return this.constructor.name ;
}
return $CLASS$;
}());


7. Намерете бутона"edit variables". Там напишете това, което съм показал по горе в първата снимка. Именно "capitalize(fileNameWithoutExtension())" прави вашата променлива да взима името на вашия файл, да го прави с голяма буква ,както си е по конвенция в JS и да го ползва като име на класа ни, но не работи когато пишете всички класове в един файл .За да го оправите сменете полето с "jsClassName()", както съм показал на долната снимка. Ако не искате да не рефакторирате името, кликнете отметката вдясно от променливата, както е на снимката.

Много важно е да дадете какъв език искате да ползва този template.В нашия случай е Javascript,  намерете на симката където пише"Aplicable in JavaScript", при вас трябва да е "No аplicaple context yet." Цъкнете на "Define" и изберете езика.

Кликнете ОК. И още един път ОК за да стигнете до вашия файл и да пишете в него.

8. Ако всичко е наред, трябва след като напишете ключовата (дума + TAB) да изплюе кода, който ви дадох и да ви сложи курсора на липсващата думичка за "BASE" в случая за теста написах абстракния да е "Vegetable". На това място пишете името на абстрактния клас.

Забравих да спомена, че темплейта съдържа и функция "toString",която се държи както би трябвало: казва името на класа. От тук насетне само овъррайд  смело :)

9.Готово. Вече имате класа и той се попълва само с 1 параметър - Абстрактния клас, ако ще има такъв. Ако е "Vegetble" трябва да напишем това: "ctor+Tab, Vegetable+Enter" и имаме готов клас Домат наследяващ Зеленчук. То е по лесно и от .Net :D

II. Създаване на Property template:

Prop

 

1.Направете всичко, както го описах по горе за да стигнете отново до "Live template tab" и направете настройките на следващия темплейт, както описах нагоре. Използвайте картинката за олеснение, може направо от нея да преписвате. Попълнете всички полета, по препоръките от горния текст.

2. Поставете този код в "Template text" , не забравяйте да махнете (ако искате) "IMPORT TO THE CONSTRUCTOR!". Това е подсказка, че следващия ред ("this.set$ARG$($args$);")трябва да влезне като поле в конструктора на класа. Не е коментирано, за да ми хвърли грешка, за да не го забравям:

IMPORT TO THE CONSTRUCTOR!
this.set$ARG$($args$);
// Get $ARG$
$CLASS$.prototype.get$ARG$ = function(){
return this._$args$;
}
// Set $ARG$
$CLASS$.prototype.set$ARG$ = function($args$){
this._$ARG$ = $args$;
}

 

     3. Намерете бутона"edit variables". Там направете настойките както са на втората снимка. 

     4. Това е.  Ако домата ни има field grams, трябва да напишем "prop+Tab, Grams + Enter" премествате най-горния ред в конструктора и вече имаме подобно на .NET подготвено без валидация, и тя е почти готова след малко ще хвърля кода и за тях.

Ако се сетите някоя други "шмекерия" пишете, моля ви, защото не знам за вас, но аз не се чувствам подготвен за изпита.

Успех на изпита и на хората които гледат в бъдеще това... Успех и на вас :D

 

P.S. Току що завърших 3-тото домашно с тези класове криейтори всичко като време ми отне 30 минути да направя класовете с логиката им. Но от време на време не иска да хване правилното име и ме нервира, но в бързината и това е достатъчно. Много съм доволен. 

22
JavaScript Advanced 10/12/2014 00:40:53
kasskata avatar kasskata 492 Точки

Сега изследвам кода на Наков от подготовката и след малко ще дам код и за универсиални валидации на string, integer, boolean, пак направени на темплейти.

Готов съм с функциите, станаха прекраснички:

1. Стринг:

String.prototype.isNullOrEmpty = function (varName) {
if (typeof (this.valueOf()) != 'string') {
throw new Error(varName + "must be String");
}
if (!this.valueOf()) {
throw new Error(varName + " cannot be undefined or empty");
}
}

varName e променлива, която пази от кой сетър се вика функцията, подобно на Наков на примера, за да можете да хвърлите правилен Error. За да създадете темплейт вижте от картинката.

String аналогично се правят и другите просто следвайте картинките.

Няма нужда от първата валидация, защото създавам функция на прототипа на String object, но ако ви се рискува махнете я . Ако минавам през прототипа си спестявам яко много работа сега го осзнавам при тестовете, защото първо не можеш да кажеш на друг тип да извика тази функция, защото я няма, a ako не подавате нищо автоматично става undifined а undifined се оказва, че и той не вижда тази функция или по точно не може да се вика на undifined, защото не е стринг :D cool a ? Ако някой намери проблем да се обади преди изпита.

2. Integer

Number.prototype.isIntegerAndInRange = function (minValue, maxValue, varName) {
if (typeof ( this.valueOf() ) != 'number') {
throw new Error(varName + " must be Number.");
}
if (this === parseInt( this.valueOf() , 10)) {
throw new Error(varName + " must be Integer.");
}
if (this.valueOf() < minValue || this.valueOf() > maxValue) {
throw new Error(varName + " must be Integer in range[" + minValue + "..." + maxValue + "].");
}
return true;
}

Поради същата причина не ви трябва първата проверка, просто няма как да кажеш на нещо различно от Number да използва функцията. Гърми.

3. Boolean

Boolean.prototype.isBoolean = function (varName) {
if (typeof (this.valueOf()) != 'boolean') {
throw new Error(varName + " must be Boolean value.");
}
return true;
}

По тази логика от горните 2, май тази функция не ни трябва, но ако имате алтернативно решение споделете.

Ами за сега е това. Ако някой може да сподели и неговия опит с темплейти, ще съм ви благодарен.

П.С. Моля Администрацията на сайта: Добавете поле за код. Както е в StackOverflow например.

 

10
07/11/2014 00:20:48
LittleNinja avatar LittleNinja 71 Точки

С ReSharper-а е доста лесно :) :


Create template with ReSharper

2
07/11/2014 12:04:16
kasskata avatar kasskata 492 Точки

Вярно е доста лесно. Страхувам се от Resharper защото прекалява с благинките а и има много екстри според мен. Но е супер че споделяш и твоя начин. Ако искаш обясни малко по-подробно за да може хората, които не са пипали Resharper като мен, да може да си го настроят.

Може ли Resharper да ти взима имената на класовете, би трябвало след като е на JetBrains. според мен е била целта да го импортнат и в VS за да бъде още по- добро :D

Благодаря ти за отговора.

1
07/11/2014 16:31:30
presian avatar presian 223 Точки

За мен най-най лесно се правят снипетите  във съблайма. Уникално изчистено и елементаризирано е направено. Единствения му недостатък, е че няма директен ватиант за дебъгване. Но аз му намерих цаката - правя си проект през VS, но едитвам файла през съблайма, при отворено VS и когато максимизирам VS ми казва че им промяна по файла, и дали иксам да го рлоудне - аз естествено искам и така ползвам дебъгера на VS и едитора на съблайма. За мен това е най-добрата комбинция за момента.

3
kasskata avatar kasskata 492 Точки

Здравейте отново колеги.

Днес след 2 часа решаване на задачата от подготовката(забележете 2 часа :D с темплейтите ми), намерих дребни проблеми и неусъответствия в темплейтите си и искам да ви Updateна темплейтите за да не стават проблеми заради мен на изпита. :D 

Искам да се извиня на Влади, че наричам тези функции "клас" и "пропърти" след като ми направи забележка да ги казвам "function конструктори", но хората ще ме разберат по-добре.

А сега искам да се извиня на г-н Наков, като един виден C# фен и на всички хора, които уважават само истински ООПобразните езици, че сравнявам тези гротесни и пошли хакове с "класове" и "пропъртита", но хората така ме разбират. :D

Май след това изевление, пак ще трябва да се извинявам...laughing 

Конструктор на клас:

Видаях, че няма смисъл класа да се казва, както е файла защото е един, което означава че трябва да взима името от дуго място. Така че разликата е почти само там.

Ето Кода:

// Object.prototype.inherits = function inherits(parent) {
// this.prototype = Object.create(parent.prototype);
// this.prototype.constructor = this;
// }

var $CLASS$ = (function () {

function $CLASS$() {
// if(this.constructor === $CLASS$){
// throw new Error("Can't instantiate abstract class $CLASS$");
// }
$BASE$.apply(this, arguments);
}

// $CLASS$.inherits($BASE$);

$CLASS$.prototype.toString = function () {
// Only Type name
return this.constructor.name ;

// Base toString() func Override. Require New elemennts or will be undefined after "PLUS"
return $BASE$.prototype.toString.call(this) + ;
}


return $CLASS$;
}());

на промеливата "$CLASS$" сложете "classNameComplete()" от настройките на променливите;

Забележете че в кода има редове, които се използват за наследяване. Ако класа ви наследява нещо махате закоментирането и той е готов. Има Един ред ($BASE$.apply(this, arguments)), който е откоментиран за да може да си вземете името за парент класа, защото ако е закоментиран трябва да го налучкате, а така интелисенса помага. Можете спокойно да си разделите моя код на Абстрактен/Самостоятелен клас и Наследяващ клас и да стане 2 темплейта , но и така си е удобно. Ако не ви кефи това, че трябва при правенето на всеки клас да го има и прототипа на Оbject, който ви е най отгоре на темпейта просто си го направете на отделен темплейт, например вътре при жалидациите и да си го кръстите "Static Template" например, който да си викнете когато ви трябва най-горе.

Пропърти:

Код: 

IMPORT TO THE CONSTRUCTOR!
this.set$ARG$($args$);

// Get $ARG$
$CLASS$.prototype.get$ARG$ = function(){
return this._$args$;
}

// Set $ARG$
$CLASS$.prototype.set$ARG$ = function($args$){
// Check The Document for required validation on that property. May you lose some point if you don't have validation!!!!
this._$args$ = $args$;
}



На променливите трябва да изглежда така:
Untitled
Този дълъг коментар е нарочно дълъг за да се вижда от далече че там има липсваща валидация. Имайте предвид, че валидациите ще са доста голяма част от точките- поне 40 точки, ако трябва да съдим от задачите дадени за подготовка.Предлагам да не го махате, преди да сте намърдали някаква валидация.

 

Validation extends:

Code:

Object.prototype.inherits = function inherits(parent) {
    this.prototype = Object.create(parent.prototype);
    this.prototype.constructor = this;
}

String.prototype.isNullOrEmpty = function (varName) {
    if (typeof (this.valueOf()) != 'string') {
        throw new Error(varName + "must be String");
    }
    if (!this.valueOf()) {
        throw new Error(varName + " cannot be undefined or empty");
    }
}

Number.prototype.isIntegerAndInRange = function (minValue, maxValue, varName) {
    if (typeof ( this.valueOf() ) != 'number') {
        throw new Error(varName + " must be Number.");
    }
    if (this.valueOf() % 1 !== 0) {
        throw new Error(varName + " must be Integer.");
    }
    if (minValue > this.valueOf() || this.valueOf() > maxValue) {
        throw new Error(varName + " must be Integer in range[" + minValue + "..." + maxValue + "].");
    }
    return true;
    }

Boolean.prototype.isBoolean = function (varName) {
    if (typeof (this.valueOf()) != 'boolean') {
        throw new Error(varName + " must be Boolean value.");
    }
    return true;
}

 Тук просто взимате кода и праскате всичко в темплейт с подходящо име. "protoext" е моето име. Хубаво е да сложите курсора най-горе на функцията, която искате да валидирате, преди да извикате темплейта.

Има някои промени по кода(благодаря на Дани за адекватния feedback), така че ако сте копирали миналия ми темплейт махнете го, защото дава грешки когато въвете числа при някои случаи. Много е сложно за обеснение няма да ви занимавам, просто ископирайте наново. Този темплейт работи според мен на 90% от случаите. 

Обаждайте се, коментрирайте ако има нещо нередност или да благодарите. :D

2
11/11/2014 22:26:26
ttitto avatar ttitto 1155 Точки

Ако вкараш и да хвърля правилните изключения, а не само throw new Error цена няма да имаш.

0
kasskata avatar kasskata 492 Точки

Дай предложения как и кои error-и искаш да дава, защото аз съм сложил тези които Наков направи. До колкото знам няма голяма библиотека от ерори, за това така съм го написал.

Дай предложение с код за да ги овъррайдна.

0
ttitto avatar ttitto 1155 Точки

Имам предвид, да вкараш на мястото на throw new Error да хвърляш по-специфична грешка (напр. throw new ReferenceError(...)). Те са само няколко вида:

Error types

EvalError
Creates an instance representing an error that occurs regarding the global function eval().
InternalError
Creates an instance representing an error that occurs when an internal error in the JavaScript engine is thrown. E.g. "too much recursion".
RangeError
Creates an instance representing an error that occurs when a numeric variable or parameter is outside of its valid range.
ReferenceError
Creates an instance representing an error that occurs when de-referencing an invalid reference.
SyntaxError
Creates an instance representing a syntax error that occurs while parsing code in eval().
TypeError
Creates an instance representing an error that occurs when a variable or parameter is not of a valid type.
URIError
Creates an instance representing an error that occurs when encodeURI() or decodeURl() are passed invalid parameters.

1
11/11/2014 22:54:22
alexxdim94 avatar alexxdim94 41 Точки

Супер са темплейтите, мерси. Аз доста си ги модифицирах де, но преди тази тема не знаех, че съществуват. :D

0
kasskata avatar kasskata 492 Точки

Евала алекс. Как си ги модифицирал сподели кода си.

1
kasskata avatar kasskata 492 Точки

Може ли да обясниш стъпка по стъпка, как става, за да стане по-ясно за аудиторията.

 

1
Matrix avatar Matrix 1087 Точки

В линка/документацията на плъгина си е обяснено както подобава, даже и шорткътите са посочени ;)

Sublime text rulz!

1
13/11/2014 12:06:05
kasskata avatar kasskata 492 Точки

Сега за новия курс [JSAdvance] предполагам че пак ще ви бъде полезна тази информация.

Така че обаждайте ми се ако имате въпроси.

Споменавам от сега, че не споря сникой, че това е правилния начин за правене на Функциите просто искам да покажа как да ползвате базово Live Templates в Jetbrains продуктите(в темата се съдържат и начини за Sublime Text темплейти и Resharper).

Свободни сте да променяте, триете, режете, псувате моите темплейти, но все пак споделете вашите промени, за да обогатим темата за слдващите "поколения" :D

4
12/03/2015 15:40:22
a.angelov avatar a.angelov 1331 Точки

Благодаря, че повдигна темата. Спомням си, че я бях мяркал есента, но съм забравил за нея :)

Вече се възползвах от темплейтите и ги направих на snippet-и в Sublime.

Как се правят snippet-и в Sublime, може да видите тук: http://docs.sublimetext.info/en/latest/extensibility/snippets.html 

Ето и как изглежда снипет файла при добавяне на isNullOrEmpty функцията към String. В <tabTrigger> тага слагате текста, който като въведете и натиснете таб ще ви разпъне снипета, в <description> - описанието, което да излиза при търсене в менюто от снипети и съответно в <content> тага - самото съдържание на снипета:

<snippet>
<content><![CDATA[
String.prototype.isNullOrEmpty = function (varName) {
if (typeof (this.valueOf()) !== 'string') {
throw new Error(varName + "must be String");
}
if (!this.valueOf()) {
throw new Error(varName + " cannot be undefined or empty");
}
};
]]></content>
<!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
<tabTrigger>valstr</tabTrigger>
<description>Extension to String.prototype which validates null or empty string in JavaScript</description>
<!-- Optional: Set a scope to limit where the snippet will trigger -->
<!-- <scope>source.python</scope> -->
</snippet>
0
12/03/2015 11:41:55
vbishurov avatar vbishurov 18 Точки

Здравейте, хайде и аз да се включа малко в темата.

WebStorm си има опция за export на template-и. От File->Export Settings... Избираме само ExportableTemplateSettings, Live templates. Това ни генерира един .jar файл, в който има само "правените" template-и. Тоест не експортва вградените template-и. Процедурата за импортване е аналогична: File->Import Settings... и избираме файла.

Позволих си да направя някой промени по вече същеструващите template-и, като главно те са върху валидацията. Според мен функциите за валидация трябва да бъдат закачени на Object, вместо на по-конкретните функции, тъй като по-този начин се обезмисля проверката на типа. Например: 

var pesho = 5;
console.log(pesho.isNullOrEmpty("pesho"));

Ако функцията е закачена за стринг този код ще каже:
TypeError: Object 5 has no method 'isNullOrEmpty', вместо
TypeError: pesho must be a String

Също така добавих по-специфичните грешки и разделих template-а за клас на 2 - за клас, който не наследява друг клас и такъв, който го прави (според мен е по-удобно). Функцииката за наследяване си остава само в protoext, за да не се добавя при всяко създаване на клас наследник.

Ето това са експортнатите template-и: Цък

1
12/03/2015 14:05:46
kasskata avatar kasskata 492 Точки

Вили, разбирам твоето недоумение, защо съм го закачил към прототипа на стринга, но това е по простата причина, че трябва да проверяваш дали Object typeof("Pesho") == "String", докато по моя начин си спестявам тази проверка при валидацията, само с това закачане към правилния тип, логично е когато питаш(в VS не в JS IDЕ-та), string.IsNullOrEmpty() даже да не ти излезне ако не е от подходящия тип.

Надявам се да си ме разбрал защо го правя(и твоя начин е правилен, нев го отричам), но не спирам никой да променя или да подобрява, но забранявам да не споделяте с нас промените :D 

0
12/03/2015 15:35:26
vbishurov avatar vbishurov 18 Точки

Прав си, не би трябвало да излиза, но идеята, е че ти работиш с променливи, на които не знаеш какъв е типа. Тоест конструктора работи върху променливата name например. И ние очакваме, че name е стринг и му викаме name.isNullOrEmpty(), но всъщност ако през конструктора ни е подадено числото 5 а не стринг това ще гръмне с грешката, че 5 няма такъв метод, а не, че 5 не е стринг. Това е идеята да бъде закачено за Object и да има проверка.

P.S. Промените съм ги качил в линка. Jar файла си е обикновен архив - отваряш го и ги гледаш вътре. С цел да не става много дълъг поста не съм ги написъл тук.

Edit: Забравих факта, че на изпита инпута ще е валиден, което прави закачането на Object и проверката излишни.

0
12/03/2015 15:51:56
kasskata avatar kasskata 492 Точки

По-добре си ги валидирай, независимо колко са правилни инпутите.
Супер че си се постарал да дадеш и external файл и да обясниш как работи, защото аз скоро преинталирах и не го бях направил и сега само от тук мога да си ги взема(backup e много важен).

Разбрах те, какво искаш да кажеш за Object прототипа. Според мен е по-правилно функциите, които се отнасят за определен тип данни да си екстендват него. Според мен е по-чисто като логика. Но и твоя начин също е добър, но тогава ще трябва да проверяваш и типа на данните, които идват. Абе все тая е дали по твоя начин или моя важно е да има проверки 

:D

2
quickben avatar quickben 976 Точки

Защо да използваме това животно вместо да използваме TypeScript или CoffeeScript, мисля, че смисъла на курса е да научим чист джава скрипт а не как да излъжем системата....

0
a.angelov avatar a.angelov 1331 Точки

Какво лъжене на системата имаш в предвид? Тук става въпрос само за по-бързо писане чрез създаване на темплейти.

0
kasskata avatar kasskata 492 Точки

Да тука малко проблема ни е да си създадем Visual Studio продуктивност. Защото иначе пишеш бавно :)

А по този въпрос за TypeScript или CoffeeScript, защо не ни обясниш какво имаш предвид, ако вярно е по-бързо и помагащо за изпита ви, ще съм ти много благодарен да науча нещо ново :)

0
13/03/2015 18:12:46
quickben avatar quickben 976 Точки

Как да ти кажа, след като никой незнае какъв ще ни е изпита, на подготовката ще се разбере. А относно миналото ми запитване просто ми се струва, че е нещо като на C# Basics петата задача където cheat-вахме като използвахме StringBuilder вместо да научим побитовите операции каквтото беше идеята на тази задача. :)

0