понедельник, 29 августа 2016 г.

Обработка уведомлений с подтверждениями в Битрикс



Всем привет!
В последнее время приходится программировать под Битрикс “Корпоративный портал”. Впечатления весьма неоднозначные. Нет в этой системе той стройности и упорядоченности, как например  в фреймворке Laravel,  в коде компонентов редко используется ООП,  часто шаблоны компонентов пестрят жуткой смесью из PHP, JavaScript и html–кода.  Как сказано в одной замечательной критичной к Битрикс статье, "документация по Битрикс отстает от кода системы на 1 – 1.5 года”. Поэтому приходится залезать в дебри системных классов Битрикс и изучать все самостоятельно.
Недавно мне поступило задание реализовать следующий алгоритм на портале:


  1.  Постановщик создает задачу для ответственного.
  2. Ответственный должен открыть карточку задачи  и отредактировать крайний срок для исполнения данной задачи
  3. Постановщику должно придти сообщение с указанием данного крайнего срока и кнопками “Принять” и “Отменить”
  4. Если постановщик принимает крайний срок по задаче, то данное поле блокируется для редактирования и ответственный начинает решать задачу, иначе  - ответственному приходит сообщение о том, чтобы он предложил другой крайний срок





Алгоритм достаточно простой и понятный. Отсылка сообщений должна происходить через веб-мессенджер портала.   Основная сложность здесь – это отсылка постановщику сообщения для подтверждения или отмены и соответственно обработчик нажатия кнопок “Принять” или “Отменить”. Погуглив, я понял, что не все так просто. Вот эта статья от разработчика Битрикс https://dev.1c-bitrix.ru/community/blogs/hazz/im-post-one.php объясняет, как отсылать такое сообщение, требующее подтверждения. Однако в качестве обработчика нажатия кнопок предлагается использовать код своего самописного модуля. Модуль должен быть зарегистрирован следующей функцией.
 
RegisterModuleDependences("im", "OnBeforeConfirmNotify", 
"yourmodule","CYourModuleEvents", "CYourModuleEventsIMCallback");




Как? Неужели для этого я должен писать свой собственный модуль?
Однако выяснилось, что есть альтернатива – функция AddEventHandler, которая регистрирует обработчик события. Отличие данного регистратора события от RegisterModuleDependences в том, что последний сохраняется в базе данных и работает с событиями в модулях.
Итак, вызов функции для отправки сообщения с подтверждением в коде компонента bitrix:task.task.edit :



$mdeadline=ConvertDateTime($arFields["DEADLINE"], "DD.MM.YYYY", "ru"); 
$notify="Задача № {$arParams['TASK_ID']} будет выполнена до {$mdeadline} включительно. Прошу нажать  'Принять', если согласны, и мы приступим к решению данной задачи";
$buttons=Array(
// 1. название кнопки, 2. значение, 3. шаблон кнопки, 4. переход по адресу после нажатия (не обязательный параметр)
Array('TITLE' => 'Принять', 'VALUE' => 'Y', 'TYPE' => 'accept' /*, 'URL' => 'http://test.ru/?confirm=Y' */),
Array('TITLE' => 'Отказаться', 'VALUE' => 'N', 'TYPE' => 'cancel' /*, 'URL' => 'http://test.ru/?confirm=N' */),
);
CMessagesHelper::SendConfirmNotify($arTask['RESPONSIBLE_ID'],$arTask['CREATED_BY'],
'tasks',"tasks|CONFIRM_DEADLINE|{$arParams['TASK_ID']}|{$arTask['RESPONSIBLE_ID']}|{$arTask['CREATED_BY']}|{$task_path}",
$notify,'',$buttons,'');

Функция класса-хелпера для отсылки сообщения с подтверждением:


public static function SendConfirmNotify($from,$to,$module,$tag,$message,$message_email,$buttons,$email_template)
{
if (IsModuleInstalled("im") && CModule::IncludeModule("im"))
{
 $arMessageFields = array(
     // получатель
     "TO_USER_ID" => $to,
     // отправитель
     "FROM_USER_ID" => $from, 
     // тип уведомления
     "NOTIFY_TYPE" => 1,
     // модуль запросивший отправку уведомления
     "NOTIFY_MODULE" => $module,
     // символьный тэг для группировки (будет выведено только одно сообщение), если это не требуется - не задаем параметр
     "NOTIFY_TAG" => $tag,
     // текст уведомления на сайте (доступен html и бб-коды)
     "NOTIFY_MESSAGE" => $message,
     // текст уведомления для отправки на почту (или XMPP), если различий нет - не задаем параметр
     "NOTIFY_MESSAGE_OUT" => $message_email,
     // массив описывающий кнопки уведомления
     "NOTIFY_BUTTONS" => $buttons,
     // символьный код шаблона отправки письма, если не задавать отправляется шаблоном уведомлений
     "NOTIFY_EMAIL_TEMPLATE" => 
     $email_template,
 );
 return CIMNotify::Add($arMessageFields);
}
}

