Запретить вызовы произвольных функций / классов во внешнем коде

12

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

Например, в приложении SharePoint может показаться естественным вызывать spList.Items.GetItemByIdэлемент списка, даже если он находится в цикле, не осознавая, что это может привести к огромным проблемам с производительностью.

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

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

Alex
источник
11
Это звучит как принуждение к экстремальной форме стиля кодирования (запрещено использовать определенный библиотечный вызов). Так что для меня это ставит предварительный вопрос: делаете ли вы какие-либо обзоры кода или проверки стиля в первую очередь?
Питер М
3
Вы надеетесь перехватить и заблокировать эти вызовы во время выполнения или во время компиляции ?
MetaFight
1
Поскольку вы используете C #, вы когда-нибудь слышали о StyleCop ? Вы знаете, что можете создавать собственные правила по своему усмотрению, верно?
Мачадо
10
« Существуют ли надежные и достаточно простые способы достижения этих ограничений для внешнего кода, кроме как в определенных местах в нашем собственном коде? ». Да: напишите свой собственный Roslyn Analyzer, чтобы сообщить о доступе к определенным API как об ошибке компиляции.
Дэвид Арно
3
@Machado, StyleCop - фактически мертвый продукт. Его заменяют StyleCopAnalyzers, который построен поверх Roslyn. Это определенно не будет хорошей идеей, чтобы тратить время на написание пользовательских правил StyleCop в эти дни.
Дэвид Арно

Ответы:

8

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

Поскольку речь идет конкретно о C #, существует решение на основе компилятора, которое можно использовать здесь для обеспечения соблюдения таких правил: Roslyn Analyzers . Вы можете написать свой собственный анализатор, который сообщает о доступе к определенным API как об ошибке компиляции или предупреждении.

Примером набора анализаторов, которые предоставляют множество примеров кода при написании собственного, являются анализаторы StyleCop , которые являются заменой старой функции StyleCop для C #.

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

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

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

Например, у нас есть несколько сервисов, написанных на Scala, и одна из вещей, которые мы просим во время проверки кода, - это неизменность, но мы часто сообщаем об этом, как об избавлении от vars. Кто-то на днях использовал val x: ListBuffer [Boolean] для хранения одной изменяемой переменной как единственного элемента в списке. Вы не можете назначить другое ListBufferна x, но вы можете заменить элементы списка на месте столько, сколько хотите. Так же плохо, как с помощью var, но подлый.

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

Карл Билефельдт
источник
черт, это подлый!
WHN
@snb Это эквивалентно тому, что делает Java в качестве хака, чтобы обойти только возможность вернуть один объект / значение и отсутствие правильных ссылочных аргументов; вместо этого, передав массив, содержимое которого будет обновлено. (Некоторые примеры: AtomicMarkableReference.getа AtomicStampedReference.get).
JAB
Спасибо за ваш ответ, но я определенно не заинтересован в выполнении трудоемких сложных вещей, таких как написание оберток вокруг внешнего кода. Это, вероятно, даже не поможет, поскольку они могут просто перейти к источнику. Этот ответ, кажется, предполагает, что решение будет дорогостоящим и добавит сложности. Как насчет чистого и простого решения?
Алекс
1
@ Алекс - самое простое решение: «ничто не сравнится с обучением и проверкой кода».
Мистер Миндор
2
«Ничто не сравнится с тем, чтобы делать это вручную» - правильно, пока кто-то не автоматизирует это
Эван
0

Ответ Карла на 100% правильный. Нет способа гарантировать соответствие. Однако, в дополнение к обучению и проверке кода, рассмотрите возможность использования инструментов статического анализа для обеспечения соответствия. (Примечание: я сказал «в дополнение к», так как их можно обойти точно так же, как сказал Карл).

Преимущество использования инструментов статического анализа заключается в устранении утомительного анализа человеческого кода в поисках случаев «многократного использования IEnumerable» или любой проблемы с производительностью недели, которую вы просматриваете (или, по крайней мере, я всегда чувствую, что смотря на). Это позволит обзорам кода и обучению сосредоточиться на более «интересных» вопросах.

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

Скопируйте / вставьте прямо со страницы Википедии, используйте вики-страницу для получения самой последней информации и ссылок: https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis#.NET

  • Платформа компилятора .NET (кодовое имя Roslyn) - платформа компилятора с открытым исходным кодом для C # и Visual Basic .NET, разработанная Microsoft .NET. Предоставляет API для анализа и управления синтаксисом.
  • CodeIt.Right - совмещает статический анализ кода и автоматический рефакторинг с лучшими практиками, что позволяет автоматически исправлять ошибки и нарушения кода; поддерживает C # и VB.NET.
  • CodeRush - плагин для Visual Studio, который предупреждает пользователей о нарушениях передового опыта.
  • FxCop - бесплатный статический анализ для программ Microsoft .NET, компилируемых в CIL. Автономный и интегрированный в некоторые выпуски Microsoft Visual Studio; Microsoft.
  • NDepend - упрощает управление сложной базой кода .NET путем анализа и визуализации зависимостей кода, определения правил проектирования, анализа воздействия и сравнения различных версий кода. Интегрируется в Visual Studio.
  • Parasoft dotTEST - плагин статического анализа, модульного тестирования и обзора кода для Visual Studio; работает с языками для Microsoft .NET Framework и .NET Compact Framework, включая C #, VB.NET, ASP.NET и Managed C ++.
  • Sonargraph - поддерживает C #, Java и C / C ++ с упором на анализ зависимостей, автоматическую проверку архитектуры, метрики и возможность добавления пользовательских метрик и средств проверки кода.
  • StyleCop - анализирует исходный код C # для обеспечения соблюдения правил стиля и согласованности. Его можно запустить изнутри Microsoft Visual Studio или интегрировать в проект MSBuild.
Реджинальд Блю
источник
-1

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

Это может (и должно) включать этапы ручного и автоматического просмотра:

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

  • Добавьте проверку в правилах для поиска известных шаблонов. Это может быть сложно написать, но для большого проекта, со временем, может быть полезно. TFS позволяет вам писать правила на C #, а другие системы сборки имеют свои собственные хуки. Подумайте об использовании закрытых сборок, чтобы отклонить проверки, соответствующие шаблону. Да, это замедляет разработку, но после определенного размера и сложности проекта, замедление разработки может быть хорошей вещью.

Авнер Шахар-Каштан
источник
-1

Возможно, компилятор поможет вам перехватывать нежелательные вызовы.

Переименуйте классы / методы кода в своей собственной библиотеке, которые не должны использоваться внешними клиентами библиотеки. Альтернативно сделайте классы / методы внутренними и добавьте внутренние элементы видимыми для тех классов, которым разрешено их использовать.

Внешние пользователи lib получат метод / класс ошибки компиляции, который не найден.

Запрещенные классы / методы из публичных библиотек: создайте то же пространство имен / класс / метод в вашей библиотеке

Внешние пользователи lib получат ошибку компиляции из-за найденного дублирующего класса

[Обновить]

Нет необходимости абсолютно ни при каких обстоятельствах предотвращать доступ к этим методам / классам, например, с помощью отражения или просто какого-то отключения ...

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

k3b
источник
Понизить это не только потому, что это неприятный хак, но и легко обойти с помощью C # (с которым ОП пометил вопрос) с использованием внешних псевдонимов .
Дэвид Арно