Как написать аккуратное и гибкое сложное приложение JavaScript, используя наследование прототипов

Некоторое время я разрабатывал приложения javascript, обычно небольшие сценарии для выполнения простых задач, а также довольно большие и сложные приложения с использованием библиотека base2 Дина Эдвардса для создания псевдоклассических объектно-ориентированных классов с наследованием... в javascript.

Библиотека base2 сослужила мне хорошую службу, главным образом потому, что она позволила мне следовать классической парадигме объектно-ориентированного программирования, с которой я хорошо знаком. Я также знаю несколько других фреймворков, которые можно использовать для создания более надежных и зрелых приложений javascript (backbone.js например). Но у меня всегда есть ощущение, что этот тип библиотеки — это способ «обмана», чтобы создать способ написания кода с использованием принципов, для которых язык на самом деле не подходит.

Я читал о различных способах определения объектов/функций, создания их экземпляров и достижения полиморфизма с использованием прототипного наследования. Это действительно то, как язык работает на фундаментальном уровне, и я чувствую, что должен воспользоваться этим, а не решать, что это раздражает или странно, и пытаться найти способ делать вещи так, как я привык (классический способ OO ).

Итак, глядя на приложения, которые не используют этот тип библиотеки, кажется, что существует так много способов написать ваше приложение, в то время как для традиционных языков общего назначения, таких как Java, C++, ... правильный способ создания ваших приложений кажется более четко определенным. (намного легче отличить хороший код от плохого). Если кто-нибудь спросит меня завтра: «начать разработку проекта X для меня», я понятия не имею, как начать определять и структурировать свои объекты таким образом, чтобы я был уверен, что они не вернутся, чтобы укусить меня позже, когда будет слишком поздно реструктурировать Все это.

Как будет выглядеть скелет профессионального сложного приложения js с использованием прототипного наследования, то есть без использования какой-либо библиотеки для имитации классического объектно-ориентированного программирования, предполагая простой тип приложения MVC, но легко масштабируется до более сложных пропорций. Как определить мои объекты? Как сгруппировать объекты/классы (пространство имен)? Другими словами: как это сделать, не получая беспорядка, в котором никто больше не разбирается?


person Asciiom    schedule 04.09.2012    source источник
comment
Почему бы не потратить некоторое время на изучение популярных в настоящее время фреймворков, таких как Backbone, Ext, Ember, Angular и т. д.? Даже если они вам не нравятся, это простой способ познакомиться с архитектурными шаблонами.   -  person Pointy    schedule 04.09.2012
comment
Я просмотрел некоторые из них, но из-за множества различий я до сих пор не знаю, как лучше всего это сделать. Возможно, это слишком субъективный вопрос.   -  person Asciiom    schedule 04.09.2012
comment
Ну да, это довольно субъективно — лично я редко использую наследование в JavaScript, потому что предпочитаю добиваться повторного использования кода за счет функциональных аспектов языка. Кроме того, лично мне не нравится идея логики приложения на клиенте; У меня много клиентского кода, но он касается функций на стороне клиента, а не логики приложения. Но это только моя личная ситуация и мое мнение. Мне нравится читать о том, что делают все эти фреймворки, потому что мне интересно знать о подходах к проектированию и методах кодирования.   -  person Pointy    schedule 04.09.2012
comment
Я понимаю, что вам не нравится иметь слишком много логики приложения на клиенте, но в зависимости от типа приложения, которое вы создаете, необходимо иметь такую ​​структуру на клиенте. В моем случае мне пришлось написать инструмент для разработки печатных PDF-файлов в браузере, он имеет довольно большой внешний интерфейс для создания объектов модели, содержащих страницы файла, элементы, свойства элементов и т. д. В таком приложении это не является обязательным, если только вы не пользователи не возражают против долгого ожидания :) И даже тогда количество логики, заложенной в такое приложение, требует приличной структуры.   -  person Asciiom    schedule 04.09.2012
comment
Да-да, моя личная ситуация связана с финансовым приложением, поэтому вся моя серьезная логика действительно должна быть на моей стороне брандмауэра :-) Из-за этого мне не нравится идея архитектуры, которая включает объектные модели на обе стороны. Таким образом, мой клиентский код предназначен для обеспечения работы представлений, а его архитектура посвящена этой проблеме, а не логике приложения. Я уверен, что я здесь необычный. То, что вы описываете, похоже на то, для чего предназначены современные фреймворки JavaScript.   -  person Pointy    schedule 04.09.2012
comment
Да, вижу, разные миры :) Для себя вижу множество способов начать писать такое приложение (один из которых я реально осуществил), но никак не могу определиться с тем, что будет лучшее общее решение. Моя текущая кодовая база, на мой взгляд, слишком беспорядочна, отсюда и мой вопрос.   -  person Asciiom    schedule 04.09.2012


Ответы (1)


Есть два шаблона, которым я следую при создании объектно-ориентированных «классов» Javascript (хотя в JS нет реальных классов, мы можем их имитировать). Во-первых, это более знакомый ООП и простой для понимания.

// in JS, functions can be used as OO classes
var Person = function(name) {
    var self = this;

    //private methods and attributes
    this.getNickname = function(){
        return "Yaka";
    };

    //public methods and attributes (return obj)
    return {
        getName : function() {
            return name + ' ' + self.getNickname();
        }
    }
};

//static functions attached to 'Person' class 
Person.hasBrain = function() {
    return true;
}

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

// in JS, functions can be used as OO classes
var Person = function(name) {
    this.name = null;
};

// use of prototypes improves performance and memory use
Person.prototype.getName = function() {
    return this.name;
}

Person.prototype.setName = function(name) {
    this.name = name;
}   

Это не выглядит очень привычным для традиционных объектно-ориентированных программистов, но это оптимальный способ использования ресурсов javascript. С наследованием тоже все в порядке.

var Manager = function() {}
Manager.prototype = new Person();

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

Я также рекомендую вам использовать библиотеку AMD, такую ​​как requirejs, и определять один класс для каждого физического файла. Затем используйте оптимизатор сборки, чтобы оптимизировать ваши файлы в один скрипт.

Я скопировал вышеприведенные 2 подхода из модульных тестов в эталонной архитектуре BoilerplateJS. Взгляните на код в BoilerplateJS, он даст вам больше идей о том, как подойти к разработке сложных приложений с помощью JS.

Отказ от ответственности: я являюсь основным автором BoilerplateJS

person Hasith    schedule 05.09.2012