А вот необходимый обработчик нажатия кнопок в уведомлении, который располагается в файле bitrix/php_interface/init.php:

AddEventHandler("im", "OnAfterConfirmNotify", "OnAnswerNotifyHandler");

function OnAnswerNotifyHandler($module,$tags,$value,$arRes,$resultMessages)
{

if (IsModuleInstalled("im") && CModule::IncludeModule("im") && CModule::IncludeModule("tasks"))
{ 
if($module=='tasks' && !empty($tags))
{
 $tag_ar=explode ('|',$tags);

 if($tag_ar && $tag_ar[1]=='CONFIRM_DEADLINE')
 {
 $task_id=$tag_ar[2];
 if(!$task_id) return;
 
 $responsible_id=$tag_ar[3];
 if(!$responsible_id) return;
 
 $author_id=$tag_ar[4];
 if(!$author_id) return;
 
    $task_path="/company/personal/user/{$responsible_id}/tasks/task/view/{$task_id}/";
    
    function ChangeDeadLineCounter($val,$task_id)
    {
        global $USER;
        $loggedInUserId = (int) $USER->getId();
            //отмечаем, что автор ответил на запрос
        $oTask = CTaskItem::getInstanceFromPool($task_id, $loggedInUserId);
        if(!$oTask) 
            return false;
        $arTask = $oTask->getData();


        if(!$arTask) 
            return false;

        //уменьшаем счетчик, чтобы можно было еще раз поменять крайний срок
        if(!empty($arTask['UF_DEADLINE_COUNTER']))
            $arTask['UF_DEADLINE_COUNTER']+=$val;

        if($arTask['UF_DEADLINE_COUNTER']<0 artask="" otask-="">update(array('UF_DEADLINE_COUNTER'=>$arTask['UF_DEADLINE_COUNTER']));
        return true;
    }
         
 if($value=='Y')
 {
 //инициатор подтвердил крайний срок
   $arMessageFields = array(
            "TO_USER_ID" => $responsible_id,
            "FROM_USER_ID" => $author_id,
            "NOTIFY_TYPE" => IM_NOTIFY_SYSTEM,
            "NOTIFY_MODULE" => "tasks",
            "NOTIFY_TAG" => "",
            "NOTIFY_MESSAGE" => "Уважаемый сотрудник! Инициатор задачи № {$task_id} подтвердил установленный Вами крайний срок. Можете приступать к исполнению.",
            "MESSAGE_TYPE" => "S"
        );

    ChangeDeadLineCounter(1,$task_id);
            //echo mydump($arMessageFields);
 
 }
 else
 {

 //инициатор не подтвердил крайний срок - высылаем уведомление ответственному
      $arMessageFields = array(
            "TO_USER_ID" => $responsible_id,
            "FROM_USER_ID" => $author_id,
            "NOTIFY_TYPE" => IM_NOTIFY_SYSTEM,
            "NOTIFY_MODULE" => "tasks",
            "NOTIFY_TAG" => "",
            "NOTIFY_MESSAGE" => "Уважаемый сотрудник! Инициатор задачи № {$task_id} не подтверждает Ваш крайний срок по данной задаче. 
            Редактирование крайнего срока вновь доступно в карточке задачи. Скорректируйте крайний срок еще раз.",
            "MESSAGE_TYPE" => "S"
        );
 
    ChangeDeadLineCounter(-1,$task_id);
 }
    $notifyID = CIMNotify::Add($arMessageFields);

 }
}
}

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

пятница, 15 апреля 2016 г.

Быстрый доступ к коду функций при работе в PgAdmin

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

PgAdmin, к сожалению, такими возможностями не обладает. Раньше, для просмотра кода функции мне приходилось искать  соответствующий файл среди своих исходников в git-репозитории. Если файл не находился по наименованию - приходилось выполнять полнотекстовый поиск с помощью Far. Однако с добавлением удобнейшего запроса в макросы PgAdmin уже не приходится осуществлять такой поиск.

Указанный ниже запрос выдает следующие столбцы:
  • sql_text - команда вызова функции (если понадобится вызвать функцию со своими аргументами)
  • Schema - схема, где находится функция
  • Name - наименование функции
  • Result data type - результирующий тип данных функции
  • Argument data types - входные переменные для функции
  • Function text - полный код функции 
  • Argument data types without defaults - входные аргументы функции без значений по-умолчанию
  • Type - тип функции (agg - агрегатная, window - оконная функция, trigger - триггерная функция, normal - обычная функция)
SELECT
'select ' || n.nspname || '.' || p.proname || 
'(' || pg_catalog.pg_get_function_arguments(p.oid) || ') for update;'
 as sql_text,
n.nspname as "Schema",
  p.proname as "Name",
  pg_catalog.pg_get_function_result(p.oid) as 
"Result data type",
  pg_catalog.pg_get_function_arguments(p.oid) as 
"Argument data types",
  pg_get_functiondef(p.oid) as "Function text",
  pg_get_function_identity_arguments(p.oid) as 
"Argument data types without defaults",
 CASE
  WHEN p.proisagg THEN 'agg'
  WHEN p.proiswindow THEN 'window'
  WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype 
THEN 'trigger'
  ELSE 'normal'
 END as "Type"
FROM pg_catalog.pg_proc p
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE
(p.proname ilike '%' || trim('$SELECTION$') || '%') ORDER BY 1, 2, 4;
Пример работы функции:
После введения данного макроса стало намного проще анализировать код. 
Не нужно искать в исходниках или в дереве PgAdmin текст функции - проще вспомнить ее примерное наименование, написать его, выделить и выполнить макрос.
В появившейся таблице в поле function text достаточно будет скопировать текст и вставить в отдельное окно редактора, чтобы произвести анализ. 
Работа над проектом из-за этого макроса значительно ускорилась.







вторник, 2 февраля 2016 г.

5 полезных приёмов для программиста PostgreSQL





1. СТРОГОЕ  СРАВНЕНИЕ ЗНАЧЕНИЙ В ЗАПРОСАХ

Есть к примеру запрос, который обновляет некоторые поля данными из исходной таблицы в случае их отличия от данных в таблице назначения:


update dest
set
name=src.name
from src
where dest.id=src.id
and
dest.name<>src.name;


Проблема заключается в том, что одно из полей name в таблицах dest или srcможет быть NULL, а следовательно не может обрабатываться оператором сравнения <>. В таком случае поле в таблице назначения src обновлено не будет.Раньше для решения этой проблемы я пользовался функциeй проверки значения на NULL - coalesce. Мой код выглядел неоптимально:


update dest
set
name=src.name
from src
where dest.id=src.id
and
coalesce(dest.name,'')<>coalesce(src.name,'');

Если обновление происходит для нетекстового поля, то вместо приведения к пустой строке в случае NULL, нужно приводить к 0. Пример:

update dest
set
numcol=src.numcol
from src
where dest.id=src.id
and
coalesce(dest.numcol ,0)<>coalesce(src.numcol ,0);

Постоянно писать проверку на NULL для каждого обновляемого поля утомительно.
Поэтому я открыл для себя  оператор  IS DISTINCT FROM.
Данный оператор по своей функции схож с оператором <>, и возвращает true, если правая и левая части разные и false, если они одинаковые ( с учетом NULL в этих значениях).
Оператор IS NOT DISTINCT FROM похож на оператор =, но также учитывает с NULL.

Проиллюстрирую работу этих операторов на примерах:

select NULL IS DISTINCT FROM  NULL; --Результат false
select NULL IS NOT DISTINCT FROM  NULL; --Результат true
select NULL IS NOT DISTINCT FROM  10; --Результат false
select NULL IS NOT DISTINCT FROM  'abc'; --Результат false
select 10 IS NOT DISTINCT FROM  10; --Результат true
select 'abc' IS DISTINCT FROM  'abc'; --Результат false


Таким образом, оптимизируя код первого запрос, я написал следующее:

update dest
set
name=src.name
from src
where dest.id=src.id
and
dest.name IS DISTINCT FROM  src.name;


IS DISTINCT FROM или IS NOT DISTINCT FROM следует использовать вместо <> или = там, где в сравниваемых значениях возможны NULL.


2. ЗАМЕДЛЕНИЕ РАБОТЫ ЗАПРОСА


Иногда при работе некоторых функций возникает взаимоблокировка транзакций (deadlock).  
По логам видно, что 2 функции вызвали взаимоблокировку. При этом одна из них может достаточно быстро отрабатывать свою задачу и запустив их в разных окнах PgAdmin можно не получить deadlock.  В таких ситуация возникает потребность замедлить работу функции или запроса. 
Так я открыл для себя функцию pg_sleep(nsec). Функция замедляет выполнения запроса, на nsec секунд. Таким образом, чтобы замедлить мою исходную тестируемую функцию MyFunc на 10 секунд можно выполнить следующий код:

select *,pg_sleep(10) from MyFunc();



3. РЕАЛИЗАЦИЯ ЗАПРОСОВ В ФУНКЦИЯХ В ЗАВИСИМОСТИ ОТ ЗНАЧЕНИЙ ВХОДНЫХ ПАРАМЕТРОВ ФУНКЦИИ



Представим себе функцию CountOfGoodsByBrandID, которая на вход принимает параметр v_brand_id. Назначение функции - вычислять количество товаров в таблице goods, принадлежащих указанному бренду-параметру.
Однако если функция принимает в качестве v_brand_id=0, то необходимо выдать общее количество товаров.
Напишем код функции с учетом этого нюанса:

create or replace function public.CountOfGoodsByBrandID(v_brand_id int default 0)
RETURNS int
security definer
as $$
declare
result int;
BEGIN

if v_brand_id<>0 then
select count(1) into result from goods where brand_id=v_brand_id;
else
select count(1) into result from goods;
end if;

return result;
END;
$$ language plpgsql;

Для поддержки различной логики в зависимости от значения v_brand_id приходится реализовывать громоздкую 
конструкцию:

if v_brand_id<>0 then
select count(1) into result from goods where brand_id=v_brand_id;
else
select count(1) into result from goods;
end if;

помимо длинной реализации проблема заключается в потенциальной возможности усложнения кода за счет появления  еще одного   входного параметра, который как может иметь какое-либо значение, или же можеть быть NULL. Добавим в функцию входной параметр v_is_domestic (значение 1 -  товар отечественный, 0 - импортный, NULL - выборка всех товаров). Тогда реализация логики выбора запроса будет следующей:

if (v_brand_id<>0 and v_is_domestic is not null) then

select count(1) into result from goods
where brand_id=v_brand_id and is_domestic=v_is_domestic;

ELSIF (v_brand_id<>0 and v_is_domestic is  null) then

select count(1) into result from goods
where brand_id=v_brand_id;

ELSIF (v_brand_id=0 and v_is_domestic is not null) then

select count(1) into result from goods
where is_domestic=v_is_domestic;

ELSIF (v_brand_id=0 and v_is_domestic is  null) then

select count(1) into result from goods;

end if;

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

1)
select count(1) into result from goods
where
((brand_id=v_brand_id and v_brand_id<>0) or (v_brand_id=0))
and
((is_domestic=v_is_domestic and v_is_domestic is not null) or (v_is_domestic is null));
;


Количество кода существенно сократилось. Вся логика обработки параметров функции перешла в тело запроса.
В качестве альтернативы данному запросу можно написать запрос с использованием оператора CASE:

2) 
select count(1) into result from goods where
case
when (v_brand_id=0 and v_is_domestic is null) then 1=1
when (v_brand_id<>0 and v_is_domestic is null) then brand_id=v_brand_id
when (v_brand_id=0 and v_is_domestic is not null) then is_domestic=v_is_domestic
else
brand_id=v_brand_id and is_domestic=v_is_domestic
end;


