Вообще-то я программирую в 1С, на языке, похожем на Visual Basic. Но мне кажется, что затронутый в этой теме вопрос касается всех языков программирования, т.к. затрагивает проблему, с которой рано или поздно сталкивается программист при работе со сложным кодом.

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

Приведу пример, где после изменений требуется, чтобы выводилась не сумма y и z, а эта сумма, умноженная на некоторый коэффициент c, который вводится на верхнем уровне, в процедуре Top.

Исходный код:

sub Top()
  Middle
end sub

sub Middle()
  y = get1
  z = get2
  Down y, z
end sub

sub Down(y, z)
  echo y+z
end sub

Проблему можно решить передачей дополнительного параметра c, но если цепочка процедур длинная, это вызовет слишком обширные изменения во многих промежуточных процедурах:

sub Top()
  Input c
  Middle c
end sub

sub Middle(c)
  y = get1
  z = get2
  Down y, z, c
end sub

sub Down(y, z, c)
  echo (y+z)*c
end sub

Неплохо, если автор процедуры сделал переменную-структуру k для хранения контекста вызова, куда можно добавлять произвольные поля, тогда задача решается просто:

sub Top()
  Input c
  k = strukt
  k.add "c", c 
  Middle k
end sub

sub Middle(k)
  y = get1
  z = get2
  Down k, y, z
end sub

sub Down(k, y, z)
  echo (y+z)*c
end sub

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

Поэтому на практике я применяю другой подход:

sub Top()
  Input c
  global.add "c", c
  Middle
end sub

sub Middle()
  y = get1
  z = get2
  Down y, z
end sub

sub Down(y, z)
  echo (y+z)*global.c
end sub

Здесь global - это некоторая глобальная структура, которая хранит глобальные данные текущего сеанса пользователя, у каждого пользователя своя. Конкретно в 1С - это параметры сеанса.

Такой подход требует внимательной проверки на реентерабельность, но в целом, довольно часто успешно решает проблему.

Непосредственно методику использовал в двух случаях:

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

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

Что скажете насчет способа? Использовали? Или что можно предложить взамен? А может быть некоторые языки поддерживают такую передачу контекста вызова "играючи"? Хотелось бы взглянуть.