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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 21.07.2009, 18:56   #1  
ski is offline
ski
Участник
 
35 / 12 (1) ++
Регистрация: 27.05.2009
? Как лучше вносить изменения в чужой класс
Есть необходимость доработать ранее созданый отчет. Как лучше: править класс, создавая новые методы и исползовать их или лучше вставлять условные операвторы (как в примере)?
X++:
void Function()
{
     // чужой код
     // ...
     if ( Report.Type == ReportType::MyType)
     {
           // мой длинный код ...
     } 
     else 
     {
           // оставляю чужой код 
           // ....
     }
}
Старый 21.07.2009, 19:37   #2  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Если старый код точно никому больше не нужен, то лучше сразу удаляйте (сохраните где-нить в архиве на всякий пожарный), а то потом завязнете в захламленном всяким ненужным кодом и коментариями болоте.

Если же нужен, то лучше всего сделать иерархию классов, чем цепочку if-ов, я думаю...
__________________
Zhirenkov Vitaly
За это сообщение автора поблагодарили: ski (1).
Старый 22.07.2009, 00:09   #3  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от ZVV Посмотреть сообщение
сохраните где-нить в архиве на всякий пожарный
Начиная с Ax4 можно использовать контроль версий.


http://channel9.msdn.com/posts/benri...rsion-Control/
http://channel9.msdn.com/posts/mfp/V...rol-in-MorphX/

про расширение функционала см http://channel9.msdn.com/posts/mfp/D...ustomizations/
Старый 23.07.2009, 18:29   #4  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
647 / 350 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Наиболее оптимальный и действенный вариант - комментирование своих модификаций таким кодом:
X++:
//ins > NAME, FD-005, 01.01.2009
 	//вставленный код
//ins < NAME, FD-005, 01.01.2009

//del > NAME, FD-005, 01.01.2009
//… 	//удаленный код
//del < NAME, FD-005, 01.01.2009

//chg > NAME, FD-005, 01.01.2009
 	//вставленный код
//chg <---> NAME, FD-005, 01.01.2009
//… 	//удаленный код
//chg < NAME, FD-005, 01.01.2009
Вы всегда будете знать, что, кто и когда писал. А также неоценимую помощь вы почувствуете при переносе модификаций.
За это сообщение автора поблагодарили: ski (1).
Старый 23.07.2009, 22:31   #5  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,305 / 3538 (124) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от dech Посмотреть сообщение
Наиболее оптимальный и действенный вариант - комментирование своих модификаций таким кодом
...
Вы всегда будете знать, что, кто и когда писал. А также неоценимую помощь вы почувствуете при переносе модификаций.
А когда таких "модификаций" будет пару-тройку раз в одном месте кода - то у Вас комментариев будет больше чем кода и разобраться в нем совершенно новому человеку будет уже нереально. Первое желание, которое возникнет - стереть все комментарии .

Поэтому тут - палка о двух концах. На одной чаше весов - разовое удобство переноса модификации для себя, на другой многократные попытки исследования кода для других.
Поэтому - как разработчик - могу посоветовать НЕ комментировать свои модификации, стирать старый код и писать свой поверх. Единственный комментарий, который можно оставить - это у класса/формы/отчета в ClassDeclaration. Остальное - вполне можно видеть путем сравнения слоев (в крайнем случае сравнения со старым слоем). Не надо забывать, что за комментариями в коде надо "ухаживать", чтобы они не устаревали и оставались актуальными.

В идеале я для себя вижу следующий вариант - если "врезка" нового кода "условно-мала" (условно-мала - это сколько?) по отношению к остальному коду в методе, то ее нужно снабдить комментариями. В противном случае - все надо стереть и оставить только одну свою метку.
Все это нужно хранить ДО переноса модификации. После переноса - жестко стирать и удалять.