Он длинее, чем предыдущий, и более понятен. Однако для профессионального программирования функции с поддержкой различных значений параметров я использую реализацию 1 (см. выше).
Таким образом, наша функция после оптимизации логики будет иметь следующий вид:
drop function if exists public.CountOfGoodsByBrandID(int,int);
create or replace function public.CountOfGoodsByBrandID(v_brand_id int default 0,v_is_domestic int default NULL)
RETURNS int
security definer
as $$
declare
result int;
BEGIN

select count(1) into result from goods where
((brand_id=v_brand_id and v_brand_id<>0) or (v_brand_id=0))
and
((is_domestic=v_is_domestic and v_is_domestic is not null) or (v_is_domestic is null));


return result;
END;
$$ language plpgsql;



4. КОНКАТЕНАЦИЯ ЗНАЧЕНИЙ ПАРАМЕТРОВ В ДИНАМИЧЕСКОМ SQL 


В своих функциях я часто использую динамически формируемые запросы. Значения в текст таких запросов добавляются с помощью оператора конкатенации  (||)

Пример:

EXECUTE 'SELECT id,name,brand_id from public.goods where brand_id=' || v_brand_id::text || ' and is_domestic=' || v_is_domestic::text || ';'

Код запроса здесь соседствует с параметрами и при увеличении количества параметров или текста кода запроса  возрастает сложность поддержки. Хотелось бы функцию, позволяющую отделить текста запроса от подставляемых в него значений, как например sprintf в PHP. И такая замечательная функция есть (format) , вот реализация формирования динамического sql c ее помощью:

EXECUTE format('SELECT id,name,brand_id from public.goods where brand_id=%s  and is_domestic=%s;',v_brand_id::text,v_is_domestic::text);

Благодаря format, поддержка и понимание кода упрощается.


5. ВЫПОЛНЕНИЕ ФУНКЦИЙ ПОД ПРАВАМИ СОЗДАТЕЛЯ


Иногда приходится модифицировать код sql или pl/pgsql -функций и выкладывать их на рабочем сервере, для того, чтобы пользователи сайта могли запускать данные функции. Конечно пользователи запускают функции не напрямую, а делая запросы к сайту, взаимодействуя с интерфейсом сайта.

Сайт подключен к БД под учеткой с ограниченными правами. Это делается для того, чтобы злоумышленники, найдя дыру в безопасности сайта, не смогли провести атаку типа sql-injection.
Функции же создаются и обновляются под учеткой с админскими правами на сервере Postgresql.
Когда учетка сайта обращается к данной функции - возникает ошибка доступа. Даже если владельцем функции назначена учетка сайта, то все равно возникает проблема, т.к. функция при выполнении может использовать таблицы и другие объекты, доступ к которым для учетки сайта закрыт.
Поэтому, чтобы избежать таких ошибок с правами учетки, я все функции создаю и обновляю с директивой SECURITY DEFINER.
Данная директива говорит о том, что права на доступ к объектам БД функция при работе берет не от запустившей ее учетки, а от создавшей ее учетки.

