Собираем
информацию
по крупицам

RSS подписка

Подпишитесь на новости сайта по RSS

Статьи - Компьютерное

Перевод документации Ext JS 4.2

Ext JS 4.2. Часть 2: Система классов
24-08-2013
19:12:56

 

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

 

Описание системы классов разбито на 4 раздела:

  • Раздел I: Краткий обзор, в котором объясняется необходимость надежной системы классов;
  • Раздел II: Соглашения о наименовании. В разделе рассказывается о способах наименования классов, методов, переменных и файлов;
  • Раздел III: Практикум. Рассматриваются пошаговые примеры написания кода;
  • Раздел IV: Отслеживание ошибок и отладка. Полезные советы о том, как отлавливать исключения.

 

I. Краткий обзор

 

Фреймверк Ext JS состоит из более чем 300 классов. Наш фреймверк объединил большое мировое сообщество из более чем 200000 разработчиков, работающих в самых различных сферах информационных технологий. Поэтому, для того, чтобы фреймверк был прост в использовании и хорошо масштабируем, необходимо чтобы архитектура фреймверка удовлетворяла следующим требованиям:

 

  • Лёгкое обучение;
  • Быстрая разработка, простая отладка, беспроблемная публикация на боевом сервере;
  • Хорошая организованность кода и расширяемость.

 

Язык JavaScript - это прототипно-ориентированный язык программирования, в котором отсутствуют классы. Следовательно, по своей природе язык JavScript чрезвычайно гибок, что позволяет делать одну и ту же работу различными путями, используя совершенно разные стили и методики написания кода. Однако за такую гибкость приходится платить большую цену. Цена эта - трудно прогнозируемое качество результата работы программиста. Не имея четкой и унифицируемой структуры, на языке JavaScript легко создать трудно понимаемый код, непригодный для сопровождения и повторного использования.

 

Модель программирования, основанная на классах, всё ещё остается очень популярной методикой, называемой объектно-ориентированным программрованием (ООП). Языки, основанные на классах, обычно требуют строгую типизацию данных, эффективно скрывают реализацию, а разработчики обычно придерживаются стандартов в соглашениях о кодировании. Заставляя разработчиков придерживаться общепринятых принципов, написание кода можно  сделать более предсказуемым, а код более расширяемым и масштабируемым в течении длительного времени. Однако, у таких языков нет тех же возможностей по динамическому расширению кода, которые есть у JavaScript.

У каждого подхода есть свои достоинства и недостатки, однако почему бы не взять всё хорошее из обеих подходов, при этом отбросив все неудачные решения? Именно это мы и реализовали в нашем фреймверке Ext JS 4.x.

 

II. Соглашения о наименовании

 

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

 

 

1) Именование классов

 

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

 

Пример:

 

MyCompany.useful_util.Debug_Toolbar - недопустимо
MyCompany.util.Base64 - допустимо

 

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

 

Пример:

 

MyCompany.Application

MyCompany.data.CoolProxy

 

 

Пространство имен верхнего уровня и имя текущего класса необходимо писать в ВерхнемВерблюжьемРегистре, все остальное - в нижнем.

 

Пример:

 

MyCompany.form.action.AutoLoad

 

 

Классы, автором которых не является компания Sencha, никогда не должны использовать "Ext" в качестве пространства имен верхнерго уровня.

 

Аббревиатуры (т. е. устоявшиеся сокращения) так же должны писаться в ВерхнемВерблюжьемРегистре.

 

Примеры правильного написания:

 

Ext.data.JsonProxy вместо Ext.data.JSONProxy
MyCompany.util.HtmlParser вместо MyCompary.parser.HTMLParser
MyCompany.server.Http вместо MyCompany.server.HTTP

 

 

2) Исходные файлы

 

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

 

Пример:

 

Файлы классов Ext JS:

Ext.util.Observable расположен в path/to/src/Ext/util/Observable.js
Ext.form.action.Submit расположен в path/to/src/Ext/form/action/Submit.js

 

Файл стороннего класса:
MyCompany.chart.axis.Numeric расположен в path/to/src/MyCompany/chart/axis/Numeric.js

 

В данном примере путь path/to/src является путем к директории, в которой расположены файлы классов вашего веб-приложения. Все файлы классов должны располагаться где-то внутри данной директории, которая считается корневой. Такая организация исходного кода обеспечит наилучшее дальнейшее сопровождение и доработку.

 

 

3) Именование методов и переменных

 

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


Названия методов и переменных должны всегда писаться в нижнемВерблюжиемРегистре. Это правило относится так же и к аббревиатурам.
 
Примеры:

 

Допустимые имена методов:

encodeUsingMd5()

getHtml() вместо getHTML()

