Как стать автором
Обновить
56
0

Пользователь

Отправить сообщение
Это вы сейчас так говорите, а в статье ни слова.

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

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

В случае функционального подхода можно представить иерархию функций:
let func1 f =
  let func2 f =
    let funcX f = f + 1
    funcX f;
  func2 f;
   
printfn "%i" (func1 1)

И предположить, что функция funcX сделана другим автором, который потом берет и меняет ее поведение на:
let funcX f = f - 1

В этом случае у нас тоже может все поломаться и без всякого ООП.
К сожалению, написать статью так, чтобы каждый нашел для себя что-то новое и интересное, затрагивая большой круг тем, да еще и в компактном виде, наверное, нереально.
Жаль, что это статья не смогла Вам угодить. Надеюсь, в какой-нибудь другой раз все будет иначе.
Я не понимаю, как Ваш комментарий связан с проблемой изменения существующего поведения, на основе которого реализовано другое поведение.
Если Вы используете чужую процедуру, исходного кода которой у Вас нет и полагаетесь на ее поведение, что произойдет если ее поведение поменяется? У Вас ничего не поломается все равно?
Тоже самое можно сказать и про процедурный подход — если поменять логику работы процедуры, которая используется в других процедурах, то они так же могут поломаться.

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

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

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

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

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

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

Если Вы считаете, что она здесь не нужна, то стоит применить тот подход, который на Ваш взгляд будет наилучшим. Я обеими руками за то, чтобы подходы и инструменты применялись разумно, а не бездумно.
— Переопределяя очередной метод в большой иерархии, программист не может быть уверен, что не нарушит деятельность объекта на каком-то уровне

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

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

Описание всех этих аспектов, пускай и в компактном виде, но в одном месте — было одной из целей данной статьи.
И было бы здорово перенять положительный опыт и рисовать классы и методы в UML.

Спасибо за замечание, учту на будущее.
У вас похожий подход, «XACML простой», а затем, предположительно, многостраничное пояснение «простых моментов» :)

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

Например, PolicySet может содержать вложеный PolicySet, который в свою очередь является «контейнером» для других PolicySet'ов и т.д., соответственно финальная иерархия будет достаточно сложной для понимания (на каждом уровне свой combining algorithm и т.д.)


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

Все еще легко? Тогда насколько хорошо вы сможете объяснить факт существования следующей таблицы? :)


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

Мы ведь говорим о системе, которая может быть life-critical. Соответственно, один из вопросов: сможет ли Администратор быть на все 100% уверен в своем наборе политик проведя несколько «точечных» тестов с несколькими контекстами?

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

Основное отличие в том, что Oracle заранее не знает, какие значения у лидирующего столбца в индексе, чтобы спускаться по дереву к каждому левому значению, и поэтому не знает где очередное начинается и где заканчивается, поэтому ему нужно отлавливать, когда значение лидирующего в branch-блоках изменяется и брать его уже для прохода по leaf-блокам, а остальные leaf-блоки skip'ает.
В принципе можете прочитать тут и статью и комментарии: richardfoote.wordpress.com/2008/03/10/index-skip-scan-does-index-column-order-matter-any-more-warning-sign/


Спасибо за пояснение и ссылку, очень познавательно. Я попробовал графически выразить свое понимание принципа работы ISS. Если я ошибся поправьте меня пожалуйста:

— представим что есть составной индекс (CHAR, NUM) и идет поиск строк с условием NUM = 2.
Соответственно при IRS мы будем заходить сразу с верхними и нижними границами по каждому из 10 значений полученных из xt_nums. А Index skip scan, при сработавшем Join elimination, вычитывает весь индекс IX_BIG_TAB, а не спускается по дереву как IRS.

Я предполагал, что INDEX SCIP SCAN (ISS) логически разобьет индекс IX_BIG_TAB на 10 небольших индексов и уже последовательно пройдется по ним, используя access(«T».«DT»>=SYSDATE@!-.01 AND «T».«DT»<=SYSDATE@!). Т.е. сделает подобие IRS 10 раз, и, логически получится тоже самое что и в шагах 3-5 из запроса без join elimination. Но, судя по вашим словам, ISS отработает на подобии INDEX FULL SCAN раз ему придется вычитывать весь индекс IX_BIG_TAB?
Буду очень признателен если Вы поподробнее поясните это.

Вообще-то этот пример я как раз делал на 11.2. У вас, наверное какая-нибудь низкая версия типа 11.2.0.1 — 11.2.0.2 — это заметно по 0 в стоимости INDEX UNIQUE SCAN, насколько помню это в каком-то промежуточном патче было исправлено.

