AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 26.09.2012, 12:11   #1  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,275 / 3476 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Удобство чтения кода - залог и определенная гарантия его работоспособности
Сообщения выделены из темы добавить поле в dialog класса //oip

Мысль интересная, но обычно все пытаются облегчить написание кода или процесс его вливания в общее приложение, но никто обычно не задумывается про удобство чтения кода (тут конечно нет, но когда макросами заменяют целые выражения типа метода find или еще как-то - то вопрос возникает).

А между прочим - удобство чтения кода - залог и определенная гарантия его работоспособности.
__________________
Возможно сделать все. Вопрос времени
За это сообщение автора поблагодарили: mazzy (2).
Старый 26.09.2012, 12:59   #2  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Мысль интересная, но обычно все пытаются облегчить написание кода или процесс его вливания в общее приложение, но никто обычно не задумывается про удобство чтения кода (тут конечно нет, но когда макросами заменяют целые выражения типа метода find или еще как-то - то вопрос возникает).

А между прочим - удобство чтения кода - залог и определенная гарантия его работоспособности.
Ага, я когда-то давно сопровождал вот примерно такой код (все на макросах, 1000+строк в методе) Получил много незабываемого удовольствия при модификации и отладке.

X++:
...
    #localmacro.attrFilter
        %1
    #endMacro
...
   #localmacro.table
        tableMapping=new IntegrTableMapping_Master(tableNum(#tableName), '%1');
        ret.add(tableMapping,'%2');
    #endmacro

    #localmacro.field
        tableMapping.add(
            new IntegrFieldMapping(
                #attrFilter(IntegrTableFieldAttribute::construct(
                    tableNum(#tableName), fieldNum(#tableName, %1)
                ))
            )
        );
    #endmacro

    #localmacro.GUIDField
        tableMapping.add(
            new IntegrFieldMapping_Guid(
                #attrFilter(IntegrTableFieldAttribute::construct(
                    tableNum(#tableName), fieldNum(#tableName, %1)
                ))
                , tableNum(%2), fieldNum(%2, %3) #ifnot.empty(%4), %4 #endif
            )
        );
    #endmacro
// ...
// еще десяток подобных макросов на все случаи жизни, но зато дальше весь код был "простой и удобный" :)
// ...
    #define.tableName(InventJournalTable)

    #table(inventJournalTable)
    #field(GUID)
    #field(journalId)
    #field(JournalType)
    #field(JournalNameId)
    #field(JournalDate)
    #GUIDField(fromInventLocation, InventLocation, inventLocationID)
    #GUIDField(toInventLocation,  InventLocation, inventLocationID)
    #method(department)
//...
P.S. Кстати, автор кода - действительно ОЧЕНЬ сильный программист. Прошу его на меня не обижаться.
__________________
С уважением,
Олег.
За это сообщение автора поблагодарили: BOAL (2), sukhanchik (2), lev (2), ViV (1).
Старый 26.09.2012, 15:16   #3  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от oip Посмотреть сообщение
Кстати, автор кода - действительно ОЧЕНЬ сильный программист. Прошу его на меня не обижаться.
не обижусь, если ты расскажешь про конкретные проблемы в понимании и отладке. Насколько я помню, я старался упаковать в макросы только то дублирование, которое плохо записывается в методы либо которое можно преодолеть только метапрограммированием с нарушением статической типизации. Заметь, что в приведенном оде внутри макроса и так особо не отладишься, так как посмотреть на промежуточные результаты внутри выражения не получается.

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

В следующий раз подумаю о кодогенерации с сохранением результата в виде исходников.
Старый 26.09.2012, 15:27   #4  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,275 / 3476 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от belugin Посмотреть сообщение
но зато код было легко модифицировать.
Тут такая ситуация. Главная проблема любой замены кода макросом является тот факт, что это сделано не повсеместно в системе. Не секрет, что чем больше разных "стилей" программирования встречается - тем сложнее читать код.
Т.е. приходит новый человек, строит перекрестные ссылки и видит .... такую конструкцию с макросами. Как минимум - ему к этой конструкции привыкать придется и к идеологии, которую заложил автор. Причем - далеко не факт, что:
- автор везде ей следовал
- автор переписал (как минимум) весь код в окрестностях исследуемого кода, чтобы глаз "наметался" на использование макросов.