Посмотрим на наш любимый Микрософт. Сравните кол-во комментариев в коде в 3-шке и в 4-ке - В 4-ке много потерли комментариев.
__________________
Возможно сделать все. Вопрос времени
Старый 24.07.2009, 08:21   #6  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,731 / 406 (17) +++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
А когда таких "модификаций" будет пару-тройку раз в одном месте кода - то у Вас комментариев будет больше чем кода и разобраться в нем совершенно новому человеку будет уже нереально. Первое желание, которое возникнет - стереть все комментарии .
в таких случаях можно переименовать метод в old_name(), и создать новый метод name(), куда перенести только код, а в коментариях к нему перечислить все модификации, например.

Последний раз редактировалось ice; 24.07.2009 в 08:24.
Старый 24.07.2009, 09:13   #7  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
647 / 350 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
А когда таких "модификаций" будет пару-тройку раз в одном месте кода - то у Вас комментариев будет больше чем кода и разобраться в нем совершенно новому человеку будет уже нереально. Первое желание, которое возникнет - стереть все комментарии .

Поэтому тут - палка о двух концах. На одной чаше весов - разовое удобство переноса модификации для себя, на другой многократные попытки исследования кода для других.
Поэтому - как разработчик - могу посоветовать НЕ комментировать свои модификации, стирать старый код и писать свой поверх. Единственный комментарий, который можно оставить - это у класса/формы/отчета в ClassDeclaration. Остальное - вполне можно видеть путем сравнения слоев (в крайнем случае сравнения со старым слоем). Не надо забывать, что за комментариями в коде надо "ухаживать", чтобы они не устаревали и оставались актуальными.

В идеале я для себя вижу следующий вариант - если "врезка" нового кода "условно-мала" (условно-мала - это сколько?) по отношению к остальному коду в методе, то ее нужно снабдить комментариями. В противном случае - все надо стереть и оставить только одну свою метку.
Все это нужно хранить ДО переноса модификации. После переноса - жестко стирать и удалять.

Посмотрим на наш любимый Микрософт. Сравните кол-во комментариев в коде в 3-шке и в 4-ке - В 4-ке много потерли комментариев.
Позвольте не согласиться
Вам никогда не приходилось откатывать назад модификации? Совместно с ведением архитектурного дизайна проекта, в котором учитываются изменения во всех затронутых объектах АОТ это получается действительно самое оптимальное решение. И поверьте, чужому человеку гораздо легче будет взглянуть на номер модифа в комменте и почитать ФД (ТЗ), чтобы понять, чего тут написано до него. А также, очень часто бывают случаи, когда по прошествии пользовательского тестирования нужно переносить в боевую базу объекты, в которых есть код из других модифов, что-то нужно переносить, что-то нет. Тут я задам скромный вопрос: Вы точно запомните, что нужно переносить?
__________________
// no comments
Старый 24.07.2009, 09:14   #8  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Посмотрим на наш любимый Микрософт. Сравните кол-во комментариев в коде в 3-шке и в 4-ке - В 4-ке много потерли комментариев.

В пятерке комментариев опять много и они носят не технический характер, а по существу. К тому же сделали XML документацию.
Старый 24.07.2009, 09:28   #9  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,305 / 3538 (124) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от dech Посмотреть сообщение
Позвольте не согласиться
Вам никогда не приходилось откатывать назад модификации? Совместно с ведением архитектурного дизайна проекта, в котором учитываются изменения во всех затронутых объектах АОТ это получается действительно самое оптимальное решение. И поверьте, чужому человеку гораздо легче будет взглянуть на номер модифа в комменте и почитать ФД (ТЗ), чтобы понять, чего тут написано до него. А также, очень часто бывают случаи, когда по прошествии пользовательского тестирования нужно переносить в боевую базу объекты, в которых есть код из других модифов, что-то нужно переносить, что-то нет. Тут я задам скромный вопрос: Вы точно запомните, что нужно переносить?
Ну я ж говорю - что это палка о двух концах - забота о себе любимом (откат модификаций и проч) и забота о будущих ковырятелях кода (когда что-то не работает)

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

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