Я пробовал на Oracle 11.2.0.4.0. Параметр optimizer_index_cost_adj = 100 (значение по умолчанию).
Попробовал выполнить запрос используя Ваш хинт, и получил такой же план как и в Oracle 12.1, но его стоимость оказалась выше чем у других планов для Oracle 11.2:
-------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                 |   164 |  4100 |    22   (0)| 00:00:01 |
|*  1 |  FILTER                       |                 |       |       |            |          |
|   2 |   NESTED LOOPS                |                 |   164 |  4100 |    22   (0)| 00:00:01 |
|   3 |    NESTED LOOPS               |                 |   164 |  4100 |    22   (0)| 00:00:01 |
|   4 |     INDEX FULL SCAN           | SYS_C0013510913 |    10 |    30 |     1   (0)| 00:00:01 |
|*  5 |     INDEX RANGE SCAN          | IX_BIG_TAB      |    16 |       |     2   (0)| 00:00:01 |
|   6 |    TABLE ACCESS BY INDEX ROWID| XT_BIG_TAB      |    16 |   352 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
1 - filter(SYSDATE@!>=SYSDATE@!-.01)
5 - access("T"."NUMS_ID"="N"."ID" AND "T"."DT">=SYSDATE@!-.01 AND "T"."DT"<=SYSDATE@!)

Видимо различия в каких-то еще параметрах.
Проверил все планы запросов для Oracle 11.2 получив их через dbms_xplan.display_cursor и все совпало.
Интересный пример, спасибо. Не могли бы Вы его немного прокомментировать?
Если посмотреть на планы запросов в Oracle 12.1:

1) c join eliminate
---------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |            |   164 |  3608 |   167   (0)| 00:00:01 |
|*  1 |  FILTER                              |            |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| XT_BIG_TAB |   164 |  3608 |   167   (0)| 00:00:01 |
|*  3 |    INDEX SKIP SCAN                   | IX_BIG_TAB |   164 |       |   166   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
 1 - filter(SYSDATE@!>=SYSDATE@!-.01)
 3 - access("T"."DT">=SYSDATE@!-.01 AND "T"."DT"<=SYSDATE@!)
      filter("T"."DT">=SYSDATE@!-.01 AND "T"."DT"<=SYSDATE@!)

2) без join eliminate
-----------------------------------------------------------------------------------------------
| Id  | Operation                     | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |               |   164 |  4100 |    22   (0)| 00:00:01 |
|*  1 |  FILTER                       |               |       |       |            |          |
|   2 |   NESTED LOOPS                |               |       |       |            |          |
|   3 |    NESTED LOOPS               |               |   164 |  4100 |    22   (0)| 00:00:01 |
|   4 |     INDEX FULL SCAN           | SYS_C00459678 |    10 |    30 |     1   (0)| 00:00:01 |
|*  5 |     INDEX RANGE SCAN          | IX_BIG_TAB    |    16 |       |     2   (0)| 00:00:01 |
|   6 |    TABLE ACCESS BY INDEX ROWID| XT_BIG_TAB    |    16 |   352 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
 1 - filter(SYSDATE@!>=SYSDATE@!-.01)
 5 - access("T"."NUMS_ID"="N"."ID" AND "T"."DT">=SYSDATE@!-.01 AND 
              "T"."DT"<=SYSDATE@!)


то видно, что действительно, cost второго запроса ниже, не смотря на то, что сам запрос более сложный. Но, получается, что шаги 3-5 во втором случае тоже самое, что и шаг 3 в первом случае и, помимо этого, во втором случае присутствует еще один цикл, в то время как в первом случае происходит batched table access. Почему же cost так сильно отличается и во втором случае он в несколько раз меньше?

Кстати, в Oracle 11.2 запросы получаются немного другие и их cost одинаков:

1) с join elimination
-------------------------------------------------------------------------------------------
| Id  | Operation                    | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |            |   164 |  3608 |    13   (0)| 00:00:01 |
|*  1 |  FILTER                      |            |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| XT_BIG_TAB |   164 |  3608 |    13   (0)| 00:00:01 |
|*  3 |    INDEX SKIP SCAN           | IX_BIG_TAB |   164 |       |    12   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
1 - filter(SYSDATE@!>=SYSDATE@!-.01)
3 - access("T"."DT">=SYSDATE@!-.01 AND "T"."DT"<=SYSDATE@!)
     filter("T"."DT">=SYSDATE@!-.01 AND "T"."DT"<=SYSDATE@!)