Кто против использования макросов? Я против? Я только за - но при этом за принцип - "пусть безобразно, но единообразно". Пусть автоматизация написания кода будет заключаться в том, что после написания макросов - работает лексер на Х++. Но после чтения кода - у нового специалиста (который может быть совсем не новым, но просто "свежепришедшем") будет возможность читать привычный код, написанный боле-менее едином стиле. И отладчик будет стоять на строке кода, какая бы она не была, а не понятно на чем в случае макроса (согласен на допилку отладчика )
__________________
Возможно сделать все. Вопрос времени
Старый 26.09.2012, 15:30   #5  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Т.е. приходит новый человек, строит перекрестные ссылки и видит .... такую конструкцию с макросами. Как минимум - ему к этой конструкции привыкать придется и к идеологии, которую заложил автор. Причем - далеко не факт, что:
- автор везде ей следовал
- автор переписал (как минимум) весь код в окрестностях исследуемого кода, чтобы глаз "наметался" на использование макросов.
Любой код несет в себе что-то новое, вопрос в том, насколько долго принимать это новое. В описанном случае макросы маленькие а классы большие. Почему изучить малеьнике макросы эта проблема, а большие классы - нет?
Старый 26.09.2012, 15:37   #6  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,275 / 3476 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от belugin Посмотреть сообщение
Почему изучить малеьнике макросы эта проблема, а большие классы - нет?
А какую фразу проще прочитать:
"Вч. я н. чит. аксф." или "Вчера я начал читать аксфорум"?
Та, которая короткая, или та, которая длинная? А теперь представим себе книгу (код подобен книге). Если все предложения в книге представлены в сокращенном виде и, соответственно, в полном.
Те, кто привык к сокращениям / аббревиатурам (н = начать, Вч = вчера) - уже совершенно спокойно могут читать книгу. А остальные нет.

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

Опять-таки - вопрос отладки. В тех случаях - когда замена макросом усложняет процесс отладки (=проверки орфографии) - очень сложно отлаживать
__________________
Возможно сделать все. Вопрос времени

Последний раз редактировалось sukhanchik; 26.09.2012 в 15:39.
За это сообщение автора поблагодарили: macklakov (2).
Старый 26.09.2012, 15:43   #7  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
При всем моем уважении, сам факт наличия метода с 1000+ строк - это уже "удовольствие для прочтения"....

З.Ы. а вообще конечно что бы понять идею, которую предполагал разработчик, и причины, по которым было так сделано, нужно посмотреть целиком метод (а лучше весь объект, где написан этот код).
Очень похоже, что просто много раз выполняется инициализация одного и того же объекта, и что бы много раз не писать один и тот же код, были использованы макросы...
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 26.09.2012, 15:48   #8  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,275 / 3476 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от lev Посмотреть сообщение
Очень похоже, что просто много раз выполняется инициализация одного и того же объекта, и что бы много раз не писать один и тот же код, были использованы макросы...
Т.е. это оптимизация работы программиста путем экономии времени на написании за счет времени на изучение .
На самом деле - многие вещи вообще можно делать не макросами, а методами. Если код нужно "копипастить без изменений" - то стоит задуматься о выделении этого кода в отдельный метод.

Помнится на одном проекте один программист (не буду его называть) все цвета делал не в виде набора макросов (хотя это вообще константы) - а в виде специального класса со статическими методами. Очень удобно было при разработке было выбирать из списка.
__________________
Возможно сделать все. Вопрос времени
Старый 26.09.2012, 15:50   #9  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от belugin Посмотреть сообщение
не обижусь, если ты расскажешь про конкретные проблемы в понимании и отладке.
Мы с тобой похожий вопрос уже обсуждали пять лет назад. Там моя (да и твоя) точка зрения описана, с тех пор не поменялась.
Вернуть this из класса

Ты красиво макросами запрограммировал механизм интеграции. Добавить новую таблицу в механизм - да, просто и удобно. А вот поменять при необходимости сам "движок"... Я видел, как каждый новый разработчик на проекте тратил время чтобы понять, что тут и как работает. Брейкпоинты и перекрестные ссылки - тоже были проблемой. И точно помню, что после того, как алгоритм интеграции немного поменялся, модифицировать его было совсем не хорошо. Не, я конечно допускаю, что мне тогда просто квалификации не хватало (а это было 6+ лет назад), чтобы быстро разобраться, но мне и сейчас не нравится разбираться в способе написания кода, а не в самом коде. Я хочу чтобы код в системе был по возможности написан в едином стиле.

lev, 1000+ строк - это по большей части перечисление таблиц и полей для выгрузки.

P.S. Наверное зря я все это начал. Максим, извини.
__________________
С уважением,
Олег.
Старый 26.09.2012, 15:53   #10  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
На самом деле - многие вещи вообще можно делать не макросами, а методами. Если код нужно "копипастить без изменений" - то стоит задуматься о выделении этого кода в отдельный метод.