CREATE FUNCTION see_goods() RETURNS SETOF goods AS $$

SELECT * FROM goods

$$ LANGUAGE SQL SECURITY DEFINER;


Таким образом, запустить функцию может ограниченная в правах учетка, а выполняется функция с правами админа. Если код в функции некритичен и 
подделка запроса внутри нее невозможна, то SECURITY DEFINER - вполне безопасная и удобная директива для развертывания функций.

четверг, 29 октября 2015 г.

Знаменитый философ Бертран Рассел размышляет о человеческом счастье


Интервью ученого и философа Бертрана Рассела для телерадиокомпании BBC





ИНТЕРВЬЮ УЧЕНОГО И ФИЛОСОФА БЕРТРАНА РАССЕЛА BBC.

 

ТЕМА ИНТЕРВЬЮ – СЧАСТЬЕ. СОСТАВЛЯЮЩИЕ СЧАСТЬЯ ЧЕЛОВЕКА ПО МНЕНИЮ Б. РАССЕЛА.

 

В у д р о У а й э т т

 

Лорд Рассел, Вы кажетесь очень счастливым человеком. Вы всегда

были таким?

 

Л о р д Р а с с е л

 

Нет, конечно, нет. У меня были периоды счастья и периоды несчастья. К моей радости, кажется, что чем старше я становлюсь, тем длиннее становятся периоды счастья.

 

Какой был у Вас самый худший, несчастливый период?

 

Я был очень, очень несчастен в юности. Я думаю, как и многие подростки. У меня не было друзей, никого, с кем бы я мог поговорить. Мне казалось, что меня все время посещала мысль о самоубийстве и что я с трудом удерживал себя от этого поступка, а на самом деле это была неправда. О, я, конечно, выдумывал, что я очень несчастен, но это было частично вымыслом, который я почерпнул из снов. В моем сне я был действительно очень болен и умирал. Как это ни странно, у моей постели находился профессор Джовет, магистр Баллиол-колледжа и переводчик Платона, чрезвычайно ученый человек и друг нашей семьи. У него был скрипучий голос, и я в моих снах говорил ему

