Category: Программирование

21
июля

Классический MVC

Написал    в категории  Программирование 1

Это мой вольный перевод статьи Била Сандерса о реализации классического мета паттерна MVC на Smalltalk-80. Так как это мой первый опыт, строго не судите и в комментариях желательно оставлять какие либо замечания по тексту. Переводил не дословно, немного из русскоязычных источников накопал (и каюсь, перевёл не всё).

Это не введение в модель MVC, а  обзор его осуществления на Smalltalk-80 для понимания первоначальных намерений и функций триады. Классическая MVC поможет лучше понять последующее развитие  паттернов, которые появились позже. Посмотрим, как простое MVC приложение работает в Smalltalk-80 и изучим как оно может быть реализовано на языке ActionScript.

Model-view-controller (MVC, «Модель-представление-поведение», «Модель-представление-контроллер») — архитектура программного обеспечения, в которой модель данных приложения, пользовательский интерфейс и управляющая логика разделены на три отдельных компонента, так, что модификация одного из компонентов оказывает минимальное воздействие на другие компоненты.

Современный вид MVC.

Реализация Model-View-Controller в Smalltalk-80.

Модель MVC облегчает разделение ответственности при разработке интерактивных графических приложений. Логика и состояние приложения, как пользователи взаимодействуют с приложением, и как состояние приложения представляется пользователю  по средствам отдельных элементов триады MVC. Smalltalk-80 использует метафору MVC, что обеспечивает встроенную поддержку для интерактивной разработки приложений. Идея заключалась в том, чтобы обеспечить набор встроенных компонентов пользовательского интерфейса, таких как кнопки, меню и списки, которые могут быть подключены к GUI приложения. Для эффективного использования этих встроенных элементов интерфейса, реализация должна была быть построена в соответствии с MVC. Давайте посмотрим на концептуальную диаграмму приложения Smalltalk-80. Прочитать полностью →

23
мая

От суеверий к пониманию


Существуют моменты когда хочется перевести стрелки на баги языка, фреймворка или API какого нибудь ресурса, мол у меня идеальный код, а во всём виноват кто-то другой. Вот что думает по этому поводу Стив Макконнелл:

Одно из основных различий между любителями и профессиональными программистами — различие, появляющееся при переходе от суеверия к пониманию. Под суеверием я здесь понимаю не иллюзию, что программа выдаёт больше ошибок в полнолуние, а замену «прочувствования» программы и её пониманием. Если вы часто обнаруживаете, что подозреваете компилятор или аппаратные средства в ошибке, вы в плену суеверий. Давнишние исследования показали, что только  около 5% всех ошибок связано с аппаратурой, компиляторами или ОС (Ostrand and Weyuker, 1984). Сейчас этот процент, видимо, ещё меньше. Программист, достигший сферы понимания, обращает внимание прежде всего на своё творение, являющееся потенциальным источником 95% ошибок. Нужно знать роль каждой строки своей программы. Ничто не может называться верным только потому, что выглядит работоспособным. Если вы не знаете, почему это работает, вероятно, оно и не работает на самом деле.

С. Макконнелл (Совершенный код)

Стараемся, думаем, учимся и превращаемся из любителей в профессионалы :)

28
марта

Организация визуальных объектов


Например нужно создать контейнеры с разделами сайта и не запутаться кто под кем лежит и ид.

Задача. Удобно организовать визуальные объекты на сцене.

Это как то централизует управление основными визуальными слоями в приложении:

public class StageProxy extends MovieClip {
        private var _layers:Object;

	/**
	 * Modules
	 */
	public static const CONTACTS:String = "contacts components layer";
	public static const PORTFOLIO:String = "portfolio components layer";
	public static const NEWS:String = "news components layer";
	public static const SERVICE:String = "service components layer";

	private function initScene():void {
		_layers = { };

		// main module
		stage.addChild( _layers[PORTFOLIO] = new MovieClip() );
		stage.addChild( _layers[NEWS] = new MovieClip() );
		stage.addChild( _layers[SERVICE] = new MovieClip() );
		stage.addChild( _layers[CONTACTS] = new MovieClip() );
	}

	//----------------------------------
	//--------  GETTER method
	//----------------------------------
	public function getLayer(layerKey:String):Object {
			return _layers[layerKey] as Object;
	}
}

Забираем нужный слой вот так:

_stageProxy.getLayer(StageProxy.NEWS);

Всё.

2
декабря

Слайд-шоу

Написал    в категории  Программирование 3

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

Задача. Сделать слайд-шоу.

Пример кода реализующий задачу:

var idInt:Number;

// Массив имён ссылающихся на экземпляры картикон в библиотеке
var imageArr:Array = new Array("im1","im2","im3");
// Текущее изображение
var targetImage:Number = 1;
// Следующее изображение
var nextImage:Number = 2;

function startSlide():Void {
        // На верхний слой кидаем начальное изображение
	target_mc.attachMovie(imageArr[targetImage],"image", 1);
        // Под него кладём следующее
	nextImage_mc.attachMovie(imageArr[nextImage], "image", 1);
        // Запускаем анимацию смены картинки
	mask_mc.gotoAndPlay(2);

        // Меняем id текущего изображения
	targetImage=nextImage;

        // Запускаем таймер на 12 секунд, далее рекурсивно вызываем функцию
	clearInterval(idInt);
	idInt = setInterval(startSlide, 12000);
	nextImage++;

	if (nextImage > imageArr.length-1) {
		nextImage = 0;
	}
}

startSlide();
Пример работы был сделан на период работы в студии Ample.
13
октября

Сайт на PureMVC + SWFAddres


Это действительно надо!

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

Инструменты: PureMVC, SWFAddress.

Что происходит на сервере?

На стороне сервера было реализовано следующее: по ссылке http://exampl.ru/catalog мы переходим на страничку с каталогом, но если мы добавим параметр /?xml то получаем данные с этой страницы в формате xml. Для начала сделаем унифицированный xml документ со статичными аттрибутами mod и view, первый нам говорит — что за модуль мы должны загрузить, а второй сообщает нам как мы должны его отобразить:

<data mod="nameOfModul" view="typeOfView">
...more...
</data>

Например: имеется модуль галереи, у которого есть три представления:

  • Просмотр всего списка (view = allImage)
  • Отображение выбранного изображения (view = targetImage)
  • И допустим вывод картинок по какому-то признаку (view = sortBy).

В данном случае имя модуля остаётся неизменным mod = gallery, а имя представление модуля меняется соответственно на allImage, targetImage, sortBy, — говоря нашему приложению как надо обрабатывать эти данные.

Как с этим должна работать клиентская часть?

Для начала разберёмся с адресной строкой (для этого использована библиотека SWFAddress), так выглядит слушатель события реагирующий на изменение ссылки в адресной строке:

SWFAddress.addEventListener(SWFAddressEvent.CHANGE, handleSWFAddress);

function handleSWFAddress(e:SWFAddressEvent) {
    var paramArr:Array = new Array(); //массив параметров
    paramArr = e.value.split("/");
    var url : String = ""; // переменная с ссылкой на xml
    // формирем ссылку на xml документ
    for(var i : Number = 1;i <= paramArr.length - 1; i++) {
        (paramArr[i] == "" || paramArr[i] == "#") ?
            null :
            url += "/" + paramArr[i];
    }
    var sufixUrl:String ="?xml"; //
    url == "" ?
        null :
        loadXmlData("example.ru/"+ url + sufixUrl);
    paramArr = null;
}

Таким образом адресная строка вида http://example.ru/#/catalog будет распарсена и передана в качестве параметра методу loadXmlData(); в виде ссылки http://example.ru/catalog/?xml на иксэмэль документ. После загрузки файла в в метод choiseModule(); передаётся полученный нами xml документ. Его код можно посмотреть ниже:

private function choiseModule(dataXml:XML):void {
	switch (dataXml.@mod) {
		case "home":
			sendNotification(ApplicationFacade.HOME_DATA_SUCCESS,
                                                               dataXml);
		break;

		case "gallery":
			sendNotification(ApplicationFacade.GALLERY_DATA_SUCCESS,
                                                               dataXml);
		break;
        }
}

Далее, как видно, данные передаются в зависимости от того какой модуль написан в атрибуте mod, и выполняется отображение конкретного представления.

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

Ссылки

  1. PureMVC — это реализация классического MVC для Flash-платформы.
  2. Bumpslide Framework AS 3.0 and AS 2.0 (Много полезных компонентов + )
9
октября

Тройной клик (as3.0)

Написал    в категории  Программирование 3