getJsonResponse() вместо getJSONResponse()

parseXmlContent() вместо parseXMLContent()

 

Допустимые имена переменных:

var isGoodName

var base64Encoder

var xmlReader

var httpServer

 

 

4) Именование свойств

 

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

 

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

 

Пример:

 

Ext.MessageBox.YES = "Yes"
Ext.MessageBox.NO = "No"
 MyCompany.alien.Math.PI = "3.14"

 

 

III. Практикум


1. Определения классов

1.1) Старый подход

 

Если вы пользовались предыдущей версией Ext JS, вы, конечно, знаете как легко и быстро создать класс на основе уже существующего:

 

var MyWindow = Ext.extend(Object, { ... });

 

Такой метод подходит для создания класса, унаследованного от другого. Но помимо прямого наследования у нас раньше небыло никаких других API-механизмов для создания классов: небыло конфигурирования, небыло описания статических членов класса, небыло внедрения примесей (mixing). Далее мы рассмотрим эти пункты подробнее.

 

А сейчас давайте рассмотрим другой пример:

 

My.cool.Window = Ext.extend(Ext.Window, { ... });

 

 

В этом примере мы указываем пространство имен нашего нового класса, и создаем его путём расширения класса Ext.Window. Здесь мы имеем две серьезные проблемы:

 

  • Объект My.cool должен существовать до того, как мы создадим Window в качестве свойства;
  • Объект Ext.Window должен существовать (т .е. должен быть загружен на страницу) до того, как мы будем к нему обращаться и получать на него ссылку

 

Первую проблему обычно решают с помощью Ext.namespace (альтернативное имя - Ext.ns). Этот метод рекурсивно обходит весь объект, обрабатывая всё дерево свойств класса и создает нужные свойства если их нет. Вы должны постоянно помнить, что этой конструкцией всегда нужно предварять вызов Ext.extend:

 

Ext.ns('My.cool');
My.cool.Window = Ext.extend(Ext.Window, { ... });

 

Вторую проблему не так то просто решить, потому что Ext.Window зависит от многих других классов, которые наследует напрямую и коственно, а те в свою очередь зависят от других классов. По этой причине приложения, которые использовали более ранние версии чем Ext JS 4, содержали все библиотеки в файле ext-all.js. В этом фйле содержался код всех классов, из которых реально использовалась только малая часть.

 

1.2) Новый подход

 

В Ext JS 4 все вышеперечисленные недостатки исправляются одним-единственным методом, через который создается новый класс. Этот метод называется Ext.define. Его базовый синтаксис следующий:

 

Ext.define(className, members, onClassCreated);

 

где:

  • className - имя класса;
  • members - список свойств класса, оформленный в виде пар ключ-значение;
  • onClassCreated - необязательный параметр, в котором задается функция обратного вызова, которая будет вызвана в тот момент, когда новый класс будет полностью готов для работы и все элементы класса будут созданы. Из-за новой асинхронной природы создания класса, этот вызов может быть полезным во многих ситуациях. Они будут обсуждены далее в разделе IV.

 

Пример:

 

Ext.define('My.sample.Person', {

 name: 'Unknown',

 constructor: function(name) {
  if (name) {
   this.name = name;
  }
 },

 eat: function(foodType) {
  alert(this.name + " is eating: " + foodType);
 }
});

var aaron = Ext.create('My.sample.Person', 'Aaron');
aaron.eat("Salad"); // alert("Aaron is eating: Salad");

 

В этом примере мы определили объект My.sample.Person с помощью Ext.define. Затем мы создали экземляр объекта с именем aaron, укзав в качестве прототипа My.sample.Person используя Ext JS метод  Ext.create(). Для создания экземпляров объектов рекомендуется всегда использовать метод Ext.create() так как созданные этим методом объекты позволяют использовать динамически подгружаемый код. О динамической загрузке кода можно прочитать во введении в фреймверк Ext JS 4.

 

 

2. Конфигурирование класса

Ext JS 4 предоставляет специальное свойство config, которое позволяет сконфигурировать класс, перед тем как он создастся. Преимущества свойства config:

 

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

    Например, если в config прописать свойство с именем title, то автоматически будут созданы методы setTitle и getTitle. Внутри класса свойство title будет доступно как this.title.

  • Метод apply автоматически создается для каждого конфигурирующего класс свойства. Автоматически сгенерированный метод set вызывает внутри себя метод apply перед тем, как будет установлено значение свойства. Можно переопределить метод apply, если необходимо создать специальную логику работы класса перед изменением значения свойства. Если метод apply не возвращает никакого зачения, тогда сеттер не будет устанавливать переданное ему значение. Для примера, посмотрите на метод applyTitle ниже.

 