2) без join elimination
-------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                 |   164 |  4100 |    13   (0)| 00:00:01 |
|*  1 |  FILTER                       |                 |       |       |            |          |
|   2 |   NESTED LOOPS                |                 |   164 |  4100 |    13   (0)| 00:00:01 |
|   3 |    TABLE ACCESS BY INDEX ROWID| XT_BIG_TAB      |   164 |  3608 |    13   (0)| 00:00:01 |
|*  4 |     INDEX SKIP SCAN           | IX_BIG_TAB      |   164 |       |    12   (0)| 00:00:01 |
|*  5 |    INDEX UNIQUE SCAN          | SYS_C0013510913 |     1 |     3 |     0   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
1 - filter(SYSDATE@!>=SYSDATE@!-.01)
4 - access("T"."DT">=SYSDATE@!-.01 AND "T"."DT"<=SYSDATE@!)
     filter("T"."DT">=SYSDATE@!-.01 AND "T"."DT"<=SYSDATE@!)
5 - access("T"."NUMS_ID"="N"."ID")
Спасибо за подробный ответ.
Вообще, советую прочитать Cost-Based Oracle fundamentals Джонатана Льюиса. Ее просто необходимо прочесть наряду с его же «Oracle Core», если хотите заниматься оптимизацией производительности.

Эти книжки как раз на очереди.
Установил Oracle 10.2, проверил еще раз — трансформация работает с обоими вариантами синтаксиса. Поправил текст в статье, спасибо.
Все-таки, даже судя по документации, у синтаксиса ANSI-соединений больше возможностей, чем у традиционного синтаксиса. На мой взгляд, было бы странно в таком случае приводить запрос к традиционному синтаксису. Тем более, Вы сами отметили, что это происходит не во всех случаях. Но если это действительно так — не могли бы Вы рассказать, в какой момент выполнения запроса происходит это преобразование? И еще больше я был бы признателен за какую-либо ссылку на документацию по этому вопросу.
Спасибо, добавил к статье.
Спасибо за комментарий. Учту на будущее.
Еще раз хочу подчеркнуть, что одних ролей вам оказалось недостаточно и вам пришлось «зашивать» в код те проверки, которые нельзя сделать в RBAC. Если во всей системе у вас будет всего лишь несколько таких проверок и они никогда не будут меняться, то тогда вам действительно будет дешевле использовать RBAC.
Но, если бизнес-требования будут более сложными и будут требовать проверки других атрибутов, такие проверки вам тоже придется «зашивать» в код. Что если вам нужно дать разрешение менять сущность, но некоторым пользователям должны быть доступны для изменения не все атрибуты, а лишь некоторая их часть? И что если вам нужно учитывать не только пользователя, но и время, ip-адрес, или еще какие-либо атрибуты субъекта и объекта, сравнивать их между собой или с динамически вычисляемым значением? Все это тоже придется «зашивать» в код, и у вас появятся все те проблемы, что я пытался показать в статье. А если эти правила еще и постоянно меняются то для их изменения потребуется привлечь программиста, протестировать изменения, выпустить новую версию приложения, обновить ее у заказчика — все это будет долго и дорого.
В случае ABAC инфраструктура просто получает все текущие атрибуты и проверяет их, используя заданные администратором в «текстовом» виде правила, менять которые дешево.
Грубо говоря, где-то на инфраструктурном уровне это может выглядеть, как: accessEngine.Check(action, subject, object, environment).
Об этом более углубленно я постараюсь рассказать в следующей статье, в которой буду разбирать существующий стандарт — XACML.
На вопрос «зачем» — я как раз и пытался дать ответ в этой обзорной статье, и, как мне кажется, это не плохо получилось.
Если вы считаете, что у вас все проще и вам это не нужно, то ABAC для вас будет действительно избыточен. Я не собираюсь вам ничего продавать, это делают другие, если вы изучите ссылки, приведенные в конце статьи, вы увидите интересные, востребованные на рынке примеры.
Я лишь хочу познакомить вас и других читателей с тем, что еще существует, чтобы у вас был выбор при принятии решения.
То что вы описываете — уже не классический RBAC. В RBAC разрешения вешаются только на роли, субъект в определении разрешений не участвует. Тем более, вы предлагаете «хардкодить» роли в виде классов. В ABAC мы просто описываем какими значениями должны обладать те или иные атрибуты для выполнения действия. А их значения вычисляются в момент проверки прав доступа инфраструктурой. Никакого «хардкода».
1

Информация

В рейтинге
Не участвует
Откуда
Москва и Московская обл., Россия
Работает в
Дата рождения
Зарегистрирован
Активность