очень сентиментальным тоном: «Ну, в любом случае в этом есть одно удобство: скоро я буду далеко от всего этого». Он спрашивал: «Вы имеете в виду жизнь?» И я отвечал: «Да, я имею в виду жизнь». И он говорил: «Если бы Вы были чуть старше, Вы бы не говорили такую чепуху». Я просыпался и никогда больше не говорил подобных глупостей.

Но когда Вы были счастливы, это было сознательно спланировано или происходило случайно?

 

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

 

Но Вы думаете, это хорошо срабатывает оставлять счастье

на волю случая и импульса?

 

О! Я думаю, в огромной степени это зависит от удачи и также от того, как идет ваша работа. У меня был ужасно несчастливый период (в значительно более позднее время, чем тот, в юности, о котором я говорил), когда я был совершенно поставлен в тупик проблемой, которую я должен был решить прежде, чем продолжать дальше мою работу. Два года я бился над этой проблемой абсолютно без видимого прогресса, и это было очень несчастливое время.

 

Каковы, Вы думаете, составляющие счастья?

 

Я думаю, самые важные — четыре. Возможно, первая из них — здоровье, вторая — достаточные средства, чтобы уберечь вас от нужды, третья — счастливые личные связи и четвертая — успешная работа.

 

А почему здоровье? Почему Вы придаете ему такое важное значение?

 

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

 

 

Как Вы полагаете, то, что вы здоровы, делает вас счастливым,

или то, что вы счастливы, делает вас здоровым?

 

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

 

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

что хорошо выспались, чем тогда, когда Вы спали плохо?

 

О, да, конечно.

 

Мы можем рассмотреть следующую составляющую доход?

Насколько он важен?

 

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

 

Не выльется ли это, однако, в одержимую погоню за деньгами?

 

О, очень легко, и это часто бывает. Вы обнаруживаете, что богатейшие

люди боятся умереть в работном доме. Так часто случается.

 

То есть слишком большие деньги совсем не обязательно приносят

счастье.

Да. Я думаю, деньги — это своего рода минимальное условие, и вам не хочется думать о них слишком много. Если вы думаете о них слишком много, вы начинаете беспокоиться.

 

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

под этим то, что Вы считаете их третьими по приоритету?

 

Нет, нет. Исходя из моего опыта, я должен сказать, что они — это первая необходимость или это первая необходимость после здоровья.

 

Не могли бы Вы немного подробнее объяснить, что вы имеете в

виду?

 

Под личными связями?

 

Да.

 

Я предполагал, что это достаточно очевидно. Это означает дружбу, любовь, связь с детьми, все виды близости, тесных личных связей. Если они не приносят счастья, это делает жизнь довольно сложной.

 

Работа. Теперь, как высоко Вы бы оценили важность успешной работы?

 

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

 

Имеет знамение, какого рода эта работа?

 

Нет, не думаю, что имеет значение, если только это не сомнительная работа. Я полагаю, что если бы я был членом Политбюро, работа была бы немного беспокойной, но...

 

Она могла бы послужить стимулом для кого-то, кому нравятся такого рода вещи.

 

Да, если вам это нравится, то все будет в порядке.

 

Но незначительность или большая значимость того, что вы

делаете это важно?

 

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

 

То, что Вы говорите, по-видимому, предполагает, что кто-то

был бы счастлив быть ленивым, что кто-то был бы очень доволен,

если бы работы было мало?

 

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

 

Если бы Вам сказали, что Вас ждало бы больше удовольствий,

если бы Вы были менее умны, как бы вы реагировали?

 

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

 

Как Вы думаете, философия способствует счастью?

 

Она способствует, если вы интересуетесь философией и хорошо разбираетесь

в ней, но не иначе, как кладка кирпича,., если вы хороший каменщик. Все, в чем вы хорошо разбираетесь, способствует счастью.

 

Каковы факторы, которые препятствуют счастью?

 

Их существует достаточное количество, помимо тех, что являются противоположностями тех вещей, о которых мы говорили. Один из факторов, который препятствует достижению счастья, — это тревога, и в этом отношении я стал гораздо счастливее с годами, когда стал старше. Я беспокоюсь гораздо меньше, и я выработал очень полезную тактику в отношении беспокойства, которая состоит в том, чтобы подумать: «Какая самая худшая вещь, которая может случится?»...