Пример определения класса:

 

Ext.define('My.own.Window', {
 /** @readonly */
 isWindow: true,

 config: {
  title: 'Title Here',

  bottomBar: {
   height: 50,
   resizable: false
  }
 },

 constructor: function(config) {
  this.initConfig(config);
 },

 applyTitle: function(title) {
  if (!Ext.isString(title) || title.length === 0) {
   alert('Ошибка: заголовок не может содержать пустую строку');
  }
  else {
   return title;
  }
 },

 applyBottomBar: function(bottomBar) {
  if (bottomBar) {

   if (!this.bottomBar) {
    return Ext.create('My.own.WindowBottomBar', bottomBar);
   }
   else {
    this.bottomBar.setConfig(bottomBar);
   }
  }
 }
});

/** A child component to complete the example. */
Ext.define('My.own.WindowBottomBar', {
 config: {
  height: undefined,
  resizable: true
 }
});

 

Вот как этот класс можно использовать:

 

var myWindow = Ext.create('My.own.Window', {
 title: 'Привет всем!',
 bottomBar: {
  height: 60
 }
});

alert(myWindow.getTitle()); // сообщение "Привет всем!"

myWindow.setTitle('Теперь другой заголовок');

alert(myWindow.getTitle()); // сообщение "Теперь другой заголовок"

myWindow.setTitle(null); // сообщение "Ошибка: заголовок не может содержать пустую строку"

myWindow.setBottomBar({ height: 100 });

alert(myWindow.getBottomBar().getHeight()); // сообщение 100

 

 

3. Статические свойства класса

 

Статические члены класса определяются с помощью специального члена класса с именем statics:

 

Ext.define('Computer', {
 statics: {
  instanceCount: 0,
  factory: function(brand) {
   // 'this' - это статический метод, через который класс может обратиться сам к себе
   return new this({brand: brand});
  }

 },

 config: {
  brand: null
 },

 constructor: function(config) {
  this.initConfig(config);

  // Свойство 'self' - это ссылка на данный экземпляр класса (надо уточнить...)

  this.self.instanceCount ++;
 }
});

 


var dellComputer = Computer.factory('Dell');
var appleComputer = Computer.factory('Mac');

 

// Пример использования автоматически сгенерированного геттера

// для конфигурирующего свойства brand

alert(appleComputer.getBrand()); // сообщение "Mac"

alert(Computer.instanceCount); // сообщение "2"

 

 

IV. Отслеживание ошибок и отладка

 

Ext JS 4 включает в себя несколько полезных инструметов, которые помогут вам с отладкой и обработкой ошибок.

 

Вы можете использовать вызов Ext.getDisplayName() для получения имени любого метода. Этот вызов можно использовать при перехвате исключений при возникновении ошибки чтобы выяснить имя класса и наименование метода:

 

throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] Some message here');

 

Когда ошибка возникает в методе класса, определенного с помощью Ext.define(), вы можете увидеть имя класса и метода в стеке вызовов, если вы используете основанный на WebKit браузер (Chrome или Safari). Для примера приведем скриншот, как это выглядит в Chrome:

 

 

В консоли ошибок браузера FireFox можно увидеть такую же информацию.

 

 



К списку "Компьютерное"

Поделиться этой страницей



Внимание!


На этом сайте разрабатывается программа MyTetra и её родственные проекты. Доступны к просмотру следующие базы знаний:

 

База Xintrea (стр. 1)

База Rarrugas (стр. 1)

База Balas

База YellowRaven

База Yurons

База Lesnik757

База Shandor

База Sirrichar

База Anatolean (стр. 1)

База Аrmagedec

База SorokinRed

База Deadelf79

База Adgaver (стр. 1)

База Pipitos1983

База Soxsten (стр. 1)

База Silenn (стр. 1)

База Shlyapnikova - херомантия и ригидность

База Svoynickname (стр. 1)

База Larson227 (стр. 1)

База Velonski (стр. 1)

База BrokeRU (стр. 1)

База Mcold (стр. 1)

База Alensav (стр. 1)

База Consp11 (стр. 1)

База Kozlov-AE (стр. 1)

База Wwwlir (стр. 1)

База Duwaz (стр. 1)

 

Требуют доработки:

 

База Tairesh

База Ivnglkv

База Kolyag87

База Andyk101

База Garik456456

База Harpokrat

База SalexIzyh

База RuDennn (Bunny-Hop)

База Manakaden

База Vitvrn

База Fanrok

База Grimar

База_Juryak

База Nicolasomsk

База Azatserikbaev

База Shut913

 

Подробности на странице MyTetra Share.

 WebHamster.Ru
 Домик любопытного хомячка
Яндекс индекс цитирования
Почтовый ящик