Помнится на одном проекте один программист (не буду его называть) все цвета делал не в виде набора макросов (хотя это вообще константы) - а в виде специального класса со статическими методами. Очень удобно было при разработке было выбирать из списка.
абсолютно согласен!
потому и написал что само наличие метода в 1000+ строк уже странно
но судить о коде не видя всей картины, сложно

З.Ы. какой то оффтоп уже для данной темы, сорри
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 26.09.2012, 16:14   #11  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от oip Посмотреть сообщение
Ты красиво макросами запрограммировал механизм интеграции.
Макросами, насколько я помню, был сделан только один меппинг между таблицами аксапты и таблицами промежуточной базы.

Цитата:
Сообщение от oip Посмотреть сообщение
Добавить новую таблицу в механизм - да, просто и удобно. А вот поменять при необходимости сам "движок"... Я видел, как каждый новый разработчик на проекте тратил время чтобы понять, что тут и как работает. Брейкпоинты и перекрестные ссылки - тоже были проблемой.
Тут хотелось бы примера, если помнишь. По идее перерестные ссылки должны работать.

Цитата:
И точно помню, что после того, как алгоритм интеграции немного поменялся, модифицировать его было совсем не хорошо.
Цитата:

Было ли это из за макросов или из-за классов?
Какое изменение и почему не влезло?
Не, я конечно допускаю, что мне тогда просто квалификации не хватало (а это было 5+ лет назад), чтобы быстро разобраться, но мне и сейчас не нравится разбираться в способе написания кода, а не в самом коде.
Код это и есть способ его написания. Вводя новую функцию ты тоже в какой-то мере вводишь способ написания кода. Библиотека это тоже язык.
Старый 26.09.2012, 16:34   #12  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от belugin Посмотреть сообщение
Макросами, насколько я помню, был сделан только один меппинг между таблицами аксапты и таблицами промежуточной базы.
Если не лезть в детали, то да, только маппинг.

Цитата:
Сообщение от belugin Посмотреть сообщение
Тут хотелось бы примера, если помнишь. По идее перекрестные ссылки должны работать.
Уже не помню. Очень уж давно это было.

Цитата:
Сообщение от belugin Посмотреть сообщение
Код это и есть способ его написания. Вводя новую функцию ты тоже в какой-то мере вводишь способ написания кода. Библиотека это тоже язык.
Нет, способ написания кода - это нечто другое. В теме "Вернуть this из класса" это как раз и обсуждалось. Мне по-прежнему кажется, что задача была проще, чем выбранный способ реализации. Но может и правда рано мне тогда было твой код читать.

Может ну его, это обсуждение? А то о чем речь до конца понимаем только мы с тобой. Я уже сто раз пожалел, что начал.
__________________
С уважением,
Олег.
Старый 26.09.2012, 18:06   #13  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от oip Посмотреть сообщение
Нет, способ написания кода - это нечто другое. В теме "Вернуть this из класса" это как раз и обсуждалось.
По-моему, это простой и широкоизвестный за пределами мира аксапты прием под названием FluentInterface . Вопрос в том, выиграем ли мы или проиграем если будем тажить в аксапту удобные штуки снаружи.

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

Цитата:
Мне по-прежнему кажется, что задача была проще, чем выбранный способ реализации. Но может и правда рано мне тогда было твой код читать.
Простота понятие относительное. Для меня простота, это когда категории каторыми я см, кстати Mappers VS Packers) [/URL] на код.
Ну мне и самому интересно, что из этого всего вылилось. И были ли проблемы именно в макросах.

Цитата:
Может ну его, это обсуждение? А то о чем речь до конца понимаем только мы с тобой. Я уже сто раз пожалел, что начал.
Ну, если нет подробностей, то можно и закруглиться.
Старый 26.09.2012, 19:20   #14  
EVGL is offline
EVGL
Banned
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,445 / 3001 (0) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
Цитата:
Сообщение от belugin Посмотреть сообщение
Ну, если нет подробностей, то можно и закруглиться.
Да нет, просто покайтесь, посыпьте голову пеплом, и все отстанут.
За это сообщение автора поблагодарили: BOAL (2).
Старый 27.09.2012, 21:44   #15  
BOAL is offline
BOAL
Участник
Аватар для BOAL
MCBMSS
Злыдни
1C
Лучший по профессии 2015
 
619 / 453 (17) +++++++
Регистрация: 28.04.2003
Адрес: Москва
Код должен быть читабельным - это факт. Причем залог его читабельности в соблюдении принятых норм (для АХ стиля и беспрактиса).
Излишние новаторства (привычки других языков, пусть даже оч удобные автору и даже в чем-то инновационо крутые) - зло. Так как код потом ведут другие люди и заканчивается все одинаково - если код "мутный", а модифицировать его нужно, то код такой трут, хоть он может и не виноват и даже несет в себе зачатки ИИ и пишет сам себя, когда никто не видит.