И затем подумать: «В конце концов, это не было бы так плохо спустя сто лет, возможно, это не имело бы значения». После того как вы действительно

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

 

Вы способны исключить беспокойство по желанию?

 

Не полностью, нет, но в очень большой степени.

А где бы Вы бы расположили зависть?

 

О да, зависть. Это ужасный источник несчастья для очень многих людей. Я вспоминаю художника Хейдона, который был не очень хорошим художником, но хотел бы быть им. Он вел дневник и в нем он записал: «Провел несчастное утро, сравнивая себя с Рафаэлем».

 

Не могли бы Вы развить этот вопрос о зависти?

 

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

 

Да, но может ли зависть быть хорошей вещью в том смысле, что если вы завидуете чьей-то работе, потому что вы думаете, что она, возможно, лучше, чем ваша, это может быть стимулом для вас делать вашу собственную работу лучше?

 

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

 

 

Скука... Как важна скука, на Ваш взгляд?

 

Я думаю, она чрезвычайно важна, и я не буду говорить, что она характерна только для человека, поскольку я наблюдал за обезьянами в зоопарке, и мне показалось, что они тоже скучают, но я не думаю, что другие животные скучают. Думаю, это показатель высшего интеллекта, а ее важность довольно велика. Вы можете видеть это из того, что дикари, когда они впервые входят в контакт с цивилизованными людьми, больше всего хотят алкоголя. Они хотят его гораздо больше, чем Библию, или Евангелие, или даже голубые бусы, и они хотят его потому, что на время он уносит прочь скуку.

 

А как преодолевать скуку людям, например девушкам, которые довольно хорошо образованы? Они выходят замуж и им ничего не остается делать, как только присматривать за домом.

 

Это плохая социальная система. Я не думаю, что вы можете изменить ее индивидуальными действиями, но приведенный Вами пример очень важен. Он показывает, что у нас нет должной социальной системы, потому что каждый должен иметь возможность развивать любые полезные способности, какими бы он или она ни обладали.

Современные, высокообразованные женщины после того как они входят

замуж, не имеют такой возможности, но это следствие нашей социальной

системы.

 

 

Насколько понимание мотивов собственных поступков помогает человеку быть счастливым и таким образом избегать самообмана?

 

 

Я думаю, эта помощь велика. Все люди либо ненавидят какого- нибудь человека, либо ненавидят некоторую группу лиц, либо еще что-то, находясь под впечатлением, что в основе их побуждений лежит благородный идеализм. Когда фактически скорее всего это не так. Если они могли бы осознать это, я думаю, что они были бы счастливее.

 

Вы думаете, что многие люди чувствуют себя несчастными, обманывая самих себя?

 

Да, я думаю, очень и очень многие.

 

Как Вы думаете, можно быть счастливым в несчастии, скажем,

в тюрьме? Вы сами там были.

 

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

 

Вы думаете, что легче быть счастливым, например в тюрьме, в ситуации, в которой были Вы, когда Вы думали, что находились в ней за благое дело, чем если бы вы находились в ней, потому что заслужили это?

 

Да, конечно, это так. Я имею в виду то, что если бы они вынесли мне тот же приговор за воровство ложек, я был бы довольно несчастен, потому что я должен был бы чувствовать себя... ну..., я был бы заслуженно опозорен. Но в моей ситуации я не чувствовал себя обесчещенным.

 

 

Просто потому, что это было дело принципа?

 

Да.

 

Как Вы считаете, помогает людям быть счастливыми то, что

у них есть какая-то цель, ради которой они живут?

 

Да, при этом условии они могут более или менее преуспеть. Я думаю, если это цель, которую невозможно достичь, они не будут счастливы. Но если они могут добиваться успеха время от времени, тогда, я думаю, это помогает. И мне кажется, что этот принцип нужно распространять и на другие вещи; так, другие интересы, особенно когда вы становитесь старше, очень важный элемент счастья. Чем более имперсональны ваши интересы и распространяются за пределы вашей собственной жизни, тем меньше вы будете возражать против того, что ваша собственная жизнь придет к своему концу лишь через довольно длительное время. Я думаю, что это очень важный элемент счастья в старости.

 

 

Что Вы думаете обо всех этих формулах, которые люди постоянно

повторяют, как прожить долгую жизнь и быть счастливым?

 

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

Каталог блогов Blogolist