А вот в боевую базу надо не объекты переносить - а накатывать целиком приложение, предварительно откомпилированное, вылизанное и оттестированное.
__________________
Возможно сделать все. Вопрос времени
Старый 24.07.2009, 09:30   #10  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,305 / 3538 (124) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от belugin Посмотреть сообщение
В пятерке комментариев опять много и они носят не технический характер, а по существу. К тому же сделали XML документацию.
Просто я опять повторюсь - за комментариями надо "ухаживать". Строчку в код добавили, логика поменялась и комментарий устарел. Нет ничего луше грамотного комментария и нет ничего хуже комментария, несоответствующего действительности
__________________
Возможно сделать все. Вопрос времени
Старый 24.07.2009, 09:31   #11  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,305 / 3538 (124) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Ну вот - начал холивар на тему "Как надо вести разработку"
__________________
Возможно сделать все. Вопрос времени
Старый 24.07.2009, 11:51   #12  
Ivanhoe is offline
Ivanhoe
Участник
Аватар для Ivanhoe
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
4,143 / 2156 (80) +++++++++
Регистрация: 29.09.2005
Адрес: Санкт-Петербург
При разработке разными людьми, предлагаете также удалять все старое? Ну-ну )

У нас:
1. Все модификации ведутся в отдельной табличке - в них описание / задание на разработку. К ним же прицеплены проекты.
2. Все модификации кода комментируются с обязательным указанием автора, даты и кода проекта.

Если в очередной раз программист вносит изменения и видит, что комменты устарели совсем / их больше кода / другие причины, - вносится единый комментарий о переработке с указанием всех проектов, которые меняли код, код переписывается (читай удаляется все лишнее).

А по теме - согласен со вторым ответом (Как лучше вносить изменения в чужой класс).
__________________
Ivanhoe as is..
Старый 24.07.2009, 15:14   #13  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,305 / 3538 (124) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Во... так же сами подтвердили мою мысль
Цитата:
Сообщение от Ivanhoe Посмотреть сообщение
При разработке разными людьми, предлагаете также удалять все старое? Ну-ну )
....
Если в очередной раз программист вносит изменения и видит, что комменты устарели совсем / их больше кода / другие причины, - вносится единый комментарий о переработке с указанием всех проектов, которые меняли код, код переписывается (читай удаляется все лишнее).
Выделил Вашу цитату. Еще раз повторяю свою мысль - что идея комментировать что добавилось что удалилось - хороша до того момента пока
Цитата:
Сообщение от Ivanhoe Посмотреть сообщение
Если в очередной раз программист вносит изменения и видит, что комменты устарели совсем / их больше кода / другие причины
Только этот момент при таком комментировании наступает сразу же у второго программиста, который редактирует код, написанный первым программистом.

Я ж все пытаюсь донести мысль (уж извиняюсь - если не так выражался) - что конечно хорошо - когда наглядно понятно откуда растут ноги. Только эта наглядность слишком быстро ломается и приходится все стирать и заменять единым комментом (что далеко не всегда соблюдается теми, кто об этом не думает). От которого ясность тоже может не прибавиться - но это уже не об этом.
В результате, уже код на рабочей базе может пестрить кол-вом комментариев в количестве большем чем самих строк кода. Вот это на мой взгляд недопустимо. А достигать этой цели можно двумя путями - это писать много комментов, а потом перед выкладкой на рабочее приложение - их стирать, и, наконец, минимизировать кол-во комментов изначально.
Поэтому - в моем наверное, даже излишне категоричном первом сообщении
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
могу посоветовать НЕ комментировать свои модификации, стирать старый код и писать свой поверх. Единственный комментарий, который можно оставить - это у класса/формы/отчета в ClassDeclaration
мне хотелось сделать упор в первую очередь на то, что чем меньше лишних "букав" тем лучше читаемость кода.

Все конечно очень субъективно и коммент комменту рознь. Но надеюсь - идею свою донес
__________________
Возможно сделать все. Вопрос времени
Старый 18.08.2009, 10:15   #14  
mit is offline
mit
Участник
Аватар для mit
 