Тройной клик понадобился для функционала аудио плеера, аналогично управлению на ipod`ах. Один клик это — запуск песни и пауза, двойной клик — переход к следующей композиции, тройной — переход к началу композиции.

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

Минус в том что ожидание нажатия для всех положений одно :)

public function Main()
{
	clickTimer = new Timer(1);
	but = new button();
	addChild(but);

	but.buttonMode = true;
	but.doubleClickEnabled = true;
	but.addEventListener(MouseEvent.DOUBLE_CLICK, doubleHandle);
	but.addEventListener(MouseEvent.CLICK, clickHandle);
}

public function clickHandle(e:MouseEvent):void {
	stateClick = true;
	stateDoubleClick = false;

	if (! clickTimer.running) {
		clickTimer = new Timer(500, 1);
		clickTimer.addEventListener("timer", timerClickHandler);
		clickTimer.start();
	} else {
		trace("triple click");
		stateDoubleClick = false;
		stateClick = false;
	}
}

public function doubleHandle(e:MouseEvent):void {
	stateDoubleClick = true;
	stateClick = false;
}

public function timerClickHandler(event:TimerEvent):void {
	if (stateDoubleClick) trace("double click")
	if (stateClick) trace("just one click");
}

Наверное есть ещё какие-нибудь решение этой задачи, если кто знает то пишите в комменты.

28
сентября

Утечка памяти


Шейн Макартни сделал отличную презентацию. Для себя я отдельно выписал немного «догматов»:

  1. new Array(); -> Array[]
    new Object(); -> Object{}
  2. list[i] -> list[int(i)]
  3. list.push(item) -> list[length] = item
  4. list.splice(i, 1); -> list[i] = null -> list.splice(i, count)
  5. delete dict[key] -> dict[key] = null
  6. list = new Array(); -> list.length = 0;
  7. bmd = new BitmapData(32, 32); ->bmd.fillRect(bmd.rect, 0xFFF);
  8. while(i>0) {while(j>0) {} } -> while(k>0){}
  9. do1 function():void {do2} -> do12 function():void {}
  10. Определяй переменные в одну строку
  11. Деление хуже умножения
  12. MyType(instance) -> instance as MyType;

Ссылки:

5
августа

BulkLoader загрузка xml


БулкЛоадер — это библиотека для загрузки любого контента написаная на AS3.0.

Возникла трудность при загрузке XML, не с прямой ссылки http:\\example.ru\managers.xml, а с адреса вот такого вида http:\\example.ru\managers\?xml. После загрузки:

private function onCompleteHandler(evt:ProgressEvent):void {
    var textObj : XML = _bulkLoader.getXML("regionXml");
    trace(textObj);
    _bulkLoader.clear();
}

вылетает ошибка:

[BulkLoader] Failed to get content with url: 'regionXml'as type: [class XML].

Необходимо просто забрать данные как обычный текст, далее его отпарсить в XML:

var textObj : Object = _bulkLoader.getText("regionXml");
regionVO.mXML = new XML(textObj);

Или добавить тип в параметрах загрузки:

// returning a simple text
bulkInstance.add("http://mysite.com/top-ten.php", {type:"text"});

// returning a xml file
bulkInstance.add("http://mysite.com/top-ten.php", {type:"xml"});

// returning a jpeg image:
bulkInstance.add("http://mysite.com/top-ten.php", {type:"image"});
13
октября

График пифов и котировок


Демонстрация графика. Выбирайте тот период который написан в скобках у названия тикера.

Задача. Сделать простенький график пифов и котировок для инвестиционно-финансовой компании «Еврогрин».

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

Единственное что я хочу показать – это функцию которая вычисляет позицию текущей цены на графике относительно масштаба.

/**
* get prise to axis y
* @param	targetPrice – текущая цена
* @param	defMaxPrice – максимальная цена
* @param	defMinPrice – минимальная цена
* @param	axisYsize - высота оси Y
* @return
*/
public function priceToAxisY(targetPrice:Number, defMaxPrice:Number,
                     defMinPrice:Number, axisYsize :Number):Number {
     var dividend:Number = (axisYsize * (targetPrice - defMinPrice));
     var divisor:Number = defMaxPrice - defMinPrice;
     return axisYsize - (dividend / divisor);
}

Остальное это муторная отрисовка всех данных.

Данная работа была сделана на период работы в студии Ample.

Rss Feed Tweeter button Facebook button