
| | Если выпуск отображается некорректно, Вы можете посмотреть его на сайте | | | Здравствуйте, уважаемые читатели! ОглавлениеВ прошлых статьях (части 1, 2, 3) мы освоили инструмент для модульного тестирования программ, написанных на языке C, под названием Unity. Однако обладание отдельным инструментом и даже уверенные навыки работы с ним еще не гарантируют достижения конечной цели. Нужно уметь вписать операции, которые способен выполнять данный инструмент, в общую технологию. Само по себе модульное тестирование — нужная и важная часть процесса производства ПО. Однако наиболее полно раскрыть его потенциал позволяет технология, которая получила название «разработка, управляемая тестированием» (Test Driven Design, TDD), или в дальнейшем РУТ. Оценить что-то новое проще в сравнении со старым, привычным. Поэтому сначала вспомним, как производилась разработка до появления РУТ. Разработка, не управляемая тестированиемС названием для данного раздела у меня возникли совершенно непредвиденные затруднения. Поначалу само собой напрашивалось название «Традиционные методы разработки», но тогда логически следует, что далее я буду описывать «нетрадиционные» методы, а это слово в последнее время приобрело какой-то двусмысленный оттенок, идет ли речь о медицине, сексуальной ориентации или чем-то еще. Вариант «общепринятые методы» немногим лучше, — ведь TDD получает все большее признание и уже не является экзотикой. Чтобы не тратить драгоценное время на подобные второстепенные вопросы, я решил остановиться на непритязательно-нейтральном «Разработка, не управляемая тестированием» (РНУТ). Итак, что представляет собой РНУТ? На самом деле этот подход очень хорошо знаком всем без исключения разработчикам: код пишется, компилируется, а затем тестируется (как именно тестируется, в данный момент неважно; основной акцент делаем на последовательности действий, а именно: тестированию подвергается уже готовый, полностью написанный код). Долгое время такая последовательность казалась естественной и единственно возможной. Ведь тестирование — это по сути проверка, а проверить можно лишь то, что уже существует. Однако тестировать готовый код не всегда легко. Во-первых, не каждый код сам по себе пригоден для тестирования. Простой пример: некоторая функция (метод) получает извне (скажем, из базы данных) некоторые данные, а затем производит их обработку по сложному алгоритму с множеством ветвлений в зависимости от значений этих данных. Чтобы протестировать эту функцию, необходимо сначала заполнить базу данных тестовыми данными, поскольку в реальной БД может не оказаться необходимых для тестирования значений. Занесение таких данных в рабочую БД может оказать негативное влияние на рабочий процесс, если БД активно используется, а разворачивание специальной базы для тестирования и заполнение ее данными может оказаться достаточно трудоемким. В таких условиях отношение разработчиков к тестированию гарантированно будет негативным, даже если они и осознают реальную пользу от него. Понадобится глубокий рефакторинг кода, чтобы сделать такую функцию действительно пригодной для простого и эффективного тестирования. Во-вторых, при тестировании готового кода зачастую бывает достаточно трудно добиться полного покрытия кода тестами; особенно хлопотно тестировать код обработки ошибок, которые трудно вызвать или имитировать. Пример: в нашей системе используется запись данных на SD-карты. Есть некоторый код, который обрабатывает ошибки в случае, если запись на карту невозможна из-за ее аппаратной неисправности (дефектные ячейки). Попробуйте-ка испортить исправную карту таким образом, чтобы она выдавала именно нужную нам для тестирования ошибку (либо сделать аппаратный имитатор сбойной карты). Поскольку все это сделать в принципе можно, но достаточно трудоемко, в итоге подобные ветки кода так и остаются не протестированными должным образом, образуя потенциальную мину замедленного действия, которая рванет, когда редкое условие все-таки сработает. В-третьих, в программах нередко встречаются фрагменты незадействованного кода. Причины для этого разные. Иногда «запасливый» программист запасает функции впрок в полной уверенности, что они понадобятся в ближайшем будущем. Особенно часто такая ситуация встречается при проектировании и реализации «снизу-вверх», когда сначала пишутся вспомогательные модули, а затем основные, пользующиеся услугами вспомогательных. Некоторые из них оказываются вовсе невостребованными, другие и пригодились бы в принципе, но об их существовании уже забыли, к тому же написать их заново оказывается быстрее, чем найти в ворохе плохо оформленного кода. Иногда «мертвый» код появляется по объективным причинам, поскольку изменились требования к продукту и часть ранее реализованных функций теперь не нужна. Независимо от причин появления «мертвого» кода в программе, его наличие не способствует повышению качества продукта, поскольку распознать его не так просто, а сопровождать программу, изобилующую подобными шарадами и головоломками, становится труднее.Наконец, когда сроки сдачи проекта поджимают, слишком велик соблазн пожертвовать тестированием, сократив его объем, а то и проигнорировав вовсе, ведь клиент платит не за тесты. Поскольку планирование программных проектов — дисциплина весьма тонкая, вероятность того, что до полноценного тестирования дело не дойдет вовсе, достаточно велика. Итак, при том, что РНУТ представляется довольно логичной и понятной, ей присущ ряд недостатков, которые затрудняют последующее тестирование и не лучшим образом влияют на качество продукта. Разработка, управляемая тестированиемРазработка, управляемая тестированием (РУТ), как легко догадаться, представляет собой РНУТ, вывернутую наизнанку. При таком подходе сначала пишутся тесты и лишь потом сам код, который этим тестам удовлетворяет. РУТ поначалу удивляет и даже шокирует многих разработчиков; сама идея тестировать то, чего еще нет, кажется на первый взгляд абсурдной. Но это лишь на первый взгляд. РУТ — одна из основ так называемых «гибких» (agile) технологий разработки, популярность которых в настоящее время стремительно возрастает («гибкими» они называются из-за способности приспосабливаться к динамичным, постоянно меняющимся требованиям к изделию). «Гибкие» технологии сами по себе весьма интересны и заслуживают отдельной статьи (и даже не одной), но сейчас мы не будем отходить от основной темы. ... Полностью прочитать статью можно на нашем сайте, в разделе «Инструменты и технологии проектирования ПО». - Программирование
- Операционные системы
- Направления программирования
- Программирование :: .NET технология от и до
Распараллелил функцию в главном потоке (средствами Rx Framework, но это значения не имеет, пробовал и через BeginInvoke()): Цитата public void Start() { //... var startSession = Observable.ToAsync<string, string>(this.StartSession); startSession(credentionals.Login, credentionals.Password); //... }
Она вызывает асинхронно долгоиграющий метод, который в конце должен кинуть эвент всем, кто его слушает: Цитата private void StartSession(string login, string password) { //... this.OnStarted(EventArgs.Empty); }
Встал вопрос - как сделать так, чтоб метод this.OnStarted() вызывался в главном потоке? Не могу понять, возможно ли это вообще. Знаю, что обратная сторона Fork'а - Join, но при его помощи не выходит "слить" потоки обратно. Из многопоточности пока только освоил разделение, lock'и и ManualResetEvent's :) PS: дело в том, что подписчики на событие Started - в основном GUI-компоненты, и они вредничают, если менять их не из главного потока. Переделывать UI на безопасные BeginInvoke() - много мороки, много кода уже написано. Еще раз пересмотрел все темы про потоки - ничего подобного там нет... Я так понял, это связано больше с параллелизмом, но ведь даже за всеми фреймворками по паралеллизму стоят рядовые инструменты, значит это можно сделать стандартными средствами. - Программирование :: С/С++
Имеется небольшое приложение на WTL, используется boost::thread. При выборе директории через стандартный диалог считывается информация о файлах внутри и выводиться в список, это сделано в отдельном потоке для того, что бы был доступен GUI. Предположим мне нужно выбрать другу директорию и считывать информацию о ее файлах этим же потоком, но ведь он уже выполняется. Как мне его прервать и запустить снова с параметрами другой директории? Итак для большей наглядности приведу несколько ф-ций: По нажатию на кнопочку "FILL" вызываеться диалог "Browse for folder" Код: LRESULT CMainDlg::OnFill(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { { TCHAR szPath[MAX_PATH]; BOOL res = FALSE; LPMALLOC pMalloc; if (::SHGetMalloc(&pMalloc) == NOERROR) { BROWSEINFO bi; ::ZeroMemory(&bi,sizeof bi); bi.ulFlags = BIF_RETURNONLYFSDIRS; LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi); if (pidl != NULL) { if (::SHGetPathFromIDList(pidl,szPath)) { if (szPath) //если нажата кнопка ОК { TheThread (szPath); //вызывается отдельный поток } } } } return 0; } } вот что делает этот самый поток Код: int CMainDlg::TheThread (const CString& pth) { boost::thread my_thread(boost::bind(&CMainDlg::ReadFilesInf, this, pth)); //вызывается метод ReadFilesInf с параметром szPath return 0; } вот сам метод ReadFilesInf Код: int CMainDlg::ReadFilesInf (const CString& pth) { int userReplay; path p (pth.GetString()); /* привожу для наглядности struct FileInformation { CString fName; CString fPath; CString size; CString time; };*/ FileInformation information; EnterCriticalSection(&cs); recursive_directory_iterator end; recursive_directory_iterator it(p); while (it != end) { try { path curPath(*it); if (is_regular_file(curPath)) { CTime w_time = last_write_time(*it); CString str = w_time.Format( L"%d, %b, %Y, %H:%M" ); LPCTSTR timeCreation = str; std::wstring fileSizeStr = boost::lexical_cast<std::wstring>(file_size(curPath)); std::wstring filePathStr = boost::lexical_cast<std::wstring>(curPath); information.fName = curPath.leaf().c_str(); information.fPath = curPath.branch_path().c_str(); information.size = fileSizeStr.c_str(); information.time = timeCreation; list_.fileList_.push_back (information); //list_ это мой виртуальный список fileList_ это вектор который хранит информацию о файлах list_.SetItemCountEx(list_.fileList_.size(), LVSICF_NOINVALIDATEALL); } ++it; } catch (boost::system::system_error const& e) { if (e.code().value() != ERROR_ACCESS_DENIED) { throw; } } } LeaveCriticalSection(&cs); return 0; } П.С. Господа приношу извинения если не достаточно доступно изложил суть вопроса. - Программирование :: Delphi
Помогите пожалйуста! Я только начала изучать Delphi в институте и много еще не знаю. У меня маленькая база данных где отображены фамилия и имя в компоненте DBGrid. Есть панель DBNavigator, сделала поиск. Тут все работает, добавляет, удаляет и так далее. Вот я хочу, чтобы при нажатии на какую - либо фамилию в DBGride открывалась форма с полной информацией о данном человеке. Как мне это сделать? Вот код программы: Код: (delphi) unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, DBClient, ExtCtrls, DBCtrls, Grids, DBGrids, StdCtrls, ComCtrls; type TForm1 = class(TForm) DBNavigator1: TDBNavigator; DataSource1: TDataSource; ClientDataSet1: TClientDataSet; Edit1: TEdit; Button1: TButton; Edit2: TEdit; Label1: TLabel; Label2: TLabel; DBGrid1: TDBGrid; procedure Button1Click(Sender: TObject); procedure DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin if not ClientDataSet1.Locate( 'Фамилия;Имя', VarArrayOf([Edit1.Text,Edit2.Text]), [loCaseInsensitive, loPartialKey])then ShowMessage('Запись не найдена'); end; procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState); begin if gdFocused in State then with (Sender as TDBGrid).Canvas do begin Brush.Color := clFuchsia; FillRect(Rect); TextOut(Rect.Left, Rect.Top, Field.AsString); end; end; end. Если использовать вот такой вариант: Код: (delphi) const pathImage = 'D:\Image.jpg'; var OnLoad: boolean = true; procedure TForm2.FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean); var ScaleForm: Double; begin if OnLoad then begin if Assigned(Image1.Picture) then begin NewWidth := Image1.Picture.Width; NewHeight := Image1.Picture.Height; end; OnLoad := false; Exit; end; ScaleForm := NewWidth / NewHeight; if ScaleForm > Scale then begin NewHeight := Trunc(NewWidth / Scale); end else begin NewWidth := Trunc(Scale * NewHeight); end; end; procedure TForm2.FormCreate(Sender: TObject); begin if (FileExists(pathImage)) then Image1.Picture.LoadFromFile(pathImage); Scale := Image1.Picture.Width / Image1.Picture.Height; end; Свойства TImage; (http://s53.radikal.ru/i140/1108/16/0c1b09f0d685.jpg) То при запуске программы вид: (http://s44.radikal.ru/i106/1108/32/38c29359e143.jpg) Если попробовать прижать мышью заголовок формы и оттащить окно (можно еще так: мышку поместить в угол формы, собираясь изменить размер и при прикосновении произойдет аналогичное), то сразу станет так: (http://i050.radikal.ru/1108/bf/d09c5f28eed7.jpg) вот это как раз то, что и хотелось бы получить - именно такой вид. Некий рефреш происходит? Но каким образом сделать с самого начала подобное растяжение по всему пространству в форме? Delphi XE- Программирование :: Программирование 1С
Приветствую всех! Не пойму куда правильно вставить СГРУППИРОВАТЬ ПО ... Везде выдает ошибки: то к группе не относится то еще что то Код: Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ | РеализацияТМЗОбороты.Регистратор КАК ДокументДвижения, | РеализацияТМЗОбороты.Склад КАК Склад, | РеализацияТМЗОбороты.Номенклатура КАК Номенклатура, | РеализацияТМЗОбороты.ДоговорКонтрагента КАК ДоговорКонтрагента, | РеализацияТМЗОбороты.ДоговорКонтрагента.Владелец КАК Контрагент, | Выбор Когда (РеализацияТМЗОбороты.СуммаОборот)>0 Тогда РеализацияТМЗОбороты.СуммаОборот |иначе 0 Конец КАК Сумма, | Выбор Когда (РеализацияТМЗОбороты.СуммаОборот)< 0 Тогда РеализацияТМЗОбороты.СуммаОборот |иначе 0 Конец КАК СуммаВозвратов, | РеализацияТМЗОбороты.СуммаОборот Как СуммаСВозвратами, | РеализацияТМЗОбороты.НДСОборот КАК НДС, | РеализацияТМЗОбороты.АкцизОборот КАК Акциз, | РеализацияТМЗОбороты.СтоимостьОборот КАК Стоимость, | РеализацияТМЗОбороты.КоличествоОборот КАК Количество, | РеализацияТМЗОбороты.СуммаОборот - РеализацияТМЗОбороты.НДСОборот - РеализацияТМЗОбороты.АкцизОборот КАК СуммаБезНалогов, | РеализацияТМЗОбороты.СуммаОборот - РеализацияТМЗОбороты.НДСОборот - РеализацияТМЗОбороты.АкцизОборот - РеализацияТМЗОбороты.СтоимостьОборот КАК Профит, | (РеализацияТМЗОбороты.СуммаОборот - РеализацияТМЗОбороты.НДСОборот - РеализацияТМЗОбороты.АкцизОборот)/РеализацияТМЗОбороты.КоличествоОборот КАК Сумма1, | РеализацияТМЗОбороты.СуммаОборот/РеализацияТМЗОбороты.КоличествоОборот КАК Сумма2"; Если мИспользоватьПартии Тогда Текст = Текст + ", | РеализацияТМЗОбороты.Партия Как Партия"; КонецЕсли; Текст = Текст + " | {ВЫБРАТЬ | РеализацияТМЗОбороты.Организация.* КАК Организация, | РеализацияТМЗОбороты.СчетУчета.* КАК СчетУчета, | РеализацияТМЗОбороты.Номенклатура.* КАК Номенклатура, | РеализацияТМЗОбороты.ДоговорКонтрагента.Владелец.* КАК Контрагент, | РеализацияТМЗОбороты.ДоговорКонтрагента.* КАК ДоговорКонтрагента,"; Если мИспользоватьПартии Тогда Текст = Текст + " | РеализацияТМЗОбороты.Партия.* КАК Партия,"; КонецЕсли; Текст = Текст + " | РеализацияТМЗОбороты.Склад.* КАК Склад, | РеализацияТМЗОбороты.Период Как Период, | НачалоПериода(Период, День) КАК ПериодДень , | НачалоПериода(Период, Неделя) КАК ПериодНеделя , | НачалоПериода(Период, Декада) КАК ПериодДекада , | НачалоПериода(Период, Месяц) КАК ПериодМесяц , | НачалоПериода(Период, Квартал) КАК ПериодКвартал , | НачалоПериода(Период, Полугодие) КАК ПериодПолугодие , | НачалоПериода(Период, Год) КАК ПериодГод | //СВОЙСТВА |} |ИЗ | РегистрНакопления.РеализацияТМЗ.Обороты( | &ДатаНач, | &ДатаКон,"; Если мИспользоватьПартии Тогда Текст = Текст + " | Регистратор,{Организация.*, СчетУчета.*, ДоговорКонтрагента.*, Номенклатура.*, Склад.*, ДоговорКонтрагента.Владелец.* КАК Контрагент, Партия.*}) КАК РеализацияТМЗОбороты"; Иначе Текст = Текст + " | Регистратор,{Организация.*, СчетУчета.*, ДоговорКонтрагента.*, Номенклатура.*, Склад.*, ДоговорКонтрагента.Владелец.* КАК Контрагент}) КАК РеализацияТМЗОбороты"; КонецЕсли; Текст = Текст + " | //СОЕДИНЕНИЯ |{ГДЕ | Период.* Как Период, | Склад.*, | Организация.*, | Номенклатура.*, | СчетУчета.*, | ДоговорКонтрагента.Владелец.* КАК Контрагент, | ДоговорКонтрагента.*, | Регистратор.* КАК ДокументДвижения"; Если мИспользоватьПартии Тогда Текст = Текст + ", | Партия.*"; КонецЕсли; Текст = Текст + " | //СВОЙСТВА | //КАТЕГОРИИ |}"; Текст = Текст + " |{УПОРЯДОЧИТЬ ПО | Склад.*, | организация.*, | Номенклатура.*, | СчетУчета.*, | ДоговорКонтрагента.*, | Контрагент.*,"; Если мИспользоватьПартии Тогда Текст = Текст + " | Партия.*,"; КонецЕсли; Текст = Текст + " | Период, | ДокументДвижения.* | //СВОЙСТВА |} |ИТОГИ | СУММА(Сумма), | СУММА(СуммаВозвратов), | СУММА(СуммаСВозвратами), | СУММА(НДС), | СУММА(Акциз), | СУММА(Стоимость), | СУММА(Количество), | СУММА(СуммаБезНалогов), | СУММА(Профит), | СУММА(Сумма1), | СУММА(Сумма2) |ПО | ОБЩИЕ |{ИТОГИ ПО | Склад.*, | Организация.*, | Номенклатура.*, | СчетУчета.*, | Контрагент.*, | ДоговорКонтрагента.*, | ДокументДвижения.*,"; Если мИспользоватьПартии Тогда Текст = Текст + " | Партия.*,"; КонецЕсли; Текст = Текст + " | НачалоПериода(Период, День) КАК ПериодДень , | НачалоПериода(Период, Неделя) КАК ПериодНеделя , | НачалоПериода(Период, Декада) КАК ПериодДекада , | НачалоПериода(Период, Месяц) КАК ПериодМесяц , | НачалоПериода(Период, Квартал) КАК ПериодКвартал , | НачалоПериода(Период, Полугодие) КАК ПериодПолугодие , | НачалоПериода(Период, Год) КАК ПериодГод | //СВОЙСТВА | }"; Вот здесь делю суммы на количество(ниже отрывок из кода), оказалось так что делится все на каждое перебираемое количество, а нужно чтобы делил на суммированное количество Код: | (РеализацияТМЗОбороты.СуммаОборот - РеализацияТМЗОбороты.НДСОборот - РеализацияТМЗОбороты.АкцизОборот)/РеализацияТМЗОбороты.КоличествоОборот КАК Сумма1"; Пробую через СУММА(РеализацияТМЗОбороты.КоличествоОборот), но для этого нужно прописывать СГРУППИРОВАТЬ ПО, вот и не пойму куда ее вписать :) Прошу прощения за бестолковое разъяснение, но все же надеюсь вы поняли о чем я пытаюсь спросить Всем привет! Вопрос таков, как опустить Итоги в запросах вниз табличной части. Код: ЗапросТЧ.Текст = "ВЫБРАТЬ | РасходТаблРасход.НомерСтроки КАК НомерСтроки, | РасходТаблРасход.Товар КАК Товар, | СУММА(РасходТаблРасход.Количество) КАК Количество, | РасходТаблРасход.Единица, | СУММА(РасходТаблРасход.Цена) КАК Цена, | СУММА(РасходТаблРасход.Сумма) КАК Сумма, | РасходТаблРасход.НДС |ИЗ | Документ.Расход.ТаблРасход КАК РасходТаблРасход |ГДЕ | РасходТаблРасход.Ссылка = &ТекДок | |СГРУППИРОВАТЬ ПО | РасходТаблРасход.НомерСтроки, | РасходТаблРасход.Товар, | РасходТаблРасход.Единица, | РасходТаблРасход.НДС | |УПОРЯДОЧИТЬ ПО | НомерСтроки [font=Verdana] |ИТОГИ | СУММА(Сумма) [/font] |ПО | ОБЩИЕ"; В таблицу по циклу выгружаются данные из запроса, а сверху выходить итоговая сумма по колонке Сумма. Как этот итог опустить вниз таблицы? Можно ли как-то "Итог" присвоить какой-нибудь переменной, чтобы ее потом в параметр печатной области вставить? спс за внимание! - Программирование :: Программирование 1С :: 1С 7.x
Здравствуйте, в 1с v7 Торговля и склад, в справочнике цен делаю полное наполнение по группе товаров, проходит расчет остатков--и останавливается на такой ошибке Код: Документ = ДвижениеРегистраОстатков № 105 от 31.12.09 Если Запрос.Товар=Док1.Товар {Справочник.Цены3.ФормаСписка.ФормаСписка.Модуль(1190)}: Поле агрегатного объекта не обнаружено (Товар) Подскажите в чем проблема пожалуйста?! - Операционные системы :: Windows
В ХР не работает связь модема и компа,если модем настроен роутером,самопределяет IP,а в 2000 и в 7 работает,в чем может быть дело? - Направления программирования :: Drivers
ObOpenObjectByName() возвращает код ошибки 0хс0000024 : Код: RtlInitUnicodeString(&obj_name, L"\\Device\\Tcp"); InitializeObjectAttributes(&objAttr, &obj_name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); status = ObOpenObjectByName(&objAttr, NULL, KernelMode, NULL, NULL, NULL, &hObject); if (!NT_SUCCESS(status)) { DbgPrint("[Driver entry]: ObOpenObjectByName error!\n %x",status); } Поможет кто-нибудь понять в чём дело? - Направления программирования :: Web
Добрый день, уважаемые! Много букв, но по другому не получается...
Разрабатываю тизерную сеть, и вот столкнулся с такой проблемой...
Оказывается очень распространено сейчас - накрутка различных тизерных/баннерных/рекламных сетей. При чем делается это очень различными способами. Веб-мастара кликают по своим тизерам на своих сайтах и получают бабло, а у рекламодателей деньги на ветер, конверт покупок нулевой.
Хотелось бы услышать методы борьбы с такими накрутчиками...
Понятно что первое приходит на ум - это установка cookies на время, далее блокировка по хэшу IP + User_agent, или возможно просто по IP на какое-то время. Непринимать траф с известных IP-proxy, анонимайзеров, учитывать геотаргетинг, это все понятно.
Но как мы знаем - cookies - это не проблема, User_agent, HTTP_REFERER - это всего лишь заголовки и легко меняются.
А по поводу IP - здесь тоже есть особые технологии...
Уже давно есть такие системы, называемые САР - Системы Активной Раскрутки, когда за кредиты (выкупаются за ничтожные деньги) вы можете отдавать на раскрутку свой сайт, когда часть пользователей этой САР смотрят ваш сайт около минуты и получают деньги.
Но также есть разработки "продвинутых САР", которые отличаются вот чем:
- особые технологии просмотра сайта через Flash позволяют полностью скрыть, что просмотр идет с САР - есть набор определенных команд, которые может исполнять эта САР.
Можно выставить сайт в режим автосерфинга, тогда пользователям даже не нужно смотреть сайт, можно свернуть браузер (или программу), и будут автоматически просматриваться сайты рекламодателей этой САР, но команды будут работать.
По поводу команд - это, допустим, вставить любой JS-код, при просмотре через САР. Таким образом JS-код может найти через DOM нужные ссылки на тизеры, и кликнуть случайно в 5% случаях допустим... Или даже сгенерить iframe динамически и подгрузить этот линк...
Еще есть команды - навести курсор в определенные координаты, кликнуть по объекту. Т.е. полная имитация действий пользователя
Нашел людей, которые помогают настроить эти команды, скрипты... Накручивают легко даже Goggle Adsense, РСЯ Директ. И вообще, способов борьбы с этим, как я понимаю просто не существует!
Единственные вещи, которые приходят на ум:
1) при открытии сайта рекламодателя (клик на тизере) делать что-то типа простой нераздражающей каптчи, и только потом переход на сайт рекламодателя и засчет как клик
2) сделать инструмент, позволяющий рекламодателям отслеживать, с каких сайтов был переход на их сайты, и чтобы они анализировали конверт покупок. Допустим с определенных площадок, доход не идет, и заносили эти сайты в блэк-лист (в случае нахождения сайта во многих блэк-листах - возможен бан)
1 - раздражать будет посетителей, а также опять будут придумывать средства как это обойти... Хотя каптча какая-нибудь на флэш - автоматом не обойдется, но будет раздражать... И также найдутся другие способы - сервисы с оплатой за задания - зайди, кликни, введи каптчу... 2 - сложно в реализации, т.к. рекламодатели не всегда рекламируют свои сайты, а допустим ПП (партнерские программы), но они не всегда предоставляют детальную статистику - по каким УРЛ-ам был переход...
Хотелось бы услышать ваше мнение. У кого какие мысли по этому поводу?
Спасибо.
А теперь прощаемся с Вами до следующего выпуска. С уважением, команда Клуба. |
| | | | Камкордер Panasonic HDC-SD800: Full HD и 3D-видео у вас в кармане Лето, пора отпусков и путешествий, – лучшее время для покупки цифровой видеокамеры. Как выбрать камкордер, который будет свидетелем Ваших приключений и просто приятных моментов жизни не один год? Решение предлагает Panasonic. Это камера HDC-SD800 с возможностью снимать FullHD и 3D-видео. Узнай больше!
| Видеокамера Panasonic HDC-SD800 – на память в FullHD Как сохранить приятные впечатления отпуска? Ответ - снять лучшие моменты на видеокамеру. Теперь это можно сделать в высоком качестве, достойном уровня профессионалов. Камкордер Panasonic HDC-SD800, обладая компактным размером и лёгкостью, позволяет снимать FullHD и 3D-видео. Что еще? Узнай!
| Нужен ли кондиционер в детской комнате? Если это новый Panasonic CS-HE9MKD, то да. Функции Econavi и AUTOCOMFORT обеспечат оптимальный микроклимат для Вашего ребёнка и помогут избежать простуд. А инновационная система очистки воздуха e-ion APS предотвратит распространение аллергенов. Узнайте больше!
| | Внимание! Некоторые из следующих ссылок позволяют войти в кабинет подписчика без знания пароля. Не передавайте никому это письмо во избежание несанкционированного доступа к Вашему личному кабинету на проекте Рассылки@Mail.Ru. |  | Сообщить о нарушении данной рассылкой правил Сервиса
| | Отказаться от получения данной рассылки: нажмите здесь или отправьте это письмо | |
Комментариев нет:
Отправить комментарий