386 / 36 (2) +++
Регистрация: 15.01.2003
Адрес: Moscow
Цитата:
Сообщение от ZVV Посмотреть сообщение
Если старый код точно никому больше не нужен
каковы критерии нужности и точности?
Цитата:
Сообщение от ZVV Посмотреть сообщение
(сохраните где-нить в архиве на всякий пожарный)
интересно узнать как у Вас спроектировано и как организовано администрирование ресурса с архивами?
Цитата:
Сообщение от ZVV Посмотреть сообщение
то лучше всего сделать иерархию классов, чем цепочку if-ов, я думаю...
прошу пояснить что такое иерархия классов

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
А когда таких "модификаций" будет пару-тройку раз в одном месте кода - то у Вас комментариев будет больше чем кода и разобраться в нем совершенно новому человеку будет уже нереально.
смотря что комментировать. если мы переводим с х++ на русский или английский что тут делается это перебор. если мы метим то, что добавили с целью дальнейшего сопровождения, не понимаю в чем проблема будет у нового человека? наймите более толкового нового человека.
когда комментариев будет больше чем кода
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Первое желание, которое возникнет - стереть все комментарии.
а еще кучу ненужных классов, отчетов.

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Поэтому тут - палка о двух концах. На одной чаше весов - разовое удобство переноса модификации для себя, на другой многократные попытки исследования кода для других.
чесно говоря, второго конца палки не увидел. оба мотива в одну чашу попадают.

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Поэтому - как разработчик - могу посоветовать НЕ комментировать свои модификации, стирать старый код и писать свой поверх. Единственный комментарий, который можно оставить - это у класса/формы/отчета в ClassDeclaration. Остальное - вполне можно видеть путем сравнения слоев (в крайнем случае сравнения со старым слоем).
ну ну. разработчик разработчику рознь. если разработка ведется поставщиком (типовое решение) или консультантом (вертикально-горизонтальное решение), удаление комментариев рекомендовано (technet) после завершения разработки. если модификации ведутся пользователем системы самостоятельно, то процесс модификации перманентен, в этом случае даже релиз выпустить сложно. и имею ввиду именно этот случай.

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
В противном случае - все надо стереть и оставить только одну свою метку.
«Преждевременная оптимизация – корень всех зол», – Дональд Кнут (Donald Knuth).

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Не надо забывать, что за комментариями в коде надо "ухаживать", чтобы они не устаревали и оставались актуальными.
поливать и подсыпать песочек извините, но ассоциации. можно немного уточню цитатой с майкрософт?
Цитата:
Сообщение от [url
http://msdn.microsoft.com]Хорошим[/url] стилем программирования считается начинать все процедуры с краткого комментария, описывающего функциональные характеристики процедуры (то, что она делает). Это необходимо для вашего собственного удобства и удобства того, кто читает этот код. Следует отличать детали реализации (как процедура работает) от комментариев, описывающих функциональные характеристики. Если в комментарий включены детали реализации, их следует обновлять при редактировании кода.
таким образом, комментарии в начале метода (заголовке класса) полезны, а поясняющие код полезны разве что при обучении, или чего то очень специфичного.

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Посмотрим на наш любимый Микрософт. Сравните кол-во комментариев в коде в 3-шке и в 4-ке - В 4-ке много потерли комментариев.
а не показатель, так как написано выше - цели разные.

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
мне хотелось сделать упор в первую очередь на то, что чем меньше лишних "букав" тем лучше читаемость кода.
цель не превратить код в бульварное чтиво, а соблюсти работоспособность при переносе с версии на версию. возможно, при накате следующего сервис пака Ваша модификация не нужна будет. без комментария проанализировать сложнее в плане временных затрат.


используем следующий вид комментирования

UserId = текущий пользователь
Date = текущая дата
Time = текущее время
CompanyId = код компании (префикс наших объектов)
VerId = версия и сп под которую делалась модификация
ProjectId = код проекта, под которую делались изменения

для ProjectId дополнительно ведется общий реестр с описанием проектов.
проект кодируется так: UserId_YYMMDD_[КраткоеНазвание]

вся строка комментария формируется автоматом (подправили для этих целей класс EditorScripts), при выборе в контекстном меню редактора соответствующей команды.
при модификации кода, как правило, если весь блок помещается на экране, то так:
X++:
  // UserId on Date at Time, CompanyId VerId ProjectId -->
  //  e.gotoCol(1);
      e.gotoCol(2);
  // UserId on Date at Time, CompanyId VerId ProjectId <--
допускается для одной-двух сток так:
X++:
  //  e.gotoCol(1); // UserId on Date at Time, CompanyId VerId ProjectId -->
      e.gotoCol(2); // UserId on Date at Time, CompanyId VerId ProjectId <--
так "удаление" строки:
X++:
  // UserId on Date at Time, CompanyId VerId ProjectId -->  e.gotoCol(1);
или, если просто вставить, то так:
X++:
      e.gotoCol(2); // UserId on Date at Time, CompanyId VerId ProjectId <--
при модификации кода, если весь блок помещается на экране, но меняется больше половины, или пестрит врезками, или комментариев столько, что смысл или логика метода сложено улавливается, то старый код комментируется и опускается вниз, новый пишется в начале метода. выглядит так:
X++:
  // Restruct by UserId on Date at Time, CompanyId VerId ProjectId
  public void sendTo_printer(Editor e)
  {
      Args      a = new Args();
      Object    report;
      ;
   
      a.name(reportstr(SysPrintCode));
  ...
  // Old way
  //public void sendTo_printer(Editor e)
  //{
  //    Args      a = new Args();
  //    Object    report;
  //    ;
  //
  //    a.name(reportstr(SysPrintCode));
  ...
при создании своего метода, первая строка так:
X++:
  // Created on UserId on Date at Time, CompanyId VerId ProjectId
при создании своего объекта так же, только коммент в методе classDeclaration.

комментировать
плюсы:
1) при сборке проекта экономлю время. все модификации вижу проще. т.е. без функции сравнения. при конфликтах, могу легко понять под какой проект были модификации. вижу "свежесть" кода. т.е. обращаю внимание только на то что было изменено. взаимный контроль логики выполнения остальными программистами. проще выполнить аудит, и как следствие повышается самодисциплина программистов.
2) при переходе на новую версию. модификации проще отличить от просто старой версии базового кода (хотя на мой взгляд, вместо слова "проще", уместно использовать слово "возможно").
3) так как среда ориентирована на объекты, и один и тот же объект может наследоваться, при модификации знаю, на каком функционале "аукнется" новая модификация, и что после модификации следует протестировать.
4) и еще один субъективный плюс. так как система с очень сложной логикой, ошибка в логике может принести убытки бизнесу

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

