язык программирования с гранулярным методом и доступом к свойствам - PullRequest
2 голосов
/ 11 августа 2010

представьте что-то вроде этого:

import class B.*;


interface A supports A.testSum
{
   int sum( int a , int b ) access from B.calculator;

   testSum() { Assert(sum(1,1)==2); }

........


class B ...
{
  void calculator() {  A.sum(3,5); //ok }
  void someOtherMethod() { A.sum(0,3); //compile error }

идея «опор» вторична, но актуальна, поскольку в этом случае тест применяется к интерфейсу (поэтому язык будет различать тест интерфейса, которыйвсе реализации должны пройти и тест реализации, который является специфическим для приватности реализации

, но важная идея, которую я хочу передать здесь, - это семантика контроля доступа; обратите внимание, что A.sum с ключевым словом «access from» может толькобыть вызван из метода B.calculator. Все остальное обнаруживается как ошибка времени компиляции. Идея здесь состоит в том, чтобы обеспечить архитектурные ограничения более детальным способом. Если вы не добавили «доступ из» или просто добавили «доступ из»* "это будет означать поведение по умолчанию, позволяющее вызывать метод из любой точки мира. Какие архитектурные ограничения? Хорошо, тот тип, который принудительно применяется вручную при создании многоуровневого проекта: слой A (самый низкий уровень) используется из слоя B (промежуточный уровень), который в свою очередь используется изслой С (высокий уровень).Но уровень B недоступен из уровня A, а уровень C недоступен ни из A, ни из B, но в противном случае он является общедоступным (это может быть то, к чему у конечного пользователя будет прямой доступ)

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

Обновление: есть еще один действительно важный вариант использования для такого рода ограничений:

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

, поэтому, например, можно определить, что обработчик событийимеет только определенный набор видимых классов, с которыми он может взаимодействовать (или, наоборот, с определенным набором объектов, к которым он не может прикоснуться)

Ответы [ 3 ]

2 голосов
/ 15 августа 2010

Это звучит как особый случай модели возможностей объекта .Возможно, есть языки, которые реализуют это каким-то образом.

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

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

1 голос

Java поддерживает что-то почти то же самое.

Прежде всего, видимость полей и методов обеспечивается во время выполнения, непривилегированный код не может обойти это.

Вы также можете создавать свои собственные привилегии и предоставлять их определенным частям кода. Например, чтобы открыть файл, код, который хочет получить доступ к файлу, должен FilePermission для этого файла. Вы можете сделать любое разрешение, какое пожелаете, но можно сделать разрешение с именем SumPermission, которое Calculator проверяет перед суммированием, и предоставлять его только тем классам, которые вы хотите. Защитные домены охватывают разные классы, а не отдельные методы в классах, поскольку целый класс обычно получается из одного источника. Модель на самом деле идет глубже того, что вы предложили. Каждый класс в стеке (включая историю создания потоков), приводящий к проверке безопасности, должен иметь разрешение, поэтому, если какой-нибудь ненадежный код вызывает ваш код с SumPermission, он не пройдёт проверку безопасности. Конечно, это только по умолчанию, когда вы делаете все, что требует разрешений, вы можете использовать блок doPrivileged, чтобы при предстоящей проверке проверять только ваши разрешения вместо ваших и ваших абонентов.

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

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

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

0 голосов
/ 12 августа 2010

Это возможно в Ruby, хотя и с другим синтаксисом. Возьмите следующее:

module T
    def check
        raise unless self.is_a?(Ca)
        raise unless %r{in `good_func'} =~ caller.first #`
        true
    end
end

class Ca
    include T
    def good_func
        check
    end
    def bad_func
        check
    end
end

class Cb
    include T
    def good_func
        check
    end
    def bad_func
        check
    end
end

a = Ca.new
b = Cb.new

a.good_func
=> true
a.bad_func
=> (RuntimeError)

b.good_func
=> (RuntimeError)
b.bad_func
=> (RuntimeError)

При использовании модуля в качестве дополнительного модуля, self соответствует классу, include s для модуля. caller возвращает текущий стек вызовов, а caller.first возвращает первую запись в стек вызовов (то есть функцию, которая вызвала этот вызов).

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