Так что, тут получается "лучшее - враг хорошего" во всех красе

Исключение, если такой код работает годами и не требует модификации вообще - сам пользуюсь 10 лет пачкой классов такого уникума (известного тут тоже ), но за эти годы ни разу их не модифицировал - тк было не нужно, всего хватало на уровне методов. Но и код там был читабельный и по ООП, просто не нужно было туда лазить и все - инкапсуляция, однако.
При этом с точки зрения беспрактис это было неверно - тк была пачка методов и даже классов, которые нигде не использовались (и некоторые другие крутые разработчики пытались их потереть по заветам БестПрактиса), но спустя годы код надобился и он сразу был.

Ведь можно вообще дойти до внешних утилит разработки в АХ, где оч удобно все делается, на выходе пишется код в 1 строку или с шифрованием (заодно защита). А тулзы потом не даются и теряются...

Ну или .ДЛЛ делать, к чему АХ2012 стала склонна...
Х++ кодеру чистому в АХ уже ловить нечего - нужно быть или толпой или человеко-параходом во всем.
(или забить на кодинг и таки уйти в консалтинг и дальше)
За это сообщение автора поблагодарили: AlGol (2).
Старый 28.09.2012, 09:41   #16  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
>>>если код "мутный", а модифицировать его нужно, то код такой трут

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

По мне, так код мутный, когда есть три куска котогрые на первый взгляд не отличаются, а там на самом деле в одном плюс в другом минус, а в третьем поле пропущено (причем это и есть ошибка, так как при обновлении первых двух кусков забыли обносить третий). У меня раз в нескольо месяцев посещает мысль, что неплохо бы сделать плагин, который по двум выделенным кускам кода показывает, чем же они различаются все таки.
Старый 28.09.2012, 10:11   #17  
driller is offline
driller
Сам.AX
Аватар для driller
Самостоятельные клиенты AX
SAP
 
78 / 54 (2) ++++
Регистрация: 11.04.2007
Адрес: Санк-Петербург
По поводу поиска отличия в исходниках, пробовали Araxis Merge?
Если да, то чем он не устроил?
__________________
"Считать метафору доказательством, поток праздных слов источником истины, а себя оракулом - это заблуждение, свойственное всем нам."
Поль Валери
Старый 28.09.2012, 10:15   #18  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от driller Посмотреть сообщение
По поводу поиска отличия в исходниках, пробовали Araxis Merge?
Если да, то чем он не устроил?
Еще http://winmerge.org/

Ну я имел ввиду чтобы вместо

- создать два файла
- добавить туда два уска кода
- вызвать мёрож

просто выделить два куска и вызвать пункт меню
Старый 30.09.2012, 21:58   #19  
imir is offline
imir
Участник
 
159 / 161 (6) ++++++
Регистрация: 28.05.2010
А я против макросов, и всем их запрещаю, просто потому что отлаживать неудобно, есть разница между просто программированием и бизнес-программированием, в аксе нет понятия "это мой код", он должен читаться как книга.
За это сообщение автора поблагодарили: macklakov (3), lev (2), oip (1).
Старый 01.10.2012, 07:37   #20  
pitersky is offline
pitersky
северный Будда
Аватар для pitersky
Ex AND Project
Соотечественники
 
1,486 / 408 (16) +++++++
Регистрация: 26.09.2007
Адрес: Солнечная система
Цитата:
Сообщение от imir Посмотреть сообщение
А я против макросов, и всем их запрещаю, просто потому что отлаживать неудобно, есть разница между просто программированием и бизнес-программированием, в аксе нет понятия "это мой код", он должен читаться как книга.
не знаю. мне лично #InventDimJoin читать намного удобнее, чем многоэтажный прямой джойн инвентдима. особенно когда он стопиццот раз повторяется в разных местах.
нужно соблюдать принцип разумной достаточности, а не бросаться в крайности
__________________
С уважением,
Вячеслав
За это сообщение автора поблагодарили: lev (2).
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
axforum blogs: О заполнении Наименования и Кода номенклатуры в печатной форме Накладной (Ax2009 ru7) Blog bot DAX Blogs 0 07.06.2011 09:11
Помощь в построении кода по присоединению COM объектов в методы класса ZornFire DAX: Программирование 8 06.06.2011 21:40
Получение из поля Map кода поля реальной таблицы, к ней привязанной (Mappings) vey DAX: Функционал 5 16.03.2005 11:16
проблема с настройкой штрихового кода Nic DAX: Функционал 4 27.12.2004 09:04
Использование штрихового кода (barcode) в Аксапта Pavlo AKA Panok DAX: Функционал 9 17.10.2003 15:13

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 15:15.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.