возможно я консервативен, и в пятерке появилось средство управления версиями, но я вижу эту систему как дополнение, но не как замену вышеизложенному. дополнение хорошо тем, что позволяет на одном приложении исключить конфликты при изменения одного объекта разными людьми (в прежних версиях реализовано через блокировку объекта). Но самое главное что понравилось – это мониторинг изменения структуры объектов (например таблиц). Раньше приходилось вести учет отдельно. если разработка ведется на разных приложениях, изменения и комментарии при возвращения объекта в репозитарий будут утеряны (или разработку вести на подключенном к интернету месте)
__________________
Дом поросенка должен быть крепостью. (Наф-Наф, полн. собр. соч., т.5, стр. 286)

Последний раз редактировалось mit; 18.08.2009 в 10:18.
Теги
программирование

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Проблема с передачей контролов из формы в класс matew DAX: Программирование 0 28.04.2008 17:37
запретить вносить изменения в AOT kitty DAX: Администрирование 2 27.06.2006 07:52
траблы при выделении черным цветом и указанием слоя изменения кода... NetBus DAX: Программирование 8 14.07.2005 18:31
Сводное планирование - изменения&изменения мин. Alexm DAX: Прочие вопросы 1 05.04.2005 10:43
Русская локализация Axapta 3 ? SlavaK DAX: Администрирование 59 01.07.2003 22:38

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

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

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